Baixe o app para aproveitar ainda mais
Prévia do material em texto
267 Disciplina: Iniciação à Computação Prof. Augusto Antonio Pinheiro Neto Curso de Licenciatura em Matemática – UFPBVIRTUAL pinheironeto@di.ufpb.br Ambiente Virtual de Aprendizagem: Moodle www.ead.ufpb.br Site da UFPBVIRTUAL www.virtual.ufpb.br Telefone UFPBVIRTUAL (83) 3216 7257 Carga Horária: 60 horas Créditos: 04 Ementa • Componentes básicos de um computador • Linguagem de programação Descrição Nesta disciplina apresentaremos a configuração básica de um computador, de modo que o aluno tenha uma compreensão geral de sua arquitetura. Estudaremos em seguida uma linguagem de programação imperativa, permitindo capacitar o aluno na programação de resoluções de problemas numéricos. Objetivos Ao final da disciplina o aluno deverá ser capaz de: � compreender a arquitetura básica de um computador, � programar as operações de entrada\saída, � programar operações básicas como: atribuição de valores a variáveis ou constantes, permutação de valores entre duas variáveis, uso de acumuladores de soma e de produtos, � programar os diversos tipos de decisão e de repetição (laços), � compreender os principais tipos de dados inerentes à linguagem estudada, � trabalhar com funções (elemento de programação) � elaborar algoritmos de resolução de diversos tipos de problemas numéricos, � programar esses algoritmos 268 Conteúdo Unidade I Componentes básicos de um computador 1. Unidades funcionais básicas 2. Unidades de Entrada e/ou Saída 3. Dispositivos de Entrada de Dados 4. Dispositivos de Saída de Dados 5. Dispositivos de Entrada e Saída de Dados 6. Memória principal 7. Tipos de memória 8. Unidade Central de Processamento Unidade de Controle Unidade de Aritmética e Lógica Registradores Clock 9. Sistemas Operacionais 10. Os arquivos em informática Unidade II Algoritmos 1. Algoritmos 2. Abordagem dividir para conquistar 3. Algoritmo TrocarPneuFurado Refinamento do passo 1 Refinamento do passo 1.5 4. Algoritmo TrocarLâmpadaQueimada 5. Exercícios 6. Solucionando um problema Fases de resolução Fase de implementação 7. Atitude é tudo Unidade III Introdução à programação 1. Conceitos básicos 2. Memória e variáveis 3. Dando nome às variáveis 4. Tipos de variáveis 5. Declarando uma variável 6. Atribuindo valor a uma variável 7. Constantes 269 8. Exibindo o conteúdo de uma variável 9. Recebendo uma entrada 10. Teste Unidade IV Operações aritméticas básicas 1. Primeiros passos 2. A divisão 3. O módulo 4. Cálculo entre variáveis 5. Abreviações: incremento e decremento 6. Outras abreviações 7. A biblioteca matemática 8. Teste Unidade V Praticando entrada e saída 1. Algumas considerações sobre a função scanf 2. Algumas considerações sobre a função printf Unidade VI Estruturas de controle: condicionais 1. A estrutura if ... else O teste if O teste else O teste else if 2. Alguns erros comuns 3. Para melhor compreender as condições 4. A estrutura switch 5. Condições condensadas 6. Teste Unidade VII Estruturas de controle: repetições 1. O laço while 2. O laço do ... while 3. O laço for 4. Teste Unidade VIII Funções 1. Qual o objetivo de uma função? 2. A estrutura de uma função 3. Criando uma função 270 4. Chamando uma função 5. Mais exemplos I. Conversão Celsius/Fahrenheit II. Transformar segundos em horas, minutos e segundos III. Área de um retângulo IV. Um menu 6. Teste Unidade IX Ponteiros 1. Um pouco mais sobre as funções A memória e os endereços Endereço e valor 2. Utilização de ponteiros I. Criar um ponteiro II. Enviar um ponteiro a uma função III. Outro modo de enviar um ponteiro a uma função 3. Um problema estranho? 4. Resumo 5. Teste Unidade X Arrays 1. Os arrays e a memória 2. Declarando um array 3. Como acessar um elemento 4. Atribuindo valores a um array 5. Arrays e ponteiros 6. Listando um array 7. Inicializando um array 8. Passagem de arrays como parâmetros 9. Arrays de duas ou mais dimensões 10. Teste 271 Unidade I – Componentes básicos de um computador Os computadores estão cada vez mais presentes no dia-a-dia dos cidadãos. Mesmo aqueles que não os utilizam diretamente têm essas máquinas ligadas às suas vidas. Basta nascer para que as informações referentes ao novo cidadão passem a fazer parte de algum banco de dados, por exemplo, o do hospital onde a criança nasceu. Ao registrá-la, o pai (a mãe) estará contribuindo para alimentar outro banco de dados, o do cartório de registros civis. Ao iniciar seus estudos oficiais, novas informações serão transferidas para os computadores, desta vez os da escola. E assim será por toda a vida, imagino. A informação deve ser armazenada e disseminada no momento necessário. Seria bom então entender um pouco sobre essas máquinas que nos acompanham por toda a vida. Os computadores são sistemas eletrônicos de processamento de dados, compostos de uma parte física, denominada hardware e de uma parte lógica, denominada software. O hardware é formado por um conjunto de funções lógicas, geralmente associadas a um ou mais equipamentos físicos, capazes de executar determinadas tarefas. Iniciamos os nossos estudos sobre programação apresentando uma noção sobre a configuração básica de um computador. As funções lógicas associadas ao hardware de um computador são geralmente agrupadas em blocos chamados de unidades funcionais. Um computador possui as seguintes unidades funcionais básicas, compostas de circuitos eletrônicos específicos: As unidades de Entrada são blocos funcionais compostos por circuitos eletrônicos com a finalidade específica de transmitir dados do meio exterior para a memória do computador. As unidades de Saída realizam a operação inversa, transmitem dados da memória do computador Iniciação à Computação 1. Situando a temática 2. Problematizando a temática 3. Conhecendo a temática 3.1 Unidades funcionais básicas 3.2 Unidades de Entrada e/ou Saída Entrada Saída CPU UC UAL Registradores Memória Principal Teclado Mouse Leitor de disquete Scanner Tela sensível Leitor de CD, DVD Monitor (Vídeo) Impressora Gravador de disquete Gravador de CD, DVD 272 para o meio exterior. A transmissão física desses dados se dá por meio de dispositivos especiais. Na figura acima são listados alguns dispositivos que têm a finalidade de realizar essas tarefas. Os dispositivos que realizam tarefas relacionadas à função de entrada são conhecidos como dispositivos de entrada de dados. De modo análogo, os dispositivos que realizam tarefas relacionadas à função de saída são conhecidos como dispositivos de saída de dados. Alguns dispositivos são capazes de executar entrada e saída de dados. Exemplos de alguns dispositivos de entrada de dados: teclado, mouse, scanner. Existem outros, como microfone (dispositivo de entrada de som), monitores de vídeo sensíveis ao toque, light-pen, joystick, etc. Os dispositivos mais comuns de saída de dados são as impressoras e os monitores de vídeo. Entretanto, existem outros dispositivos nesta classe como plotters (traçadores de gráfico), projetores, caixas de som, etc. Alguns dispositivos possuem as funções de entrada e saída. Eles são bem conhecidos e podemos citar, por exemplo, leitor/gravador de discos (disquetes, CD’s, DVD’s, etc), 3.3 Dispositivos de Entrada de Dados 3.4 Dispositivos de Saída de Dados 3.5 Dispositivos de Entrada e Saída de Dados Teclado Mouse Impressora Monitor Leitor/Gravador de disquetes Leitor/Gravador de CD’s Scanner projetor Leitor/Gravador de HD’s 273 Por memória, compreende-se todo dispositivo capaz deguardar qualquer dado ou informação. A memória principal de um computador é o local onde estão armazenados os programas e dados que são utilizados durante um processamento. Todo dado ou programa a ser processado deve estar na memória principal do computador. Caso esses dados estejam armazenados em disquetes, Cd’s ou HD’s, será necessário, primeiro, transferi-los para a memória principal. A memória principal do computador possui a característica de ser volátil, isto é, caso o computador seja indevidamente desligado (falta de energia elétrica, por exemplo), todo o seu conteúdo será perdido, ou seja, tornar-se-á inacessível. A memória principal de um computador existe na forma de “pentes de memória” como mostrado nas figuras a seguir. Atualmente, os pentes de memória, mais encontrados, instalados nos microcomputadores são os de 256 MBytes, 512 MBytes, ou 1GBytes. As memórias estão representadas em duas grandes categorias de chips: RAM (random access memory): são chips de memória que podem ser lidos e/ou gravados pela CPU. A memória principal é deste tipo. ROM (read only memory) : são chips de memória que podem apenas ser lidos pela CPU. Uma memória ROM é permanente e sua gravação é feita pelo fabricante do computador, ou pelo fabricante de memórias. Um conjunto específico de programas, necessários à inicialização de um computador, denominado BIOS, localizado na placa mãe do computador, está encapsulado em uma memória deste tipo. A unidade central é o elemento funcional central de todo computador. É o “coração”, ou melhor, o “cérebro” do computador. Nesta unidade são realizadas todas as operações. Todas as informações tratadas pelo computador transitam por esta unidade funcional. A unidade central é também conhecida por CPU (Central Processing Unit), Unidade Central de Processamento e é dividida classicamente em três partes: I - Unidade de Controle, responsável pela extração das instruções da memória do computador e por sua análise. Essa unidade controla dois registros especiais denominados CONTADOR DE INSTRUÇÃO (PC) que contém o endereço de memória da próxima instrução a ser executada e REGISTRO DE INSTRUÇÕES que contém a instrução extraída da memória. É a unidade de controle que gerencia todos os eventos necessários à operação do computador. II - Unidade de Aritmética e Lógica (UAL) controla um conjunto de registros que devem conter os códigos dos operandos e do operador, necessários à realização de uma operação aritmética ou lógica. Exemplos de operações aritméticas: adição, subtração, multiplicação ou divisão de números. Exemplos de operações lógicas: comparação de dois valores alfabéticos, operações envolvendo operadores os booleanos, AND, OR e NOT. 3.6 Memória Principal 3.7 Tipos de memória 3.8 Unidade Central de Processamento Memória DDR2- 533 1GB Memória 256 MB 274 Nos dias atuais, uma CPU está completamente embutida em uma pastilha, denominada chip, de dimensões reduzidas. As primeiras CPUs integradas em um único chip foram a CPU 4004 e a CPU 8008. Hoje esses chips são mais conhecidos no mercado pelo nome de processador ou microprocessador. Em 1974 a Intel fabricou o 8080, o primeiro microprocessador a ser usado em larga escala nos chamados "computadores pessoais". Antes dele, os microcomputadores eram usados apenas em laboratórios científicos, em fábricas e em universidades. III - Registradores, memórias especiais, de alta velocidade, localizadas no interior de um microprocessador, enquanto a memória principal é externa a este. Cada registrador possui uma função específica. Dentre os registradores destacam-se os seguintes: Contador de programa (PC - Program Counter), que aponta para a próxima instrução a executar. Registro de instrução (IR - Instruction Register) que armazena a instrução em execução. Outros registros que permitem o armazenamento de resultados intermediários. Clock Clock é um circuito oscilador que tem a função de sincronizar a velocidade de transferência de dados entre duas partes durante um processamento. Por exemplo, a transferência de dados entre o processador e a memória principal. Essa velocidade de transferência (freqüência) é medida em ciclos por segundo, ou Hertz. A velocidade de acesso dentro do processador é maior que na memória principal. Os processadores Pentium-100, Pentium II-300, acessam a memória principal a 66 MHz. Sistemas operacionais são conjuntos de programas que permitem explorar (fazer funcionar) o computador. Atualmente os sistemas operacionais mais conhecidos são Windows e Linux. Um computador é um conjunto de materiais inertes. São as diversas camadas de software que fazem com que ele funcione. Quando ligado à rede elétrica, uma primeira camada de software, sempre a mesma, é posta em ação. Esta camada foi gravada diretamente no hardware: é a BIOS (Basic Input/Output System). Esta camada realiza certo número de verificações e de testes (presença de diversos periféricos, volume de memória, etc). Após isso o sistema operacional assume o controle. É o sistema operacional que permite aos humanos dialogar com os computadores. Segundo o grau de convivialidade do sistema, esse diálogo será mais ou menos amigável, podendo ser textual, gráfico ou uma mistura desses. A partir do sistema operacional o usuário pode então lançar os aplicativos (programas específicos). Todo arquivo é visto e tratado do mesmo modo pelo sistema operacional em vista de seu armazenamento em disco. Tecnicamente, um arquivo é um conjunto de bits formando uma entidade identificada por um nome e uma extensão seguindo a forma: nome.ext. Somente a sua extensão é capaz de determinar a natureza e assinalar ao sistema operacional o que esse arquivo é capaz de fazer. Assim, um arquivo .doc é reconhecido como um programa Word, um arquivo .xls é reconhecido como um arquivo do Excel e esses softwares são carregados na memória para execução. Alguns arquivos de imagens (.jpeg ou .jpg, .gif, .png, etc.) necessitam de um visualizador de imagens instalado no computador para que essas imagens possam ser exibidas na tela. Por padrão, está previsto que esses arquivos podem ser abertos no Internet Explorer, capaz de exibi-los a partir de páginas da Internet. Dependendo do sistema operacional, existem regras com mais ou menos restrições para dar nomes aos arquivos. No MS-DOS, antigo sistema operacional, os nomes de arquivo deveriam ter no máximo 8 caracteres com uma extensão de três caracteres. A partir do Windows 95 os nomes dos arquivos passaram a ter até 256 caracteres (incluindo o caminho onde se encontra o arquivo, por exemplo, C:\programas\C\programa1.exe). 3.9 Sistemas Operacionais 3.10 Os arquivos em informática 275 Unidade II - Algoritmos Programar é uma ciência ou uma arte? A computação é uma ciência, porem programar está mais para arte. A programação requer certo dom. Mas isto podemos desenvolver com esforço e paciência. Assim como aprendemos a pintar, também podemos aprender a programar. Alguns requisitos são necessários, é verdade. Para desenvolvermos programas que realizem algumas « proezas » matemáticas, é necessário que tenhamos algum conhecimento para matemático, senão, como programá-las? Qualquer que seja a natureza de nossos programas, existem algumas regras básicas a serem seguidas. Primeiramente, é preciso entender o enunciado do problema a ser resolvido e então partirmos para encontrar uma solução. O estudo do domínio de um problema é conhecido no mundo da computação como análise. A apresentação de uma solução para esse problema faz parte do que se chama projeto. Como os domínios (álgebra, geometria, trigonometria, etc) são vastos e variados, procuramos seguir uma metodologia de resolução de problemas. É o que faremos a seguir no estudo dos algoritmos. Suponhamos o seguinte problema: trocar o pneu furado de um carro (você já passou por este tipo de problema?).Parece que estamos diante de um problema simples, mas tentemos explicar a um robô como proceder para realizar tal tarefa. Veremos um enfoque denominado “dividir para conquistar”, que nos ajudará bastante nessa e outras tarefas. Definição: conjunto finito, ordenado e não ambíguo de passos necessários para realizar uma tarefa. Esse conjunto apresenta as seguintes características: • possui um ponto de parada, isto é, sua execução é finita; • recebe dados de entrada e, em função desses, produz dados de saída. Um algoritmo pode ser correto ou não. Um algoritmo correto produz uma saída correta e pára, enquanto que um algoritmo incorreto produz uma saída incorreta ou não pára. Essa abordagem, muito utilizada em informática, consiste em dividir o problema inicial em vários subproblemas, recursivamente. Cada subproblema é, logicamente, mais simples que o problema inicial. Esse procedimento de divisão continua até que sejam encontrados subproblemas, que possam ser resolvidos de forma simples ou trivial. 1. Situando a temática 2. Problematizando a temática 3. Conhecendo a temática 3.1 Algoritmos 3.2 Abordagem dividir para conquistar Algoritmo ≅ Receita de bolo 276 Refinamento do passo 1 Refinamento do passo 1.5 O passo 1.6 revela a existência de um procedimento repetitivo: enquanto não houver espaço suficiente para colocar o estepe, faça o seguinte: levante o carro com o macaco. Outro procedimento que pode ser associado ao passo 1.6 é: repita o levantamento do carro com o macaco até que haja espaço suficiente para colocar o estepe. 3.3 Algoritmo Trocar Pneu Furado 3.4 Algoritmo Trocar Lâmpada Queimada 1. pegue o macaco e levante o carro 2. retire o pneu furado 3. pegue o estepe, coloque-o na roda e aperte os parafusos 4. abaixe o carro e reaperte os parafusos 5. guarde o pneu furado e o macaco 1.1 remova o macaco do porta-malas 1.2 coloque o macaco sob o carro, próximo ao pneu furado 1.3 desaperte os parafusos da roda 1.4 insira a manivela no macaco (ou monte-o de acordo com o modelo do macaco) 1.5 coloque um calço sob o carro para impedi-lo de se mover 1.6 levante o carro com o macaco até que haja espaço suficiente para colocar o estepe 1.5.1 se o carro estiver em uma ladeira, de frente para o topo desta, então coloque o calço atrás de um pneu em bom estado caso contrário, coloque o calço na frente de um pneu em bom estado 1. Remova a lâmpada queimada 2. Coloque a nova lâmpada 1. Posicione uma escada em baixo da lâmpada queimada 2. Escolha uma nova lâmpada com a mesma voltagem da queimada 3. Suba na escada até que a lâmpada possa ser alcançada 4. Gire a lâmpada queimada no sentido anti-horário até que ela se solte 5. Posicione a nova lâmpada no soquete 6. Gire-a no sentido horário até que ela se firme 7. Desça da escada Refinamento 277 Esses passos e refinamentos seriam importantes para a realização dessas tarefas por uma máquina. Um ser humano faz essas coisas intuitivamente, mas as máquinas... 1 – Elabore um algoritmo para fazer pipoca em uma panela de fogão, usando manteiga, sal e milho. 2 – Elabore um algoritmo para realizar uma chamada telefônica local. 3 – Elabore um algoritmo para realizar uma chamada telefônica de longa distância (interurbana). 4 – Elabore um algoritmo que simule sua saída de casa pela manhã. Comece com o passo “dormindo na cama” e inclua todas as suas atividades matinais. 5 – Elabore um algoritmo para calcular as raízes reais de uma equação do 2º grau. Se a equação não tiver raízes reais, isto deve ser mencionado como resposta. 3.5 Exercícios 3.6 Solucionando um problema 1. Posicione uma escada em baixo da lâmpada queimada 2. Selecione uma nova lâmpada para a substituição 2.1. Se a voltagem não for a mesma da lâmpada queimada, repita os passos abaixo até encontrar uma que sirva 2.1.1. Descarte a lâmpada selecionada 2.1.2. Selecione uma nova 3. Repita até que a lâmpada possa ser alcançada 3.1.1. Suba um degrau da escada 4. Repita até que a lâmpada fique livre do soquete 4.1.1. Gire a lâmpada no sentido anti-horário 5. Posicione a nova lâmpada no soquete 6. Repita até que a lâmpada esteja firme 6.1.1. Gire a lâmpada no sentido horário 7. Desça da escada Algoritmo Fase de resolução do problema Fase de implementação da solução Passo único Problema Programa de computador 278 Fase de resolução – elaboração de um algoritmo para resolver o problema proposto, incluindo testes para verificar se a solução é boa. Fase de implementação – ao encontrarmos o algoritmo adequado à solução do problema, precisamos codificá-lo em uma linguagem de programação. Geralmente, essa codificação é fácil de ser feita desde que o programador compreenda bem a sintaxe e a semântica dos comandos da linguagem escolhida para a implementação. Luis é o tipo de cara que você gostaria de conhecer. Ele estava sempre de bom humor e sempre tinha algo de positivo para dizer. Se alguém lhe perguntasse como ele estava, a resposta seria logo: Se melhorar estraga. Ele era um gerente especial em um restaurante, pois seus garçons o seguiam de restaurante em restaurante apenas pelas suas atitudes. Ele era um motivador nato. Se um colaborador estava tendo um dia ruim, Luis estava sempre dizendo como ver o lado positivo da situação. Fiquei tão curioso com seu estilo de vida que um dia lhe perguntei: Você não pode ser uma pessoa positiva todo o tempo. Como faz isso? Ele me respondeu: A cada manhã, ao acordar, digo para mim mesmo: Luis, você tem duas escolhas hoje: Pode ficar de bom humor ou de mau humor. Eu escolho ficar de bom humor. Cada vez que algo ruim acontece, posso escolher bancar a vítima ou aprender alguma coisa com o ocorrido. Eu escolho aprender algo. Toda vez que alguém reclamar, posso escolher aceitar a reclamação ou mostrar o lado positivo da vida. Certo, mas não é fácil - argumentei. É fácil sim, disse-me Luis. A vida é feita de escolhas. Quando você examina a fundo, toda situação sempre oferece escolha. Você escolhe como reagir às situações. Você escolhe como as pessoas afetarão o seu humor. É sua a escolha de como viver sua vida. Eu pensei sobre o que o Luis disse e sempre lembrava dele quando fazia uma escolha. Anos mais tarde, soube que Luis cometera um erro, deixando a porta de serviço aberta pela manhã. Foi rendido por assaltantes. Dominado, enquanto tentava abrir o cofre, sua mão tremendo pelo nervosismo, desfez a combinação do segredo. Os ladrões entraram em pânico e atiraram nele. Por sorte foi encontrado a tempo de ser socorrido e levado para um hospital. Depois de 18 horas de cirurgia e semanas de tratamento intensivo, teve alta ainda com fragmentos de balas alojadas em seu corpo. Encontrei Luis mais ou menos por acaso. Quando lhe perguntei como estava, respondeu: Se melhorar estraga. Contou-me o que havia acontecido perguntando: Quer ver minhas cicatrizes? Recusei ver seus ferimentos, mas perguntei-lhe o que havia passado em sua mente na ocasião do assalto. A primeira coisa que pensei foi que deveria ter trancado a porta de trás, respondeu. Então, deitado no chão, ensangüentado, lembrei que tinha duas escolhas: poderia viver ou morrer. Escolhi viver! Você não estava com medo? Perguntei. Os para-médicos foram ótimos. Eles me diziam que tudo ia dar certo e que ia ficar bom. Mas quando entrei na sala de emergência e vi a expressão dos médicos e enfermeiras, fiquei apavorado. Em seus lábios eu lia: "Esse aí já era". Decidi então que tinha que fazer algo. O que fez? Perguntei. Bem, havia uma enfermeira que fazia muitas perguntas. Perguntou-me se eu era alérgico a alguma coisa. Eu respondi:"sim". Todos pararam para ouvir a minha resposta. Tomei fôlego e gritei: - "Sou alérgico a balas!" Entre risadas lhes disse: - "Eu estou escolhendo viver, operem-me como um ser vivo, não como morto." Luis sobreviveu graças à persistência dos médicos, mas também graças à sua atitude. Aprendi que todo dia temos opção de viver plenamente. Afinal de contas, "ATITUDE É TUDO". Agora você tem duas opções: 1. Após ler estas aulas, esquecê-las. 2. Dar o melhor de si, com todas as dificuldades que possam aparecer e escolher aprender. Boa escolha e bons estudos. (Texto de autor desconhecido, obtido na Internet.) 3.7 Atitude é tudo 279 Pensar por etapas, foi o que vimos. Não adianta querer que os computadores se comportem como os humanos. Eles fazem, realmente, operações aritméticas e de comparações, muito mais rápido do que nós o fazemos, mas é preciso dizer-lhes, felizmente, o deve ser feito, como e quando. Os algoritmos se resumem nisso, informar ao computador de modo inequívoco essas formas e temporalidade. 1. Salvetti, Dirceu D., Barbosa, Lisbete M., Algoritmos. Pearson Education do Brasil, 1998 2. Pinheiro Neto. Augusto A., Notas de aula, 2001. 4. Avaliando o que foi construído 5. Referências 280 Unidade III - Iniciação a Programação Poderíamos dizer que a palavra programar vem do Latim programmeus. Você acredita? Pois bem, é verdade. Mas o que nos interessa é que a palavra programar, em nosso contexto, significa simplesmente: escrever programas de computador. Os programas solicitam aos computadores a realização de ações. Veremos como dialogar com um computador, procurando ensinar-lhe como realizar essas ações, ou seja, vamos aprender a codificar em uma linguagem de programação um algoritmo apresentado como solução para um problema. O computador é uma máquina estranha, é o mínimo que se pode dizer. Ele entende apenas aquilo que está codificado somente com 0’s e 1’s. Esse tipo de linguagem é denominado linguagem de máquina, ou de baixo nível. Imaginemos, por exemplo, que a operação de somar seja representada por 11001100 e que desejemos somar 2 com 3. Para transmitir essa ordem a um computador, temos que escrever uma instrução equivalente a esta: 11001100 00000010 00000011. Felizmente, as linguagens de programação atuais estão bem mais próximas das linguagens naturais, aquelas que os homens utilizam para se comunicarem. Existem diversas linguagens de programação que podem ser utilizadas na implementação de algoritmos. Estudaremos a seguir uma das mais importantes hoje em dia, a linguagem C. Linguagens de alto nível As linguagens atuais com as quais se escreve programas para computadores são estruturadas (possuem estruturas de controle), mais próximas da linguagem natural e com certo formalismo matemático. Essas linguagens são chamadas de linguagens de Alto Nível. Exemplos de linguagens de alto nível. C, C++, Java, Pascal, Visual Basic, Delphi, PHP, etc... Programa fonte e programa executável Os programas escritos em linguagens de alto nível, aqueles escritos pelo programador, são geralmente chamados de programas fonte, pois ali são codificados os conhecimentos necessários para a solução de determinada tarefa. Uma vez traduzido para a linguagem de máquina, aquela dos 0’s e 1’s, o programa resultante recebe o nome de programa executável. Tradutores Tradutores são programas especiais que traduzem um programa fonte para linguagem de máquina. Alguns programas são ditos compilados e outros interpretados. O que é isso? Existem tradutores que, quando da tradução do programa fonte, traduzem cada linha e a executam imediatamente. Nesse caso diz-se que houve uma interpretação do programa fonte e esse tipo de tradutor é denominado interpretador. Quando a tradução se dá por inteiro e tão somente após seu término o programa é executado, diz-se que ocorreu uma compilação e esse tipo de tradutor é denominado compilador. Programas compilados são mais rápidos do que programas interpretados. Importante! Existe um compilador diferente para cada linguagem de alto nível. Isso é lógico. As linguagens sendo diferentes, não se traduz C do mesmo modo que Delphi, por exemplo. 1. Situando a temática 2. Problematizando a temática 3. Conhecendo a temática 3.1 Conceitos básicos 281 Fazendo um esquema gráfico do que acabamos de dizer temos: Veremos em seguida que mesmo para uma única linguagem como C, por exemplo, existem vários compiladores diferentes. Há compiladores escritos pela Microsoft, GNU, etc. Felizmente esses compiladores são quase idênticos. Linguagens de altíssimo nível São fáceis de utilizar, possuem vários elementos de linguagem que podem ser arrastados para a área do programa e o seu código é então gerado automaticamente, digamos "grande público", como Visual Basic. Essas linguagens apresentam alguns inconvenientes: elas custam caro e são limitadas à plataforma. Se o compilador for voltado à plataforma Windows, por exemplo, não espere fazer um programa desenvolvido com ele funcionar sob Linux ou Macintosh. Enfim, não podemos fazer tudo que desejarmos com esse tipo de linguagem. Perceba que estamos de certa forma limitados. As linguagens de alto nível são um pouco mais difíceis que Visual Basic, mas com uma linguagem deste tipo, como C ou C++, aprendemos muito mais sobre programação e funcionamento dos computadores. Após aprendermos uma linguagem deste tipo, somos capazes de aprender mais facilmente uma outra linguagem de programação. O programador torna-se então mais autônomo. Em particular C e C++ são linguagens muito populares. Elas são utilizadas para programar uma grande parte dos softwares mais conhecidos. Enfim, programando em C ou C++, o programador está livre de comprar softwares caríssimos. Programar em C ou C++ é, geralmente, gratuito. Qualidades de um programador Um programador deve ter certas qualidades: • paciência: se um programa não funcionar da primeira vez, é preciso saber perseverar! • bom senso: não é preciso ser tão forte em matemática, mas isso não impede de se ter que refletir! • Calma: não se dá tapa no computador . Isso não faz o programa funcionar. Em resumo, não são necessários conhecimentos especiais para programar. Alguém fraco em matemática pode até se sair bem, o essencial é a paciência para refletir. O mínimo que deve estar disponível para um programador: • Um editor de texto para escrever o código fonte do programa. Em teoria um software como o Bloco de Notas do Windows, “edit” em linha de comando do DOS ou o “vi” em Linux é suficiente. O ideal é dispor de um editor de texto inteligente que colore o código, o que permite acompanhá-lo mais facilmente. • Um compilador para transformar (compilar) o código fonte em binário. • Um depurador (debugger) para ajudar a encontrar alguns erros no programa, erros de utilização da memória do computador (erros de lógica do programador não são detectados). Programa escrito em linguagem de Alto Nível Programa traduzido em linguagem de máquina Programa de tradução para linguagem binária Programa Fonte Programa Executáve l Compilador/ Interpretador Fonte 282 É comum utilizarmos um programa 3-em-1 que combina editor de texto, compilador e depurador. Esses programas são também chamados de IDE "Integrated Development Environment". Exemplos de IDE para programar em C: Bloodshed Dev-C++ e Code::Blocks. Em nosso curso escreveremos os programas fonte no bloco de notas (notepad) se o sistema operacional for Windows ou no KEdit (ou outro editor de texto que acompanhe a versão instalada) se o sistema operacional for Linux. Isto nos restringe aos conhecimentos da linguagem de programação, o que é mais interessante para quem está iniciando. Após conhecermosbem a sintaxe e a semântica da linguagem, usar uma interface tipo IDE será fácil. Acredite. Para que tenhamos uma idéia, eis aqui diferentes tipos de memória existentes dentro de um computador, da mais rápida para a mais lenta: 1. Os registros: uma memória ultra-rápida situada dentro do processador. 2. A memória cache: faz a ligação entre os registros e a memória RAM. 3. A memória RAM: a memória principal com a qual trabalhamos geralmente. 4. O disco rígido: que você conhece seguramente, é onde guardamos os arquivos para posterior uso. Ao dizermos que uma memória é lenta, estamos considerando a escala de tempo de um computador. Afinal, 8 milissegundos são quase imperceptíveis aos humanos, mas é muito tempo para acessar um disco rígido, por exemplo! A memória principal Fotografando de perto a memória principal (RAM) de um computador, não vemos grandes coisas. É mais importante sabermos como ela funciona internamente. Vejamos o esquema abaixo. Ele é bastante simples, mas é do necessitamos saber para programar. Como podemos ver é preciso distinguir duas coisas: 3.2 Memória e variáveis 0 145 1 3.8028322 2 0.8272555 3 39014768 940.5118 Endereço Valor . . . . . . n-1 283 • Endereços: um endereço é um número que permite ao computador se orientar na memória. Tudo começa pelo endereço 0 (justamente no início da memória) e termina no endereço 2n-1, onde n é o tamanho do barramento de endereços. Quanto mais memória existir no computador mais endereços existirão e mais coisas poderão ali ser armazenadas. • Em cada endereço podemos armazenar um único valor (um número): o computador armazena na memória esses números para poder recuperá-los depois, quando necessário. O endereçamento de memória é uma técnica que permite ao processador acessá-la. A interface utilizada para isto é, na maioria das vezes, chamada barramento (BUS), um conjunto de fios dedicados a uma utilização particular. No caso do acesso à memória, esse barramento é chamado de barramento de endereços. A memória RAM só pode armazenar números. Como fazer então para armazenar outros caracteres (palavras, por exemplo)? Boa pergunta. Na verdade, as letras não passam de números para os computadores! Uma frase é uma simples sucessão de números. Existe uma tabela, denominada ASCII, que faz a correspondência entre os números e as letras e outros caracteres. Essa tabela diz, por exemplo, que o número 65 corresponde à letra A. Variáveis Em C, uma variável é constituída de dois atributos: • Um valor: o número que ela armazena, por exemplo, 25. • Um nome: que permite reconhecê-la. Programando em C não é preciso lembrar o endereço de memória que guarda certo valor (ufa!), basta lembrar o nome da variável que contém aquele valor. O compilador fará a conversão entre o nome da variável e o endereço onde ela está armazenada (ainda bem). Isso parece um pouco confuso no momento (qual o interesse de armazenar um número se é preciso lembrar o seu endereço), mas, tudo vai tomar sentido em seguida. Em C cada variável deve ter um nome. Se uma variável guarda o valor da vida média de um cidadão, nós bem que gostaríamos de chamá-la “vida média”. Infelizmente isso não é possível. Existem certas restrições. Veja a seguir as regras que devemos seguir ao darmos um nome a uma variável. • Só podem existir letras (minúsculas ou maiúsculas), dígitos e “sublinha” _. • O nome de uma variável deve começar por uma letra. • Espaços são proibidos • Acentos não são permitidos (ãóôéàê etc). Enfim, e isto é muito importante, a linguagem C (como C++) faz diferença entre as letras maiúsculas e minúsculas. Então Brasil, bRasil e brasil são nomes que representariam três variáveis distintas. Veja alguns exemplos de nomes válidos de variáveis: Vidamedia, vida_media, vida_Media, VidaMedia, num_de_telefone, bola215, etc Cada programador tem sua maneira própria de nomear as variáveis. Uma maneira bastante utilizada é: • Começar os nomes de variáveis por maiúsculas. • Se houver várias palavras no nome da variável, colocar uma maiúscula no início de cada palavra. VidaMedia, por exemplo. 3.3 Dando nome às variáveis 284 Um computador como se pode constatar nada mais é do que uma grande máquina de calcular. Ele só sabe trabalhar com números. O problema é que existem vários tipos de números. • Números inteiros positivos: 45; 578; 2457 • Números inteiros negativos: -87; -513 • Números decimais, isto é, números com vírgula: 1,7741; 9810,7 • Números decimais negativos: -98,45; -1,0045 Nosso pobre computador precisa de ajuda. Quando pedimos a ele para armazenar um número, devemos dizer-lhe de que tipo é o número. Não é que ele não seja capaz de reconhecê-lo, mas isso o ajuda a organizar-se e não perder tempo e espaço de memória com algo que poderia ser evitado. Quando declaramos uma variável em um programa devemos então indicar o seu tipo. Vejamos os principais tipos de variáveis existentes em C: Esses não são todos os tipos, mas já dá pra começar. Os três primeiros tipos permitem armazenar números inteiros (1, 2, 3, 4...). Os dois últimos permitem armazenar números decimais (13.8, 16.911...). Os tipos float e double permitem armazenar números bastante grandes. Se você não está habituado com as potências de dez, então imagine que o tipo double permite armazenar o número 1 seguido por 308 zeros, isto é, 100000000000000.... (eu não vou aqui escrever 308 zeros ) Observemos que int e long são parecidos. Antes não era assim (um int era menor que um long), mas hoje as memórias evoluíram e temos bastante espaço para escrever números grandes sem grandes preocupações com a memória. Por razões de compatibilidade, a linguagem C guarda os dois tipos. Na prática utilizamos principalmente os tipos char, long e double. Você verá que na maior parte do tempo manipularemos números inteiros (tanto melhor, pois são mais fáceis de utilizar). Atenção com os números decimais. O computador não conhece a vírgula decimal. Em seu lugar utilizaremos o ponto. Não devemos escrever 273,45, mas 273.45! Isso ainda não é tudo! Além dos tipos que armazenam números inteiros (char, int, long,...) já vistos, existem outros ditos « unsigned » (sem sinal) que podem armazenar apenas números positivos. Para utilizá-los basta escrever a palavra unsigned antes do nome do tipo. unsigned char 0 a 255 unsigned int 0 a 4 294 967 295 unsigned long 0 a 4 294 967 295 A vantagem de utilizar tipos unsigned é que podemos armazenar números duas vezes maiores (char pára em 128 enquanto unsigned char vai até 255, por exemplo). Por que criar três tipos para os números inteiros? Um só tipo não seria suficiente? Sim, mas no início foram criados vários tipos para economizar memória. A tabela a seguir mostra o espaço necessário para armazenar os tipos. 3.4 Tipos de variáveis Nome do tipo Valores que podem ser armazenados Char -128 a 127 Int -2 147 483 648 a 2 147 483 647 Long -2 147 483 648 a 2 147 483 647 Float -3.4 x 1038 a 3.4 x 1038 Double -1.7 x 10308 a 1.7 x 10308 285 Uma declaração de variável é muito simples, agora que você sabe tudo que é necessário. Basta indicar, na ordem: 1. O tipo da variável que vai ser criada 2. Teclar espaço 3. Indicar o nome desejado para a variável 4. Enfim, não esqueça o ponto-e-vírgula Por exemplo, se desejamos criar uma variável de nome TotalDePontos do tipo long, basta digitar a linha seguinte: long TotalDePontos; Isso é tudo! Outros exemplos: long NotaDeFisica; double TotalRecebido; unsigned long NumeroDeEspacosNaLeituraDeUmTextoLongo; Atenção! A declaração das variáveis deve ser feita no início das funções. O texto no quadro abaixo é um código de programa escrito em C. Um programa em C é formado por váriostrechos de código com um formato especial denominado função. Todo programa possui uma função principal chamada main, essa é a única no programa abaixo. Não se preocupe, aprenderemos aos poucos a escrever um programa. Se executarmos este programa ficaremos pasmos ao ver que ele não faz nada. Algumas explicações Na verdade se passa alguma coisa, mas não é possível vê-la. Quando a execução do programa chega à linha de declaração da variável TotalDePontos ele « solicita » ao computador permissão para utilizar um espaço de sua memória principal. Se tudo vai bem, o computador responde « pois não, faça como se estivesse em sua casa ». O único problema que poderia acontecer seria não haver mais espaço disponível na memória do computador, mas isso será um caso extremo. É possível declarar mais de uma variável em uma mesma linha do programa. Por exemplo, long a, b, c; Isso criará três variáveis de tipo long denominadas a, b e c. É tudo que há de mais simples. Para atribuir o valor 8 à variável TotalDePontos basta escrever: TotalDePontos = 8; Nome do tipo Número de bits Char 8 Int 32 Long 32 Float 32 double 64 3.5 Declarando uma variável 3.6 Atribuindo valor a uma variável #include <stdio.h> int main(int argc, char *argv[]) { // Início da função long TotalDePontos; system("PAUSE"); return 0; // Fim da função } 286 De modo geral, um comando de atribuição tem a forma: variável = expressão; Nosso programa completo se parece agora com Nada é exibido na tela do computador até agora. Em algum lugar da memória do computador o valor 8 é armazenado, esse lugar é conhecido no programa pelo nome da variável TotalDePontos e isso é tudo. O valor de uma nova variável Eis uma questão muito interessante. Quando se declara uma variável, qual o seu valor inicial? De fato, quando o computador lê a linha long TotalDePontos; ele reserva uma pequena parte da memória para armazenar um valor do tipo long. Mas que valor é esse? Existe um valor padrão (0, por exemplo)? Bem, a resposta é não. Não existe um valor padrão. O computador reserva um espaço na memória para armazenar um novo valor, mas não apaga o que já existia naquele espaço. Imediatamente a variável recebe o valor que se encontrava no espaço que foi reservado, que pode ser qualquer coisa. Assim, o melhor é inicializar as variáveis quando de suas declarações, sempre que possível. Procedemos assim: long TotalDePontos = 8; Agora a variável foi declarada e recebeu imediatamente o valor 8. Foi apagado o que poderia haver na posição de memória que lhe foi alocada e colocado ali o valor 8. Ocorre às vezes que se tem a necessidade de armazenar um mesmo valor durante toda a execução de um programa. O valor de pi (3.14), por exemplo. Isso quer dizer que uma vez declarada e inicializada, a variável deverá conservar o seu valor impedindo que qualquer pessoa possa modificá-lo. Essas variáveis particulares recebem o nome de constantes, por motivos óbvios. Para declarar uma constante em um programa deve-se utilizar a palavra “const” antes do tipo e obrigatoriamente, inicializar a variável. Exemplo de declaração de uma constante: const long PI = 3.14; Não é uma obrigação, mas por convenção, escreve-se os nomes das constantes com letras maiúsculas. Isso nos permite distinguir facilmente os nomes de constantes dos de variáveis. Fora isso uma constante é utilizada do mesmo modo que uma variável. Ao tentar modificar o valor de uma constante no corpo de um programa o compilador acusará um erro (por quê?). Utilizamos a função printf para exibir valores na tela do computador. printf("Total de pontos = %d ", TotalDePontos); O símbolo especial % seguido da letra d é um especificador de formato. Este especificador permite a exibição de um número inteiro na tela do computador. Existem vários especificadores de formato que serão visto mais tarde. Por enquanto usaremos os especificadores para números inteiros e números decimais. Símbolo Significado %d Número inteiro (ex: 56) %f Número decimal (ex: 13.75) 3.7 Constantes 3.8 Exibindo o conteúdo de uma variável #include <stdio.h> int main(int argc, char *argv[]) { // Início da função long TotalDePontos; TotalDePontos = 8 ; system("PAUSE"); return 0; // Fim da função } 287 Por enquanto saiba que, se quisermos exibir um número inteiro, precisamos utilizar o especificador %d e para exibir um número decimal precisamos utilizar o especificador %f. Os especificadores de formato são geralmente utilizados dentro de um texto explicativo, como no exemplo anterior. É preciso, entretanto indicar para a função printf qual o valor a ser exibido. Para isso é preciso escrever o nome da variável que contém esse valor após o texto contendo o especificador, após uma vírgula. Vejamos outros exemplos: printf("O valor de a eh %d ", a1); printf("Foram encontrados %d resultados ", r); No primeiro exemplo %d indica que um valor inteiro deve ser exibido na tela do computador e esse valor está armazenado em a1. No segundo exemplo esse valor está armazenado na variável r. Por enquanto veremos os programas prontos e aprenderemos cada vez mais sobre suas estruturas. Pelo que temos visto podemos tirar algumas conclusões: • Um programa começa sempre com a instrução #include<stdio.h>, isto indica que uma biblioteca de funções de nome stdio deve ser incluída automaticamente no programa e isto é feito, não se preocupe. • O cabeçalho da função principal será sempre int main(). • Após // vem um comentário, que não é executado, serve apenas de documentação. • system("PAUSE"); fixa a tela de modo que possamos ver a resposta. • return 0 indica um fim normal do programa. Este programa produz a seguinte saída: Voce possui 5 pontos **** H U M M M **** Ah, agora voce so tem 4 pontos! Pressione uma tecla para continuar... Exibir várias variáveis em um único printf É possível exibir o valor de várias variáveis em um único printf. Para tanto, é suficiente indicar %d ou %f onde se deseja que os valores sejam impressos e em seguida indicar as variáveis que contêm esses valores, obedecendo à ordem em que os especificadores foram indicados, separadas por vírgula. Exemplo. printf("Voce tem %d pontos e faltam %d perguntas", TotalDePontos, p); As variáveis vão começar a ficar mais interessantes agora. Vamos solicitar ao usuário (aquele que está operando o computador) que digite um número. Vamos aprender a recuperar essa entrada e a armazenar em um determinado lugar na memória principal. Para solicitar ao usuário que entre 3.9 Recuperando uma entrada #include <stdio.h> int main() { long TotalDePontos = 5; // No início o alunos possui 5 pontos printf("Voce possui %d pontos \n", TotalDePontos); printf("**** H U M M M ****\n"); // O aluno errou uma questão TotalDePontos = 4; // Ele acaba de perder um ponto! printf("Ah, agora voce so tem %d pontos!\n\n", TotalDePontos); system("PAUSE"); return 0; } 288 com uma determinada informação pelo teclado utiliza-se a função scanf. Essa função se parece com a função printf. Deve-se colocar um %d ou %f, entre aspas, para indicar um inteiro ou um decimal a ser digitado. Veja um exemplo. scanf("%d", &idade); Coloca-se apenas %d (ou %f) entre as aspas. Não esquecer de colocar o símbolo & antes do nome da variável que vai receber o valor. E por que esse & antes do nome da variável? É preciso que você acredite em mim. Eu explicarei isso mais tarde. Não o faço agora para não embolar o meio de campo. Quando o programa encontra um scanf ele faz uma pausa e espera que o usuário digite um valor. Esse valor será armazenado na variável idade. Veja um pequeno exemplo. Saída: Qual a sua idade? 20 Ah! Voce tem 20 anos! Pressione uma tecla para continuar... Pronto! Você compreendeu o princípio. Graças à funçãoscanf o computador pode interagir com o usuário. Observe que nada nos impede de digitar outra coisa que um número inteiro: • Se digitarmos um número decimal como 34.56, por exemplo, ele será truncado imediatamente e só a parte inteira é armazenada. Neste caso, 34 é armazenado na variável idade. • Se digitarmos letras, a variável não muda de valor. Permanece então com o valor 0 (valor com que foi inicializada). Se a variável não tivesse sido inicializada, o programa imprimiria qualquer coisa. Percebem a importância da inicialização das variáveis? 1. Quando se declara uma variável, qual memória é utilizada? ( ) Registros ( ) Memória cache ( ) Memória RAM ( ) Disco rígido 2. Qual memória não é “apagada” quando o computador é desligado? ( ) Registros ( ) Memória cache ( ) Memória RAM ( ) Disco rígido 3. Qual desses não é um nome válido de variável? ( ) scanf ( ) coordenadaDaJanela ( ) desconto_total 3.10 Testes #include <stdio.h> int main() { long idade = 0; // inicializa a variável com 0 printf("Qual a sua idade? "); scanf("%d", &idade); // Solicita a entrada de idade com scanf printf("Ah ! Voce tem %d anos!\n\n", idade); system("PAUSE"); return 0; } 289 4. Qual dos tipos de dado abaixo permite armazenar o número 15.3? ( ) char ( ) long ( ) double ( ) int 5. Qual dos tipos abaixo permite armazenar o número - 1458 ? ( ) long ( ) unsigned int ( ) unsigned double 6. Se a variável “SaldoBanco” é um long que vale 150345 reais (pensemos grande), o que a linha de código printf("Voce tem %d reais na conta ", saldoBanco); exibirá na tela? ( ) Voce tem %d reais na conta ( ) Voce tem 150345 reais na conta ( ) Voce tem d reais na conta saldoBanco 7. Para armazenar um número decimal digitado no teclado, qual das linhas de código abaixo é a boa? ( ) scanf("%f", num); ( ) scanf("%d", num); ( ) scanf("%f", &num); ( ) scanf("%d", &num); Foram apresentados alguns conceitos básicos necessários para a construção de um programa: memória, variáveis e constantes, além das instruções capazes de realizar as operações de entrada e saída desses elementos de programação. Uma operação de entrada consiste em receber um valor via teclado e armazená-lo na memória principal do computador. A operação correspondente à saída consiste em exibir, geralmente na tela do computador, um valor que esteja armazenado em uma variável. Vimos também que as linguagens utilizadas pelos programadores atualmente são classificadas em um nível tão mais alto quanto mais afastadas estiverem da codificação binária. Assim é que linguagens como C, Pascal, Ada, Java, PHP, etc., são denominadas de alto nível. 1. Ascencio, Ana F G., Campos, Edilene A V., Fundamentos da Programação de Computadores: Algoritmos, Pascal, C/C++ e Java, 2ª edição, Pearson Education, 2007. 2. Hutchison, Robert C., Just, Steven B., Programming using the C language. MGraw-Hill Book Company, 1988. 3. Kernighan, Brian W., Ritche, Dennis M., Le langage C, Masson, 1986. 4. Avaliando o que foi construído 5. Referências 290 Unidade IV - Operações Aritméticas Básicas Nesta unidade aprenderemos a realizar a maior parte dos cálculos que um computador pode executar. A idéia é retomar o conceito de variáveis visto na unidade anterior e realizar as operações básicas que as envolvem como somar, multiplicar, permutar, etc. Já sabemos que o computador é uma calculadora muito potente com a qual podemos realizar as seguintes operações básicas com muita simplicidade: • Adição • Subtração • Multiplicação • Divisão • Módulo (eu explicarei o que é isto) Quando desejamos fazer outras operações mais complicadas, temos que as programar, isto é, explicar ao computador como fazê-las. Felizmente existe uma biblioteca de funções matemáticas já prontas que acompanha a linguagem C. Neste caso não é necessário programar as operações, mas simplesmente conhecer a interface das funções correspondentes, ou seja, saber como utilizá- las. Vamos começar pela adição. Para fazer uma adição se utiliza o símbolo + (sem brincadeira). O resultado de um cálculo, geralmente, deve ser armazenado em uma variável. Atenção! Na maioria das vezes, representaremos apenas a parte do programa fonte que estiver sendo discutida. Lembre-se de completar o código do programa começando por #include <stdlib.h> #include <stdio.h> .............................. Vejamos um exemplo de um trecho de programa que realiza uma soma. .............................. long resposta = 0; .............................. resposta = 13 + 7; Não é necessário ser um gênio em matemática para saber que a variável “resposta” armazenará o valor 20 após a execução desse trecho de programa. Claro que nada é exibido na tela como resposta. Para ver o resultado na tela, como já sabemos, é necessário utilizar a função printf. Em algum lugar do programa poderíamos ter printf(“17 + 3 = %d”, resposta);. O resultado na tela seria 17 + 3 = 20. Isso é tudo para a adição. Para as outras operações o procedimento é o mesmo apenas o símbolo do operador muda. Os operadores são representados pelos símbolos: • Adição: + • Subtração: - • Multiplicação: * • Divisão: / • Módulo: % 1. Situando a temática 2. Problematizando a temática 3. Conhecendo a temática 3.1 Primeiros passos 291 As três primeiras operações são realizadas de modo natural, conhecido por quase todos. Apenas as operações de divisão e de módulo merecem um pouco de reflexão, pois existem algumas considerações específicas relacionadas com os tipos envolvidos. As divisões funcionam normalmente em um computador quando não sobram restos. Por exemplo, 8/2 é 4, mas 7/2 que deveria ser 3.5 é 3 e sobra um resto 1. Observe................................. long resposta = 0; ............................. resposta = 7/2; printf ("7 / 2 = %d", resposta); .............................. Saída. 7 / 2 = 3 Eis aqui um problema. Sabemos que 7/2=3.5, mas o resultado apresentado foi 3. Ocorre que a variável “resposta” é do tipo long, portanto inteiro, por isso o computador truncou o resultado ficando apenas com a sua parte inteira. Se “resposta” tivesse sido declarada como float ou double o resultado seria 3.500000. Faça as modificações no programa fonte e execute-o novamente para ver o resultado. Se quisermos que o computador mostre o bom resultado (3.5) será necessário transformar os números 7 e 2 para decimais. Isso é feito escrevendo-se 7.0 e 2.0 (são os mesmos números, mas agora o computador vai entendê-los como números decimais e, portanto efetuará uma divisão de decimais). Na verdade, basta escrever um dos números no formato decimal (com ponto decimal). A linguagem C reconhecerá a expressão como sendo do tipo decimal e efetuará a operação corretamente. ..................................... double resposta = 0; .................................... resposta = 7.0 / 2.0; printf ("7 / 2 = %f", resposta); ...................................... Saída 7 / 2 = 3.500000 Observe que o especificador de formato utilizado foi %f, para números decimais. Mas atenção, às vezes se deseja realmente que o resultado seja um valor inteiro, nesse caso o resultado inicial (3) estaria correto. Esta propriedade dos números inteiros é muito importante. Tenha sempre em mente que 5/2=2, 8/5=1, 6/7=0, etc. Para obter um resultado decimal é necessário que os operandos sejam números decimais: 5.0/2.0=2.5, 8.0/5.0=1.6, 6.0/7.0=0.857143, etc. De fato, na divisão 5/2, o computador responde à questão “quantas vezes o número 2 está dentro do número 5?” Resposta, 2 (duas vezes). Você agora deve estar se perguntando “como fazer então para recuperar o resto da divisão”? Esse é o nosso próximo passo. O módulo é uma operação matemática que permite se obter o restoda divisão de dois números inteiros. Talvez seja uma operação menos conhecida que as anteriores, mas de grande importância nos cálculos realizados por computadores. Como mostrado anteriormente, o operador de módulo é representado por %. Veja os exemplos: • 7 % 2 = 1 ler: o resto da divisão de 7 por 2 • 28 % 5 = 3 ler: o resto da divisão de 28 por 5 3.2 A divisão 3.3 Primeiros passos 292 • 10 % 2 = 0 ler: o resto da divisão de 10 por 2 Ao executar a operação 7%2, o computador calcula o resto da divisão de 7 por 2, que é 1. A operação 10%2 fornece como resultado 0, pois esse é o resto da divisão de 10 por 2, ou seja, a divisão é exata. O interessante, agora que sabemos as cinco operações básicas, é utilizá-las entre várias variáveis. Nada nos impede de escrever, resposta = num1 + num2, por exemplo, onde num1, num2 e resposta são variáveis declaradas. Esta linha, obviamente faz a soma das variáveis num1 e num2 e coloca o resultado na variável resposta. Agora as coisas começam a ficar mais interessantes. Você já é capaz de fazer coisas espantosas, como uma calculadora. Creia-me. Imagine um programa que solicita ao usuário a entrada de dois números. Esses dois números deverão ser armazenados em variáveis. Em seguida escreva uma expressão que calcule a soma desses números e armazene o resultado em uma variável chamada resposta. Então exiba o resultado obtido na tela do computador. Experimente escrever esse programa sozinho. Uma possível resposta seria: Saída Entre com o valor de num1: 52 Entre com o valor de num2: 30 52 + 30 = 82 Experimente agora seguir o mesmo procedimento para que a sua calculadora execute as outras operações básicas, ou seja, modifique o programa acima para que ele execute as operações de subtração, multiplicação e divisão. Existem em C técnicas que permitem abreviar a escrita de certas operações. Essas abreviações têm por objetivo agilizar a digitação e tornar o código mais conciso. Incremento Quase sempre, um programador se depara com um problema bem simples, mas de grande importância: aumentar de 1 o valor de certa variável. Imagine que um programa trabalhe com uma variável denominada Total e que se deseje aumentar de 1 o valor dessa variável. Como fazê-lo se o seu valor atual não é conhecido? Solução: Total = Total + 1; O que se passa em um computador ao encontrar uma instrução como esta? Bem, ele sempre avaliará a expressão que se encontra do lado direito da instrução de atribuição (representada pelo 3.4 Cálculo entre variáveis 3.5 Abreviações: incremento e decremento #include <stdio.h> #include <stdlib.h> int main() { long resposta = 0, num1 = 0, num2 = 0; // ** solicitar num1 e num2 ao usuário ** printf("Entre com o valor de num1: "); scanf("%d", &num1); printf("Entre com o valor de num2: "); scanf("%d", &num2); // ********* Calcular ************ resposta = num1 + num2; // ** Mostrar o resultado na tela ** printf ("%d + %d = %d\n", num1, num2, resposta); system("PAUSE"); return 0; } 293 símbolo =) e armazenará o seu resultado na variável que se encontra do lado esquerdo. Assim, na unidade de aritmética e lógica (UAL), ele somará 1 ao valor atual da variável Total e substituirá o valor armazenado em Total pelo valor da expressão calculada. Observe que nessa instrução escreve-se duas vezes o nome de uma mesma variável (Total). Os programadores achando isso muito cansativo resolveram então abreviá-la. A instrução seguinte faz exatamente a mesma coisa que a anterior e escreve-se menos: Total++; Este recurso é muito usado nos programas escritos em C. Você terá oportunidade de comprovar este fato. Decremento Esta operação é o inverso daquela denominada incremento. Trata-se de retirar 1 do valor de uma variável. Então, de modo análogo à operação de incremento tem-se: Total = Total - 1; equivalente a Total--; Existem outras abreviações que funcionam sob o mesmo princípio que o de incremento (decremento) visto anteriormente, porem de forma mais geral. Essas abreviações funcionam para todas as operações básicas. A tabela abaixo mostra essas abreviações. Operação Abreviação total = total +5 total += 5 total = total -5 total -= 5 total = total *5 total *= 5 total = total /5 total /= 5 total = total %5 total %= 5 Exemplo. Supor total = 5 inicialmente. long total = 5; total += 4; // total vale 9 total -= 3; // ... total vale 6 total *= 5; // ... total vale 30 total /= 3; // ... total vale 10 total %= 3; // ... total vale 1(pois 10=3*3+1) A vantagem aqui é que podemos utilizar todas as operações básicas e podemos somar, multiplicar, etc por qualquer número. Essas abreviações são importantes quando temos operações repetitivas com essa estrutura em um programa. Todavia, o incremento é a abreviação mais utilizada. Em C existe um conjunto de funções já prontas para uso bastando apenas ao usuário compreender as suas interfaces, o meio de comunicação do programa com essas funções. Esse 3.6 Outras abreviações 3.7 A biblioteca matemática 30 total Antes Na memória 31 total Depois Na memória 30+1 Na UAL 294 conjunto de funções foi escrito por outros programadores e servem, de certo modo, para evitar que os programadores atuais reinventem a roda a cada novo programa. Já utilizamos as funções printf et scanf da biblioteca stdio.h. Existem outras bibliotecas de programas, dentre elas uma denominada math.h, que contém diversas funções matemáticas já prontas, isto é, já programadas. Tenha em mente, por exemplo, que a linguagem C não sabe calcular potência. Se escrevermos 43 o computador não saberá executar essa operação, pois ele não sabe o que isso significa. Para a realização desse cálculo é necessário indicar no início do programa a inclusão de uma biblioteca que contenha a função responsável por ele. Essa indicação é feita por: #include <math.h> Uma vez feita essa indicação, podemos utilizar todas as funções dessa biblioteca. As principais funções existentes na biblioteca math são: fabs Esta função retorna o valor absoluto de um número, isto é, |x| (sua notação matemática). O valor absoluto de um número é o seu valor positivo: • Ao passar o valor -78 para a função, ela retornará 78. • Ao passar o valor 175 para a função, ela retornará 175. ........................................................ double absoluto = 0, x=-42; absoluto = fabs(x); // absoluto receberá o valor 42 ........................................................ A função fabs retorna um valor double por isso devemos declarar a variável absoluto (aquela que vai receber o retorno da função) como sendo do tipo double. Existe uma função similar a fabs na biblioteca "stdlib.h", é a função abs. Essa função funciona do mesmo modo que fabs, mas somente para valores inteiros. Devemos então declarar a variável que vai receber o retorno da função como sendo do tipo int. ceil Esta função retorna o menor número inteiro maior que o número decimal que lhe é passado como argumento. Por exemplo, ao passar 18.33 como argumento para a função ela retorna 19. Esta função retorna um valor do tipo double. ......................................................... double teto = 0, valor1 = 18.33; teto = ceil(valor1); // teto valerá 19 floor Esta função funciona como a precedente, mas retorna o maior inteiro menor do que o valor decimal passado como argumento. Por exemplo, ao passar 18.99 como argumento para a função ela retorna 18. Vejamos um programa que exemplifica as duas funções. //Programa floor, ceil #include <stdio.h> int main(void) { double base=0, valor2=18.99; float teto=0, valor1=18.33; teto=ceil(valor1); base=floor(valor2); printf("Base = %f\n", base); printf("Teto = %f\n", teto); printf("Tamanho de base (em bytes) = %d\n", sizeof(base));printf("Tamanho de teto (em bytes) = %d\n", sizeof(teto)); getch(); return 0; } 295 Outras funções. 1. Qual o símbolo de multiplicação na linguagem C? ( ) * ( ) + ( ) / ( ) - ( ) % 2. Qual o resultado da operação 17 % 5? ( ) 0 ( ) 1 ( ) 2 ( ) 3 ( ) 4 ( ) 5 ( ) 15 3. Qual o valor da variável resultado após a instrução resultado = (8 / 3) - 2;? ( ) -2 ( ) 0 ( ) 1 ( ) 2 4. Qual o nome da operação seguinte em programação? x++; • ( ) incremento • ( ) argumento • ( ) suplemento 5. Qual o valor da variável “numero” após as operações seguintes? long numero = 4; numero--; numero *= 4; numero %= 12; numero += 1; ( ) 0 ( ) 1 ( ) 4 ( ) 12 ( ) 14 6. Qual das funções abaixo se deve utilizar para que 13.25 seja arredondado para 14? ( ) pow ( ) ceil ( ) floor ( ) sqrt Essas são as operações e funções que provavelmente todos os programadores mais utilizam ao trabalharem com as operações aritméticas. A sua compreensão é importantíssima, pois elas formam a base de programas mais complexos. Teremos oportunidade na seqüência deste curso de utilizá-las como operações elementares. função argumentos retorna pow(n, p) (double|float|int, double|float|int) double|float|int (np) sqrt(n) (double|float|int) double ( n ) sin(x) em radianos double (seno de x) cos(x) em radianos double (cosseno de x) tan(x) em radianos double (tangente de x) asin(x) double double (arco seno de x) acos(x) double double (arco cosseno de x) atan(x) double double (arco tangente de x) exp(x) double double ( xe ) log(x) double double (loge x) log10(x) double double (log10 x) 3.8 Testes 4. Avaliando o que foi produzido 296 1. Ascencio, Ana F G., Campos, Edilene A V., Fundamentos da Programação de Computadores: Algoritmos, Pascal, C/C++ e Java, 2ª edição, Pearson Education, 2007. 2. Hutchison, Robert C., Just, Steven B., Programming using the C language. MGraw-Hill Book Company, 1988. 3. Kernighan, Brian W., Ritche, Dennis M., Le langage C, Masson, 1986. 5. Referências 297 Unidade V- Praticando Entrada e Saída As funções que realizam as operações de entrada ou saída não pertencem à linguagem C. A biblioteca padrão de entrada/saída “stdio” contém tudo que é necessário para as operações de entrada ou saída em um programa C. Essa biblioteca é formada por um conjunto de funções que fornecem à linguagem um sistema de interfaces cômodas para a realização das operações de entrada ou saída. As funções mais utilizadas para entrada ou saída são: Sempre que um programa precisar de dados iniciais vindos do mundo exterior, esses deverão ser inseridos no programa por uma função de leitura. É isso que faz a função scanf. De modo análogo, os dados produzidos como resultado de processamento interno são exibidos, enviados para o mundo exterior, via a função printf. Vejamos alguns detalhes sobre essas funções. Consideremos o comando scanf(“%d”, &n);. Trata-se aqui da leitura de um valor que deverá ser armazenado na variável n. Para administrar corretamente a variável n, a função scanf precisa conhecer o seu tipo. No exemplo acima, o primeiro parâmetro da função, representado pela seqüência de caracteres “%d” indica ao compilador C que a variável é de tipo inteiro (int). Se a variável n pertencesse a um outro tipo, outro caractere seria usado no lugar de d. Essa seqüência de caracteres é conhecida pelo nome “especificador de formato”. O segundo parâmetro da função (&n) indica o endereço na memória do computador, onde a variável n será armazenada. O computador se encarrega de calcular esse endereço. O programador apenas deve escrever o parâmetro &n para que o computador saiba que no programa o valor armazenado naquele endereço será conhecido por n. O endereço de uma variável x é representado, portanto, pela expressão &x. O primeiro argumento dessa função é sempre uma seqüência de caracteres. Explicamos o funcionamento dessa função com a ajuda de alguns exemplos. 1. printf(“bom dia”); • Quando essa instrução é encontrada, a função printf se encarrega de escrever na tela do computador a seqüência bom dia. 2. printf("Eh agradavel escrever um programa " "em C, \nquando o utilizamos \"corretamente\".\n"); 1. Situando a temática 2. Problematizando a temática scanf Lê valores de variáveis a partir da entrada padrão, geralmente o teclado. printf Escreve sobre a saída padrão. Na ausência de indicação em contrário, essa saída é a tela do computador. 3. Conhecendo a temática 3.1 Algumas considerações sobre a função scanf 3.2 Algumas considerações sobre a função printf 298 • As aspas no fim da primeira linha e no início da segunda permitem escrever uma seqüência de caracteres em mais de uma linha. Esse comando produz como saída: Eh agradavel escrever um programa em C, quando o utilizamos "corretamente". • A seqüência de caracteres \n diz ao compilador para executar um salto de linha (passar para a próxima linha da tela) • A seqüência de caracteres \" indica o uso de aspas. Nesse caso as aspas farão parte da saída que será impressa. 3. printf(“%d”, 5); • A função printf substitui o especificador de formato %d pelo primeiro parâmetro situado após a vírgula, neste caso o inteiro 5. Lembre que o caractere d em um especificador de formato representa um número inteiro. Seja o programa 4. printf("%s mede %d cm e pesa %f kg", nome, altura, peso); • Supor que as variáveis nome, altura e peso refiram-se a uma pessoa e valham a seqüência de caracteres “João”, o inteiro 185 e o número real 80.5, respectivamente. A função printf substitui os especificadores de formato respeitando a ordem em os mesmos se encontram na instrução. Assim %s é substituído pelo primeiro parâmetro situado após a vírgula, neste caso a seqüência João, %d é substituído por 185 e %f por 80.5. Note que %s é o especificador de formato para seqüência de caracteres e %f o especificador de formato para números em ponto flutuante (números com ponto decimal). Observemos o seguinte comando: 5. printf("os valores sao \n%5d\n%5d\n%.3f\n", v1, v2, v3); • v1 e v2 são duas variáveis de tipo int que contêm os valores 4 e 256 e v3 é uma variável de tipo float contendo o valor 7.54756, por exemplo. As indicações numéricas permitem precisar o modo como esses valores são mostrados na tela. • %5d: exibe o valor correspondente, um valor inteiro, ocupando 5 posições preenchidas a partir da direita. • %.3f: exibe o valor correspondente como uma variável de tipo float com 3 casas decimais, com arredondamento. A saída é então: 00004 00256 7.548 getch(): aguarda a próxima tecla ser pressionada. Isto permite ao usuário ver na tela o resultado exibido pelo programa. #include <stdio.h> int main() { int altura=185; float peso=80.5; char nome[10]="Joao"; printf("%s mede %d cm e pesa %f kg", nome, altura, peso); getch(); return 0; } 299 A instrução return 0; ao fim da função main permite enviar o valor 0 ao sistema o que significa, por convenção, que o programa terminou normalmente. O envio desse valor é obrigatório em C, pois a função main é declarada como sendo do tipo int, logo espera um valor desse tipo. Digitemos o programa abaixo. Antes de executá-lo, procure entender como serão a sua entrada e a sua saída. O objetivo é que ele seja auto-explicativo. Alguns comentários. - algumas palavras estão sem acentuação, pois isto não é permitido na linguagem C, salvo nos comentários; - o texto entre os símbolos /* e */é um comentário e, portanto, não será compilado; - a primeira chamada à função printf serve para orientar o usuário sobre o que ele deve fazer quando da execução deste programa (o que ele deve fazer mesmo?). Experimente retirar esse comando do programa. Ele funcionará corretamente, mas o usuário saberá o que o computador estará esperando como entrada de dados? - na instrução scanf("%d %d %d",&a,&b,&c); os especificadores de formato (%d) podem ser separados por espaço ou não, isto não tem influência no programa; - a cada especificador de formato na função scanf corresponde, em ordem, um argumento a ser lido do teclado; - as próximas chamadas à função printf servem para imprimir (exibir na tela do computador) os valores das variáveis a, b e c; - no início de cada chamada a printf há uma ordem para o computador mudar de linha (\n); - getch() permite que o usuário veja o resultado na tela (fixa a tela de execução do programa). Experimente retirar esse comando do programa e tire suas próprias conclusões. As operações de entrada e saída são básicas no desenvolvimento de um programa. São elas que implementam a interface entre o homem e a máquina. Se por um lado é preciso alimentar o 3.3 Vamos praticar um pouco 4. Avaliando o que foi construído /* Este programa lê 3 valores inteiros */ #include<stdio.h> int main() { int a,b,c; printf("digite 3 numeros inteiros separados por espaco\n"); scanf("%d %d %d",&a,&b,&c); printf("\n valor de a = %d",a); printf("\n valor de b = %d",b); printf("\n valor de c = %d\n ",c); getch(); return 0; } Na plataforma Moodle você encontrará vários exercícios que permitirão consolidar a aprendizagem sobre entrada e saída de dados. Essas operações são importantíssimas e só a prática leva um programador a se sentir à vontade em sua utilização. Então, mãos à obra. 300 computador com dados do mundo exterior a fim de que ele possa realizar alguns processamentos indicados no algoritmo implementado como solução de um problema, por outro precisamos ver os resultado obtidos. Bem formatar esses procedimentos de entrada e saída implica em apresentar um trabalho legível e compreensível. De nada adianta um programa que tenha um bom desempenho nos seus procedimentos internos se não somos capazes de alimentá-los de forma adequada e amigável, com facilidade. 1. Ascencio, Ana F G., Campos, Edilene A V., Fundamentos da Programação de Computadores: Algoritmos, Pascal, C/C++ e Java, 2ª edição, Pearson Education, 2007. 2. Hutchison, Robert C., Just, Steven B., Programming using the C language. Mcgraw-Hill Book Company, 1988. 3. Kernighan, Brian W., Ritche, Dennis M., Le langage C, Masson, 1986. 5. Referências 301 Unidade VI - Estrutura de Controle Condicionais Vimos anteriormente que existem várias linguagens de programação. Algumas delas se parecem muito. A linguagem PHP, por exemplo, foi inspirada na linguagem C. A propósito, a linguagem PHP é muito utilizada na criação de páginas dinâmicas na Internet. Não é o caso da linguagem C. Dando continuidade aos conceitos básicos de programação, veremos agora os condicionais, também conhecidos como « condição » ou « seleção ». Esse conceito é utilizado para selecionar que trecho de um programa deve ser executado sob certas condições. Sem as condições os programas de computador teriam um comportamento "retilíneo", isto é, não seria possível a realização de determinadas operações que envolvem testes de variáveis. Uma condição é o resultado de um teste de comparação. Imaginemos que um programa deve executar a função A ou a função B de acordo com o valor da média aritmética calculada a partir de três notas. Se o valor da média for maior ou igual a 7, então deve ser executada a função A, caso contrário deve ser executada a função B. Assim, em que condição deve ser executada a função A? Obviamente essa função deverá ser executada se o resultado da comparação entre a média calculada e o valor 7 for "a média é superior ou igual a 7". Os símbolos de comparação utilizados na linguagem C são listados na tabela abaixo. Atenção especial é necessária para a comparação de igualdade. Note que o símbolo de comparação é formado por dois símbolos de atribuição (==). Um erro comum entre os iniciantes consiste em fazer essa comparação utilizando um único símbolo de atribuição, o que evidentemente não é um teste de igualdade em C. As condições são representadas em C por estruturas de controle ditas estruturas de seleção, implementadas pelas instruções if e switch. O teste if Este teste consiste em realizar uma operação de comparação e indicar o que deve ser feito quando o resultado da comparação é verdadeiro. Isto é codificado assim: onde expr é uma expressão de comparação. A parte do programa escrita entre as chaves { e } é denominada um bloco de instruções, também chamada simplesmente bloco. A semântica dessa instrução é: se o valor da expressão expr for True (verdadeiro), então o computador deverá executar o bloco de instruções pertencente à instrução e, em seguida, executar a próxima instrução após o if. Caso o valor da expressão condicional seja False (falso), a próxima instrução após o if será executada. 1. Situando a temática 2. Problematizando a temática Símbolo Significado == é igual a > é superior a < é inferior a >= é superior ou igual a <= é inferior ou igual a != é diferente de 3. Conhecendo a temática 3.1 A estrutura if ... else if (expr) { Bloco de instruções } próxima instrução 302 if (idade>=18) { printf(˝ voce eh maior de idade ˝) ; } próxima instrução; #include <stdio.h> int main() { long idade = 25; if (idade >= 18) { printf("Voce eh maior de idade!\n"); } system("PAUSE"); // ou getch() return 0; } Graficamente, a semântica deste teste é representada assim: Problema1. Testar a variável idade, correspondente à idade de uma pessoa. Se o valor dessa idade for maior do que ou igual a 18, imprimir uma mensagem informando esse fato. Observação. Quando há somente uma instrução entre as chaves, estas se tornam facultativas. Pode-se então escrever: if(idade>=18) printf(˝ voce eh maior de idade ˝) ; próxima instrução; Eis ao lado um código completo (código1) que pode ser testado. Este código pode servir de base para testar os exemplos dos próximos testes. Não deixe de fazê-los. Uma questão de legibilidade A disposição das chaves não é muito importante. O programa funcionará também se você escrever assim if(idade>=18) {printf("Voce eh maior de idade!\n");}, mas vemos claramente que a disposição anterior é mais legível. Essa é a recomendação do estilo C. O teste else – o uso de else para dizer "caso contrário" Agora que sabemos fazer um teste simples, é hora de ir um pouco mais longe. Se o teste não funcionar, isto é, se o resultado da avaliação da expressão de comparação for False e a solução que está sendo codificada exigir que seja dito explicitamente ao computador o que fazer, trata-se de outro tipo de teste: if ... else. Para codificar este teste basta adicionar após o bloco correspondente ao resultado True, outro bloco, agora precedido da palavra reservada else. Esse bloco é conhecido como bloco else. Por exemplo, expr Bloco próxima instrução True False . . . . . 303 if (idade>=18) { printf("voce eh maior de idade ") ; } else { printf("voce eh menor de idade") ; } próxima instrução; Se o resultado da expressão de comparação for verdadeiro (True), será executada a instrução printf("voce eh maior de idade") e a execução do programa fará um salto para "próxima instrução". Se o
Compartilhar