Baixe o app para aproveitar ainda mais
Prévia do material em texto
CENTRO UNIVERSITÁRIO VILA VELHA PROGRAMAÇÃO I Elizabeth Maria Klippel Ester Maria Klippel Vila Velha / ES 2008 Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 1 1 - Introdução Esta apostila trata de algoritmos e da implementação de algoritmos em uma linguagem de programação. Esta definição de objetivos deveria introduzir ao leitor as seguintes perguntas: O que é um algoritmo? O que é a implementação de um algoritmo? O que é uma linguagem de programação? Iremos analisar estas e outras questões nesta apostila, começando com o estudo de algoritmos. 1 .1 - Algoritmos Quando trabalhamos em PROGRAMAÇÃO de computadores temos que ORGANIZAR O NOSSO PENSAMENTO de forma a propormos uma solução para o problema que tentamos resolver. Quando organizamos o pensamento utilizamos o RACIOCÍNIO LÓGICO. O raciocínio lógico é usado por todos na solução de diversos problemas cotidianos. Especialmente pelos profissionais de informática, pois seu dia-a-dia profissional consiste em solucionar problemas e atingir os objetivos apresentados pelos usuários, utilizando os recursos computacionais disponíveis com eficiência e eficácia. Esta disciplina não pretende ensinar ninguém a pensar de forma lógica. Todos nós temos este dom. Nosso objetivo é, através de técnicas de programação, aperfeiçoar o uso do raciocínio lógico no desenvolvimento de programas de computador, lembrando que isso exigirá persistência e prática constante, chegando à exaustão sempre que necessário. Pense nisto: ao estudar e criar algoritmos você estará desenvolvendo um raciocínio lógico mais apurado, que lhe proporcionará boas condições quando tiver problemas a analisar, mesmo se esses não puderem ser resolvidos por meio de algoritmos formalmente construídos. Você poderá aproveitar o que aprendeu aqui em outros cursos e em outras leituras. Quando programamos utilizamos a lógica para IDENTIFICAR e SEQÜENCIAR as etapas a serem seguidas para solucionar um problema. Devemos: 1º - Entender o problema. 2º - Analisar o problema e encontrar uma solução. 3º - Analisar a solução para encontrar a melhor forma de implementá-la , considerando: a. as restrições existentes; b. a simplicidade da implementação; c. a elegância; e d. a confiabilidade. Ao definirmos a forma de implementação construímos uma seqüência finita de passos que ao serem executados solucionam o problema, a que chamamos de ALGORITMO. Utilizamos algoritmos quotidianamente, por exemplo, quando seguimos uma receita de omelete: Pegue uma tigela pequena. Acrescente 3 ovos sem casca Acrescente uma colher de café de sal Mexa durante 2 minutos Frite em óleo quente Muito importante, um algoritmo tem que ser executável por um mecanismo. Executar um algoritmo significa realizar efetivamente as instruções. Executável por um mecanismo significa que deve ser possível construir uma máquina que execute o algoritmo de forma autônoma, sem percepção, habilidade, discernimento ou sensibilidade humanos. ALGORITMO é uma lista de instruções que, quando executadas, transformam informações da entrada até a saída. As instruções são um conjunto finito de etapas que podem ser executadas, numa ordem precisa, por um mecanismo determinista. Quando estas etapas são efetivamente executadas, a execução deve terminar em um tempo finito. Existem três aspectos fundamentais nesta definição: Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 2 Expressão finita: Um algoritmo possui uma quantidade finita de instruções. Isto assegura que podemos realmente descrever o algoritmo. Se o algoritmo possuir um número infinito de instruções na sua lista, podemos passar todo o tempo descrevendo-o e jamais conseguir executa-lo. Execução por mecanismo: Deve existir uma máquina que possa realizar – executar – as etapas do algoritmo. O mecanismo é uma parte fundamental no processo de criação de um algoritmo. Execução finita: O algoritmo deve terminar em um tempo finito. A criação de algoritmos significativos pode ser relativamente desgastante para o intelecto. Muitas vezes é difícil de ver como a solução de um problema pode ser encontrada usando um algoritmo. Às vezes, é difícil até mesmo expressar as etapas óbvias em termos de operações que o algoritmo deve fazer. Frequentemente é difícil obter os detalhes corretos e ver as implicações de um conjunto de etapas de um algoritmo. Algoritmos como projetaremos são escritos em símbolos estáticos numa folha de papel (ou num arquivo de computador), mas estes símbolos possuem vida dinâmica quando o algoritmo é executado. Quando você cria um algoritmo, está, consequentemente, tentando imaginar as eventuais implicações de suas instruções. Como exemplo, construiremos um algoritmo para cálculo da média de duas notas de 0 a 10, fornecidas pelo usuário: O computador não possui experiências anteriores, nem poder de discernimento e raciocínio. Temos que fornecer ao computador detalhes de todas as ações que ele deve executar, prevendo todos os obstáculos e a forma de transpô-los. Ou seja, temos que definir uma seqüência finita de passos que garantam a solução do problema. Primeira Solução: Digite a primeira nota Digite a segunda nota Some as notas digitadas Divida a soma por 2 Mostre o resultado na tela Involuntariamente seguimos uma determinada seqüência de ações para representar nosso algoritmo, calculando a média. Mas se o usuário fornecer uma nota inválida (menor que zero ou maior que 10)? Para solucionar este problema, antes de calcular a média devemos verificar se as notas são válidas. Segunda Solução: Digite a primeira nota Digite a segunda nota SE as notas forem válidas inicio Some as notas digitadas Divida a soma por 2 Mostre o resultado na tela fim Agora estamos ligando algumas ações à condição das notas serem válidas. Observe a inclusão de um TESTE SELETIVO que determina quais ações serão executadas (note que antes todas eram). Vamos melhorar a interface do nosso programa. Caso as notas não sejam válidas mostraremos uma mensagem de erro. Terceira Solução: Digite a primeira nota Digite a segunda nota SE as notas forem válidas inicio Some as notas digitadas Divida a soma por 2 Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 3 Mostre o resultado na tela fim SENÃO inicio Mostre na tela a mensagem “valores inválidos digitados para uma ou mais notas.” fim Mudemos um pouco o problema, ainda calcularemos a média de duas notas lidas, porém repetiremos a leitura até que o usuário forneça duas notas válidas. Quando então calcularemos a média. É impossível definir quantas digitações serão necessárias até que o usuário forneça duas notas válidas. Assim repetiremos a leitura até a correta digitação.Quarta Solução: ENQUANTO notas inválidas inicio Digite a primeira nota Digite a segunda nota SE notas inválidas inicio Mostre na tela a mensagem “valores inválidos digitados para uma ou mais notas.” fim fim Some as notas digitadas Divida a soma por 2 Mostre o resultado na tela Nem sempre o primeiro algoritmo proposto representa a melhor solução para o problema. Às vezes é necessário torná-lo mais eficiente. Observando o exemplo vemos que ele pode ser aperfeiçoado, podemos testar cada nota em separado. Quinta Solução: ENQUANTO primeira nota inválida inicio Digite a primeira nota SE primeira nota inválida inicio Mostre na tela a mensagem “valor inválido digitado para a primeira nota.” fim fim ENQUANTO segunda nota inválida inicio Digite a segunda nota SE segunda nota inválida inicio Mostre na tela a mensagem “valor inválido digitado para a segunda nota.” fim fim Some as notas digitadas Divida a soma por 2 Mostre o resultado na tela A condição nota inválida estabeleceu um FLUXO REPETITIVO que será finalizado assim que a condição for falsa, ou seja, que uma nota válida for digitada. Até agora estamos efetuando o cálculo da média de um aluno. Imagine se tivermos que calcular a média de 10 alunos? Uma solução seria repetir o bloco de comandos acima 10 vezes. Poderíamos, entretanto, fazer com que após o cálculo de uma média o fluxo de execução retornasse e executasse novamente o cálculo para duas novas notas. Gerando um FLUXO REPETITIVO por 10 vezes. Sexta Solução: PARA 10 alunos { número de repetições definido } inicio ENQUANTO primeira nota inválida { número de repetições indefinido } inicio Digite a primeira nota Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 4 SE primeira nota inválida { teste condicional } inicio Mostre na tela a mensagem “valor inválido digitado para a primeira nota.” fim fim ENQUANTO segunda nota inválida inicio Digite a segunda nota SE segunda nota inválida inicio Mostre na tela a mensagem “valor inválido digitado para a segunda nota.” fim fim Some as notas digitadas Divida a soma por 2 Mostre o resultado na tela fim 1 .2 – Lista de Exercícios – Testes Lógicos Enumere, utilizando texto ou gráficos, os passos necessários para solucionar os problemas abaixo: 1. Um agricultor está com um problema! Precisa transportar sua carga, que são dois fardos de capim e um carneiro, para a cidade. O problema é que ele só pode transportar uma coisa de cada vez no seu pequeno veiculo. Pior ainda, se ele deixar o carneiro e o capim juntos, o carneiro vai comer o mesmo. Como fazer então para que ele leve sua carga para a cidade sem prejuízo algum? 2. Um senhor de 80kg e suas 2 filhas cada uma com 40kg precisam chegar a uma cidade usando uma bicicleta. Só que há um problema, a bicicleta só suporta 80kg. Como farão para chegar, com o mínimo de viagens? 3. Um homem precisa chegar a uma ilha usando um barco com capacidade para ele e mais uma de suas três cargas: um lobo, um bode e um saco de repolho. Supondo que o homem dispõe apenas do barco e que o lobo e o bode não fogem quando soltos, responda: O que ele deve fazer para chegar a ilha sem perder suas cargas? 4. Três jesuítas e três canibais precisam atravessar um rio, para tal dispõem de um barco com capacidade para 2 pessoas. Organize a travessia de forma que em nenhum momento o número de jesuítas seja inferior ao número de canibais em uma das margens do rio (os tripulantes do barco quando atracado devem ser considerados como presentes na margem), garantindo desta forma a segurança dos jesuítas. 5. Perto de Hanói há um mosteiro em cujo pátio existem 3 postes. Em cima de um deles existem 4 discos, cada um com um buraco no centro e um raio diferente. Cada disco está acima daquele com tamanho imediatamente maior que o seu. A tarefa diária dos monges é mover, com o mínimo de movimentos necessários, os discos para um dos outros postes considerando que apenas um disco pode ser movido de cada vez e que nunca um disco maior pode ser colocado sobre um menor. D C B A 3 2 1 6. Existem 2 jarras, de 4 e 3 litros, sem qualquer marcação de medidas. Estas podem ser cheias e esvaziadas à vontade com água. O que você deve fazer para colocar exatamente 2litros de água na jarra de 4litros? 7. Três recipientes, do maior para o menor, suportam respectivamente os seguintes volumes: o primeiro, 6 litros; o segundo, 5 litros e o terceiro, 1 litro. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 5 A situação atual é a seguinte: no momento, o de 6 litros está com apenas 2 litros, o de 5 litros está com seus 5 litros e o de 1 litro está com 1 litro. Eis o Problema: sabendo-se que os volumes só podem ser manipulados com seus respectivos recipientes, como fazer para distribuir os volumes de modo que o de 5 e o de 6 litros, fiquem com 4 litros cada um? 8. Você possui 16 esferas iguais na aparência, sendo que uma delas pesa ½ quilo e as demais pesam 1 quilo. Usando uma balança de duas bandejas por no máximo 3 vezes descubra qual esfera pesa ½ quilo. 9. Em um quarto existem três interruptores, apenas um deles é capaz de acender um abajur no quarto ao lado. Descubra qual interruptor acende a lâmpada sendo que os interruptores podem ser testados quantas vezes for necessário e que você só pode ir até o quarto ao lado uma única vez. 10. Como, com apenas três cortes retos, dividir este bolo em 8 partes iguais? 11. Usando as operações: PEGAR BLOCO (x) LARGAR BLOCO (x) VERIFICAR BLOCO (x) LIVRE POSICIONAR BLOCO (x) SOBRE ESPAÇO VAZIO POSICIONAR BLOCO (x) SOBRE BLOCO (y) a) a partir da situação inicial obtenha a situação final. b) a partir de qualquer situação inicial obtenha a situação final mostrada no item a). A B C A B C Situação Inicial Situação Final 1.3 – Controle Dinâmico da Execução Os três conceitos de estruturação de algoritmos, seqüência, seleção e iteração descrevem o “controle de fluxo” dinâmico do algoritmo quando ele é executado, e todos os três devem ser expressos de alguma maneira na descrição estática do algoritmo (em uma folha de papel ou em um arquivo de computador). Seqüência especifica uma ordem linear de execução na qual uma tarefa particular é explicitamente indicada para suceder à outra. Esta é a idéia mais simples de execução de um algoritmo. No texto do programa a seqüência é frequentemente induzida, em parte, pela ordem na qual as instruções aparecem na tela. As instruções mais acima são executadas antes das instruções escritas mais abaixo. Seleção é a execução seletiva de um grupo de instruções baseada em alguma condição. A execução seletiva, ou condicional, de instruções num algoritmo nos dá meios de tratar situações nas quais as etapas de transformações de dados diferem em função dos dados a serem transformados. Iteração é a execução repetida de um grupo de instruções atéque alguma condição seja satisfeita. Algoritmos com freqüência precisam fazer o mesmo tipo de trabalho um número repetido de vezes. O termo “Controle de fluxo” é frequentemente usado para descrever esta organização de idéias na declaração e execução de um algoritmo. A cada instante de execução o computador faz uma etapa do algoritmo, e esta seqüência de etapas, alinhadas na ordem de execução, define o caminho, uma linha, Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 6 do principio ao fim do algoritmo. Na expressão estática de um algoritmo existem muitos caminhos potenciais pelos quais a linha poderia passar, mas, durante a execução, as estruturas de controle de fluxo – seqüência, seleção e iteração – direcionam a linha por um caminho específico, determinado dinamicamente em tempo de execução pelos dados a serem transformados. Ao descrever uma seqüência, existe um único caminho potencial para as etapas do algoritmo. Na seleção os caminhos são muitos, ramificando as etapas do algoritmo em caminhos potenciais, mas apenas um destes caminhos será seguido em tempo de execução. Com a iteração, um conjunto de etapas seqüências pode ser repetido várias vezes, até que uma condição seja satisfeita. 2 – Conceitos Fundamentais 2.1 - Modelo de um Computador O Computador é a máquina de execução de um algoritmo programável. Nele podemos introduzir ambos, um algoritmo e dados, fazendo com que os dados sejam transformados pelas etapas executáveis do algoritmo. Ou seja, o computador armazena e opera com os dados, e armazena também o algoritmo que está conduzindo as operações. O computador deve ter muitos recursos, com sugerido na figura abaixo para assegurar nossas necessidades de execução. Sendo capaz de armazenar informações (nossos dados e nossos algoritmos), transformar informações e trocar informações com o meio externo. CPU Memória principal Memória secundária Dispositivos de Entrada/Saída Canal de comunicação - BUS Um computador contém: ? Processador de dados, frequentemente chamado de unidade central de processamento (CPU), que representa o “cérebro” do computador, e é responsável pelo controle de todas as operações realizadas. Este processador é projetado para ler informações da memória do computador e interpretar estes dados como instruções logarítmicas para transformar outros dados na sua memória de entrada em saída. ? Canal de Comunicação (BUS): representa o meio de transferência de dados entre os diversos componentes. ? Memória Principal: para que a CPU possa executar uma seqüência de comandos ou acessar uma determinada informação, é necessário armazenar os comandos e os dados correspondentes na memória principal. A memória principal tem acesso randômico, o que significa que a CPU pode endereçar (acessar) diretamente qualquer posição na memória. Essa memória não é permanente e, para um programa, os dados são armazenados enquanto ele está sendo executado. Normalmente, após o término do programa, a área correspondente ocupada na memória fica disponível para ser usada por outros programas. ? Área de Armazenamento Secundário: Essa memória tem a vantagem de ser permanente, os dados armazenados em disco permanecem válidos mesmo depois de encerrado os programas. Ela tem custo mais baixo do que a memória principal, porém o acesso as dados é bem mais lento. Para que a CPU processe um dado armazenado na memória secundária, é necessário que antes ele seja transferido para a memória principal. ? Dispositivos de Entrada e Saída: os dispositivos de entrada (por exemplo, teclado e mouse) permitem passar dados para um algoritmo, enquanto os dispositivos de saída permitem que um algoritmo exporte seus resultados (por exemplo, monitor e impressora). Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 7 2.2 - Armazenamento de Dados e Programas na Memória A memória do computador é dividida em unidades de armazenamento chamadas bytes, sendo cada byte composto por 8 bits. Cada bit pode armazenar o valor zero (desligado ou desativado) ou um (ligado ou ativado). Cada posição da memória (byte) tem um endereço único, não sendo possível endereçar diretamente um bit. Nada além de zeros e uns pode ser armazenado na memória do computador. Por essa razão, todas as informações (programas, textos, imagens, etc.) são armazenadas com o uso de uma codificação numérica na forma binária (seqüência de oito zeros e uns). Por exemplo, o número 5 é representado na base binária com a seqüência 00000101. Já que só podemos armazenar números na memória. Como armazenar um texto? Para armazenar uma seqüência de caracteres que representa o texto do algoritmo atribui-se, utilizando a tabela ASCII - American Standard Code for Information Interchange, disponível no blog, a cada caractere um código numérico. Assim associa-se ao caractere A o código 65, ao caractere B o código 66, e daí por diante. Se todos os caracteres tiverem códigos associados (inclusive os caracteres de pontuação e formatação), podemos armazenar um texto na memória do computador como uma seqüência de códigos numéricos. A mesma estratégia é usada para executar um programa na memória do computador. Um programa executável é uma seqüência de instruções que a CPU interpreta, executando as operações correspondentes. Essa seqüência de instruções também é representada como uma seqüência de códigos numéricos. 2.3 - Linguagens de Máquina e de Programação O processador (CPU) pode compreender apenas um conjunto específico de instruções, chamado linguagem de máquina, que NÃO é compreensível pelo ser humano e nem é muito significativa. As instruções em linguagem de máquina são blocos de construção muito primitivos, implementar algoritmo usando linguagem de máquina seria como construir um carro começando da fundição do ferro. Não temos interesse em escrever algoritmos em linguagem de máquina. Mas nosso desejo é ter nossos algoritmos executados por computadores que só executa código de máquina. Assim devemos expressar o algoritmo em uma linguagem especial, redigível e legível pelo homem, e que possa ser traduzida em código de máquina. Uma LINGUAGEM DE PROGRAMAÇÃO é uma linguagem bem definida, cujos construtores possuem uma forma precisa (sintaxe) e um significado (semântica) tais que eles podem ser traduzidos mecanicamente em linguagem de máquina. Onde: Sintaxe = como exprimimos uma idéia na linguagem. Semântica = o significado do que exprimimos na linguagem. Muitas linguagens de programação com sintaxes distintas possuem semânticas similares, ou seja, podemos dizer a mesma coisa com elas, mas devemos exprimir nossos pensamentos numa sintaxe diferente. Se deve trabalhar para entender a semântica de várias linguagens de programação. Esta semântica diz o que é possível exprimir na linguagem, é ela que define as instruções básicas usadas na criação de um algoritmo. Sintaxe, embora importante, é secundário. Uma vez que se tenha entendido as idéias da semântica e como usá-las, é possível aprender linguagens com semânticas similares facilmente, basta apenas aprender a sintaxe.Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 8 Quando escrevemos a solução de um problema utilizando uma linguagem de programação ou uma linguagem de máquina estamos construindo um PROGRAMA. Exemplo: última solução proposta para o cálculo e apresentação da média escrito na linguagem C # include<stdio.h> //contém as implementações do printf e scanf # include<stdlib.h> //contém a implementação do system main () { float numero1, numero2; for (int i= 1; i <= 10; i++) { do { printf ("Digite a primeira nota: "); scanf ("%f",&numero1); if ( (numero1< 0) || (numero1> 10)) printf (“\n Primeira nota inválida \n”); } while ( (numero1< 0) || (numero1> 10)); do { printf ("Digite a segunda nota: "); scanf ("%f",& numero2); if ( (numero2 < 0) || (numero2 > 10)) printf (“\n Segunda nota inválida \n”); } while ( (numero2< 0) || (numero2 > 10)); printf("Media: %f\n", (numero1 + numero2)/2); } system("PAUSE"); //exibe a mensagem ”Pressione qualquer tecla para continuar...” e aguarda que algo seja teclado } 2.4 - Construção de Programas Quando programamos, em geral, utilizamos um ambiente integrado de desenvolvimento (IDE – Integrated Development Enviromment), que possui basicamente: ? Um editor de texto, que reconhece o texto como sendo um programa, identificando e destacando os elementos importantes da linguagem. ? Um compilador, que verifica se o texto digitado obedece à sintaxe da linguagem de programação e, caso isso ocorra, traduz o texto para uma seqüência de instruções em linguagem de máquina possíveis de serem executadas. Nós utilizaremos o ambiente de programação Dev-C++ (software livre disponível gratuitamente em http://www.boodshed.net), que utiliza o compilador gcc do Projeto GNU - General Public License (http://www.gnu.org). Esclarecimento: A tradução da linguagem de programação para a linguagem de máquina é necessária porque um programa escrito em uma linguagem de programação não pode ser diretamente executado, pois os computadores só executam programas em Linguagem de Máquina específica a cada modelo de máquina (por exemplo, um PC com o sistema operacional Windows ou um PC com o sistema operacional Linux, são consideradas “máquinas” ou “plataformas” diferentes). Assim o processo de compilação deve ser repetido para cada plataforma. Uma vez que um programa em C compilado para um PC com Windows não pode ser executado em um PC com Linux e vice-versa. Não é possível descrever completamente aqui todas as maneiras pelas quais os textos escritos em linguagens de programação são traduzidos em etapas executáveis. Descreveremos uma destas maneiras em uma forma esquemática: Primeiro - A escrita do algoritmo: Escrevemos um algoritmo como um texto escrito em uma linguagem de programação, e este texto escrito é armazenado em um arquivo. É feito no editor de texto do IDE, gerando o que chamamos de programa fonte. Segundo - A tradução do algoritmo: Como sabemos, para termos efetivamente o nosso algoritmo executado, devemos traduzi-lo em linguagem de máquina e para isto precisamos de um algoritmo – um compilador - para traduzir nosso programa fonte em linguagem de máquina. Não precisamos conhecer este algoritmo (ele é, Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 9 frequentemente, muito complexo e é escrito em linguagem de máquina), mas precisamos ter uma cópia dele no nosso IDE. Ao executar o algoritmo de compilação fornecemos o nosso programa fonte como entrada. O algoritmo de compilação, com a ajuda de outros programas, traduz o programa-fonte em linguagem de máquina, que é armazenado em um novo arquivo pronto para ser executado (um arquivo com extensão *.exe). O processo de compilação, na verdade, se dá em duas fases, como mostra a figura abaixo: - a fase de tradução, que transforma o Programa Fonte em Programa Objeto e - a fase de ligação, que junta o Programa Objeto às instruções necessárias das bibliotecas para produzir o programa executável. Editor Programa Objeto Compilador Programa Fonte Bibliotecas incluídas Programa Executável Ligador Esclarecendo: o trabalho do compilador é pegar um texto escrito na linguagem de programação e traduzi-lo em código de máquina. Ele traduzirá a sintaxe correta em linguagem de máquina preservando a semântica (mantendo o significado do que exprimimos na linguagem). Ele não tem poderes sobrenaturais, nem inteligência, e nem tem meios de saber se o que escrevemos resolverá o problema que temos. Ou seja, se a semântica estiver errada, assim continuará. O compilador não se preocupa com isto. O programa executável, por ser escrito em Linguagem de Máquina, pode ser executado quantas vezes você quiser e em qualquer máquina que possua a mesma Linguagem de Máquina. A máquina em que o programa é executado não precisa ter um Compilador instalado, nem precisa ter acesso ao código C do programa. 2.5 - Linguagem de Programação C A Linguagem de Programação C tem sido amplamente utilizada na elaboração de programas e sistemas nas áreas em que a informática atua, e seu aprendizado tornou-se indispensável para quem trabalha com programação de computadores. Existem muitas informações disponíveis sobre ela, e qualquer dúvida que possa existir pode ser respondida sem muito esforço empregado na pesquisa. O C é uma linguagem de propósito geral, sendo adequada à programação estruturada. É uma grande linguagem, e possui muitos meios de exprimir etapas algorítmicas. Muitas destas construções são centradas em torno da organização e administração de dados, outras existem cuidados de importantes detalhes, como para escrever compiladores, analisadores léxicos, bancos de dados e editores de texto. A linguagem C pertence a uma família de linguagens cujas características são: portabilidade, modularidade, compilação separada, recursos de baixo nível, geração de código eficiente, confiabilidade, regularidade, simplicidade e facilidade de uso. Esclarecendo: Não aprenderemos e nem usaremos todo esta linguagem, mas sim um subconjunto da linguagem e de suas bibliotecas-padrão, que simplificam nosso trabalho quando implementamos algoritmos. Se você quiser usar completamente a linguagem C terá muito mais a aprender. Até aqui introduzimos de forma suscita várias questões: O que são algoritmos? Quais problemas podem ser resolvidos com algoritmos? Como organizar e escrever nossos algoritmos? Com organizar e administrar dados, enquanto nossos algoritmos os transformam? Como testar nossos algoritmos? Como verificar a sua correção? Nas seções seguintes, começaremos a estudar estes assuntos e outros mais. A medida que for construindo o seus algoritmos você deve transcrevê-los em linguagem C, compilá-los com um compilador C e executar o programa resultante. Isto lhe dará imediatamente uma experiência do Centro Universitário Vila Velha Disciplina: Programação I Professores: ElizabethKlippel Ester Maria Klippel 10 processo de compilação e uma apreciação de como o programa-fonte é colocado em ação quando executado pelo computador. Você deve também fazer pequenas modificações e ver seus efeitos. Esta é a melhor maneira de se sentir à vontade com a sintaxe da linguagem e sua semântica. 3 - Estrutura de um Programa em C Para exemplificar a estrutura de um programa em C, apresentaremos o código de um programa simples que recebe dois números inteiros e retorna a média aritmética. Neste momento não deve haver preocupação com o entendimento de todo o código apresentado. As características essenciais da linguagem serão detalhadamente apresentadas e discutidas posteriormente. 1. # include <stdio.h> //contém as implementações do printf e scanf 2. # include <stdlib.h> //contém a implementação do system 3. main () 4. { 5. float numero1, numero2; 6. printf ("Digite o primeiro numero: "); 7. scanf ("%f",&numero1); 8. printf ("Digite o segundo numero: "); 9. scanf ("%f",&numero2); 10. printf("Media: %f\n", (numero1+numero2)/2); 11. system("PAUSE"); //exibe mensagem ”Pressione qualquer tecla para continuar...” e aguarda que algo seja teclado 12. } A idéia central do algoritmo está descrita nas linhas de 5 a 10. O restante do texto é apenas uma massa estrutural que deve existir para suportar qualquer programa, mas que não é a essência do problema. Neste momento vamos analisá-las sem entrarmos em detalhes. Na linha 5 - float numero1, numero2 São criados recipientes de dados capazes de armazenar números fracionários. É feita uma espécie de “apresentação”. Sem esta apresentação o compilador (ou o leitor do programa) não saberia ao certo o que significaria numero1 e numero2 quando eles fossem usados nas linhas 7, 9 e 10. As linhas 7 e 9 - scanf ("%f",&numero1) e scanf ("%f",&numero2) Nestas linhas são obtidos os dados que o programa requer para o calculo da média. São essencialmente comandos do tipo “espere a pessoa que está executando o programa digitar alguma coisa que pareça um número”, e uma vez que a pessoa fez isto, “armazene o numero digitado no recipiente de dados identificado”. O programa para e espera que a pessoa digite alguma coisa no teclado. Obs: As linhas 6 e 8 são usadas para avisar ao usuário o que deve ser informado, melhorando a interface do programa, quefunciona sem elas, apenas fica com uma interface ruim, pois não parecerão as mensagens solicitando a entrada de dados. A linha 10 - printf("Media: %f\n", (numero1+numero2)/2) Calcula a média dos números fornecidos – (numero1+numero2)/2 - e retorna o resultado para a pessoa que deu início a execução. È mostrada na tela do computador à frase Media: <valor da média> Vamos analisar agora as partes que compõem qualquer programa: a – Biblioteca de Funções: Uma biblioteca é uma coleção de rotinas pré-fabricadas fornecidas pela linguagem C que podemos usar quando criamos programas. Usamos uma rotina contida em uma biblioteca fornecendo-lhe dados e esperando o seu resultado. Não precisamos saber como a rotina funciona, como são feitos os cálculos ou, como é o algoritmo. Só precisamos conhecer que tipo de valor ela pode receber e o que ela pode retornar como resultado. Existem muitas rotinas que nos são fornecidas em uma biblioteca e, existem várias bibliotecas disponíveis na linguagem. Cada biblioteca agrupa um conjunto de rotinas com funcionalidades similares. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 11 No nosso exemplo, a biblioteca stdio se fez necessária devido às rotinas printf e scanf. A biblioteca stdlib se deve a rotina system. b - Diretiva de inclusão do pré-processador: Linhas 1 e 2 As bibliotecas são incluídas no programa através de uma diretiva de inclusão do pré-processador #include. O compilador ao encontrar uma instrução #include no programa fonte traduzirá o texto presente no arquivo *.h da mesma forma como faria se o texto tivesse sido digitado no próprio programa- fonte. Temos, por exemplo, na linha 1 uma diretiva de inclusão do pré-processador: #include <stdio.h>. Ela pede ao compilador para encontrar a biblioteca que contem as rotinas usadas para receber e fornecer dados do programa. Isto é efetivamente feito copiando dados do arquivo nomeado, na linha 1 stdio.h, diretamente no programa-fonte antes desse ser processado pelo compilador. Por que é preciso fazer isto? É uma conseqüência do princípio da linguagem C de que todo identificador deve ser declarado antes de ser utilizado. c - Função main – linha 3 Um programa em C deve ter obrigatoriamente a função principal main, uma vez que a execução do programa começa sempre por ela. A execução se inicia na primeira instrução da função main e continua executando seqüencialmente até a última instrução, obedecendo à ordem em que estas estão dispostas no texto. Por enquanto utilizaremos o cabeçalho da função main em sua forma mais simples, como a mostrada no exemplo. Posteriormente retornaremos a este assunto para mais detalhes. d - Chaves – linhas 4 e 12 Os símbolos { e } indicam início e fim de uma instrução composta. A instrução composta do exemplo começa na linha 4 com o { e termina na linha 12 com }. e - Quebra de linha e Recuo à Direta dos Comandos É importante que o programa-fonte seja facilmente legível, não apenas pelo seu autor com também por outras pessoas. Ele deve ser apresentado de forma agradável e ser compreensível por qualquer pessoa que conheça a linguagem. Note que foi colocada uma instrução em cada linha do programa. A linguagem C não impõe esta formatação rígida. Podemos, por exemplo, escrever vários comandos em uma mesma linha. No entanto, para que nosso código possua maior legibilidade, escreveremos, sempre que possível, um comando por linha, recuados à direita, destacando a hierarquia dos comandos. f - Ponto-e-vírgula As linhas de 5 a 11 do programa terminam por ponto-e-vírgula. Estes ponto-e-vírgulas são marcadores fundamentais que descrevem a ordem de execução – o encadeamento – das instruções do nosso código-fonte. As etapas requeridas pela instrução na frente de um ponto-e-vírgula são completadas antes que qualquer instrução escrita após o ponto-e-vírgula comece. Retirar ponto-e-vírgula, ou colocá- los em lugar errado é um erro comum para quem escreve programas usando linguagens da família C. Obs: A linha 3 não termina por um ponto-e-vírgula. Isto ocorre por que main ( ) não é nem uma declaração simples nem uma expressão, ela é uma função que marca através das { e } uma instrução composta. g - Comentários – final das linhas 1, 2 e 11 Os comentários são utilizados para documentação do programa, aumentando a clareza do código-fonte. Estes pedaços do texto são destinados apenas para uso humano – ao leitor do programa - e ignorados durante a compilação. Comentários podem ser incluídos no código fonte utilizando: // para comentários de linha ou /* */ para bloco de comentários. h - Case Sensitive A linguagem C é case sensitive, ou seja, considera diferentes as letras maiúsculas e minúsculas. Assim, por exemplo, o nome da função principal deve ser escrito em letras minúsculas: main. Qualquer outra forma de escrever retornará um erro de sintaxe. i - keywords - Palavras Reservadas da LinguagemSão usadas para estruturação do programa, tais como main e printf. Em geral, são escritas em minúsculas. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 12 j - Identificadores São nomes usados para se fazer referência a variáveis, constantes, tipos, funções, e vários outros objetos definidos pelo usuário. A linha 5, onde foram criados os identificadores para as variáveis numero1 e numero2, é um bom exemplo de um principio importante em C: Todo identificador deve ser declarado antes de ser utilizado. Cada identificador deve identificar um único objeto dentro de um mesmo escopo do programa e deve ser representativo quanto a sua função no programa. Eles podem ser escritos usando letras, dígitos e sublinhado. Sendo que o primeiro caractere deve ser uma letra ou um sublinhado. A forma de escrita de um identificador é de fundamental importância para a qualidade, legibilidade e extencibilidade do programa. Atualmente desenvolvedores do mundo todo tem usado os padrões de nomes sugeridos pela Microsoft, sendo eles: 1. Pascal Case: A primeira letra do identificador e a primeira letra de cada palavra subseqüente concatenada é escrita em maiúscula. Exemplos: SalarioFamilia, DataAniv 2. Camel Case: A primeira letra do identificador é escrita em minúscula e a primeira letra de cada palavra subseqüente concatenada é escrita em maiúscula. Exemplos: salarioFamilia, dataAniv 3. Uppercase: Todas as letras do identificador são escritas em maiúscula. Este padrão deve ser usado apenas para identificadores compostos por poucas letras. Exemplos: ID, CPF Seguindo a sugestão da Microsoft, nós utilizaremos os padrões como mostrado a seguir: Objeto Case Constante Pascal Variável Camel Tipo de Dado Pascal Função Pascal Parâmetro Camel 4 - Tipos de Dados Básicos Para armazenar um dado (uma informação ou um valor) na memória do computador devemos reservar o espaço (em bytes) correspondente ao tipo do dado. A linguagem C possui diversos tipos básicos de dados, nós trabalharemos com os listados abaixo, observe que cada um utiliza um espaço de memória (número de bytes) diferente. Tipo Tamanho (bytes) Valor Faixa de Abrangência char 1 Um caractere ou um inteiro de -128 a 127. Um caractere é representado entre apóstrofos (‘ ’). Observaremos posteriormente que uma seqüência de caracteres é representada entre aspas (“ ”). Um caractere ou um inteiro de -128 a 127. int 4 Um número inteiro. de –2147483648 a 2147483647 float 4 Um número com parte fracionária, com pelo menos 6 dígitos de precisão decimal. de 3.4 E-38 a 3.4 E+38 double 8 Um número com parte fracionária, com pelo menos 10 dígitos de precisão decimal. de 1.7 E-308 a 1.7 E+308 O tipo lógico (falso ou verdadeiro) será simulado. Um valor igual a zero é considerado um valor lógico falso, e qualquer valor diferente de zero (por exemplo, 1) é considerado um valor lógico verdadeiro. Mais tarde usaremos este fato nas condições das estruturas de controle. 5 - Variáveis Quando desenvolvemos um programa este normalmente recebe e processa dados (informações), os quais precisam ser armazenados na memória RAM do computador para que possam ser usados. As variáveis são usadas para permitir o armazenamento e o processamento destes dados. Variável, no sentido de programação, é uma região previamente identificada e que tem por finalidade armazenar temporariamente os dados de um programa. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 13 Lembretes: Uma variável é um identificador, então: a) deve ser declarada antes de ser utilizada. b) cada variável terá um nome único que a identifica. c) o nome pode ser escrito usando letras, dígitos e sublinhado (sendo que o primeiro caractere deve ser uma letra ou um sublinhado). Sintaxe: <tipo de dado> <nome da variável>; onde: <tipo de dado> - determina a natureza do dado que será armazenado. <nome da variável> - serve de referência ao dado armazenado no espaço de memória Quando duas ou mais variáveis forem do mesmo tipo, estas podem ser declaradas juntas, basta separá- las por vírgula. Exemplos: int num; float nota1, nota2; Dê valores significativos a uma variável tão logo seja possível. Quando uma variável é declarada, mas não é inicializada, ela possui um valor, mas não podemos conhecer este valor (não temos como controla-lo). Ter variáveis com valores indefinidos é frequentemente uma fonte de erro no código, ao usá-la antes de fornecer-lhe um valor significativo. Por exemplo, a declaração: int numero; Indica que precisamos de espaço para armazenar um valor inteiro, mas não dá um valor significativo. O próximo comando fornecerá o valor significativo 6. numero = 6; 6 - Constantes Declaramos como constantes dados que permanecerão inalterados durante toda a execução do programa. As constantes são usadas muitas vezes para aumentar a clareza, a facilidade de manutenção e a legibilidade do programa. Sintaxe: #define <nome da constante> <valor> Exemplo: #define Media 7 7 - Operadores Aritméticos Os operadores aritméticos trabalham com operandos numéricos que podem ser dados literais ou variáveis declaradas como tipos numéricos. São eles: Operadores Aritméticos Operador Significado / Função Prioridade - Faz a mudança de sinal do valor numérico 1 * Multiplicação 2 / Divisão 2 % Operador Módulo. Retorna o resto inteiro da divisão. Aplica-se somente a operandos inteiros. 2 + Soma 3 - Subtração 3 Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 14 Exemplos de uso do operador %: 10 % 3 retorna 1 2 % 3 retorna 2 5 % 1 retorna 0 Na linguagem C os tipos dos operando determinam o tipo de resultado. Assim: ? Se os dois operandos forem do tipo int (inteiro) o resultado é int (inteiro). ? Se um dos operandos for float ou double a operação será feita no tipo do operando de maior precisão. Se, por exemplo, somarmos um operando int a um operando double, teremos um resultado double. O operador de divisão merece ser melhor analisado: ? Se os dois operandos forem inteiros o resultado dará inteiro. Por exemplo, a expressão 5/2 resulta no valor 2. O resultado é inteiro já que a operação / é feita na precisão inteira pois 5 e 2 são inteiros. ? Se for necessário obter o resultado da divisão contendo a parte fracionária deve ser utilizado um dos operandos com valor real. Por exemplo, as expressões 5.0/2.0, 5/2.0 ou 5.0/2 resultam no valor real 2.5, uma vez que pelo menos um dos operandos é real. Exemplo utilizando a precisão dos operandos – ele trabalha com 3 variáveis: int a; double b, c; a = 3.5; // armazena o valor 3 na variávela, truncando 0.5 b = a / 2.0; // armazena 1.5 na variável b c = 1 / 3 + b; // armazena 1.5 na variável c, uma vez que, 1/3 resulta no valor 0 As operações são realizadas seguindo a prioridade dos operadores, da maior para a menor. Operadores com a mesma ordem de prioridade são avaliados da esquerda para a direita, ou seja, o operador que aparece primeiro será calculado primeiro. Assim, na expressão: 5 + 2 * 6 / 3 Executa-se 1º a multiplicação, seguida da divisão e da soma. Tendo como resultado o valor 9. A Ordem de Prioridade pode ser alterada através dos parênteses. Uma expressão dentro dos parênteses é calculada antes de qualquer operação fora dos parênteses. Assim, na expressão: (5 + 2) * 6 / 3 Executa-se 1º a soma seguida da multiplicação e divisão. Tendo como resultado o valor 14. Dica: Parênteses devem ser usados para tornar clara a ordem de avaliação das expressões. Isto aumenta a legibilidade e torna menos provável a introdução de erros no código do programa. 8 - Operadores de Atribuição Um valor pode ser atribuído a uma posição de memória representada por uma variável através do operador de atribuição =. Por exemplo, int x; x = 5; Armazena o valor 5 na posição de memória reservada para a variável x. Observe que o operador = de atribuição tem à esquerda um nome de variável e à direita um valor ou uma expressão que retorne um valor de mesmo tipo que a variável. É importante pensar em atribuição como uma operação ativa. O símbolo = é um pedido para armazenar o dado que está a direita do operador na variável que se encontra a esquerda. Cuidado: O símbolo = não é uma afirmação de igualdade. É bem provável que você, uma vez ou outra, esqueça isto e use a atribuição onde pretendia usar a igualdade ou a use invertida. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 15 Só podemos atribuir valores do mesmo tipo declarado a uma variável. Não é possível, por exemplo, armazenar um valor real em uma variável inteira. Se fizermos: int x; x = 4.3; Será armazenado em x apenas a parte inteira do número real, isto é, 4. Alguns compiladores exibem uma advertência quando encontram este tipo de atribuição. Uma exceção permitida é a atribuição de um valor inteiro a uma variável float ou double, neste caso o valor inteiro é automaticamente convertido para float ou double. Com o comando de atribuição é possível: ? Inicializar as variáveis durante a declaração. int x = 3, y = 4; ? Atribuir valores a mais de uma variável ao mesmo tempo. Neste caso a ordem de avaliação é da direita para a esquerda. y = x = 5; Primeiro armazena 5 em x, e, em seguida, armazena em y o valor produzido por x = 5, que é 5. ? Utilizar os chamados operadores de atribuição compostos, onde a variável aparece em ambos os lados do comando de atribuição. i = 2; i = i + 3; Que resulta no valor de i sendo igual a 5 (2 + 3). Dica: Os operadores de atribuição compostos podem ser escritos na forma compacta. i += 3 é igual a i = i +3 As formas compactas são: +=. - =, *=, /= e %=. 8.1 - Operadores de Incremento e Decremento Uma operação muito comum em programação e o incremento ou decremento de uma unidade no valor de uma variável. A linguagem C traz dois operadores, ++ e --, para facilitar estas operações. Assim, ao invés de escrevermos x = x + 1 podemos escrever x++. Analogamente, no lugar de x = x – 1 podemos escrever x--. Os operadores ++ e -- podem ser prefixos ou sufixos ao nome da variável. Quando a operação de incremento ou decremento aparece isolada não faz diferença usar o operador como prefixo ou sufixo. Exemplo: int x = 5; x++; // resulta em x=6 x = 5; ++x; // resulta em x=6 Contudo, quando a operação de incremento ou decremento faz parte de uma expressão faz muita diferença usar o operador como prefixo ou sufixo. Exemplo: int y; int x; x = 5; y = x++ + 2; // equivalente a y = x + 2; seguido de x = x + 1; resulta em y = 7 (5+2) e x = 6 x = 5; y = ++x + 2; // equivalente a x = x + 1; seguido de y = x + 2; resulta em x = 6 e y = 8 (6+2) Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 16 9 - Funções de Entrada e Saída de Dados Um programa para ser útil deve, normalmente, receber dados do ambiente externo e sempre, de algum modo, retornar dados para este ambiente. Entrada - são dados que devem ser fornecidos a um programa para que ele execute e realize sua função. Saída - são dados que um programa fornece ao ambiente externo. Para cada programa devemos definir uma interface descrevendo: 1. Quais dados o programa precisa, e como eles são passados ao programa. 2. Quais dados de saída o programa retornará ao ambiente de chamada, e como esta saída será devolvida. Utilizaremos a função scanf para a entrada de dados e a função printf para a saída de dados. Ambas são encontradas na biblioteca stdio.h. 9.1 - Função de Saída de Dados Transmite para o ambiente exterior um ou mais valores, permitindo ao usuário acesso aos resultados obtidos pelo programa. Adotaremos o monitor como dispositivo de saída padrão. Sintaxe: printf (<formatos>, <lista de constantes/variáveis/expressões> ); Onde <formatos> é uma cadeia de caracteres, delimitada por aspas, que contém o formato de saída das constantes, variáveis e expressões listadas a seguir. Na <lista de constantes/variáveis/expressões>, para cada valor que se deseja imprimir, deve existir ordenadamente um especificador de formato correspondente na cadeia de caracteres <formatos>. Os diversos valores devem ser separados por vírgula. Os especificadores de formato (ou tags) variam com o tipo do valor e a precisão com que queremos que sejam impressos. Estes especificadores são precedidos pelo caractere % e podem ser, entre outros: Especificador ou Tag Significado %c Especifica um char %d Especifica um int %f Especifica um double ou float %e Especifica um double ou float no formato científico %s Especifica uma cadeia de caracteres A precisão é informada após o símbolo %, como mostrado a seguir: %7f – especifica a impressão de um double ou float usando no mínimo 7 caracteres (incluindo os dígitos, o sinal e o ponto decimal, se houver). %7.2f – especifica a impressão de um double ou float usando no mínimo 7 caracteres, fixando 2 casas decimais. Espaços em branco por ventura existentam são alinhados à esquerda. %.2f – especifica a impressão de um double ou float fixando 2 casas decimais. Se o tamanho do campo for maior do que o necessário para a impressão é incluído caracteres brancos à esquerda. Se o tamanho do campo for menor que o necessário para a impressão este é ignorado e o número é impresso normalmente. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth KlippelEster Maria Klippel 17 Exemplo: Comando Valor Impresso float x = 21.5687124; printf("%5f", x); 21.568712 printf("%7.2f", x); 21.57 printf("%5.2f", x); 21.57 printf("%.3f", x); 21.569 Existem ainda outros caracteres de escape freqüentemente usados nos formatos de saída. Entre eles: Caracter de Escape Significado \n Imprime uma nova linha \t Imprime uma tabulação horizontal \” Imprime o caractere “ \\ Imprime o caractere \ Exemplos: printf (“Salário Mensal: R$ %7.2f \n”, salarioFunc); printf (“Média: %5.2f Total de Faltas: %d, (nota1 + nota2)/2, faltas); 9.2 - Função de Entrada de Dados Permite que uma ou mais variáveis recebem dados do ambiente exterior. Adotaremos o teclado como dispositivo de entrada padrão. Como no comando de atribuição o valor transferido para a variável deve ser compatível com o tipo para ela declarado. Sintaxe: scanf (<formatos>, <lista de endereços das variáveis>); Onde <formatos> possuem especificadores similares aos usados pela função printf. Exceção para os tipos float e double que possuem especificadores distintos. Especificador Significado %c Especifica um char %d Especifica um int %f Especifica um float %lf Especifica um doble %s Especifica uma cadeia de caracteres Na <lista de endereços das variáveis> é necessário passar o endereço de cada variável, isto é feito escrevendo o operador & antes do nome de cada variável. Exemplos: float salario; char sexo; int idade; printf (“Digite o salário: ”); scanf (“%f”, &salário); printf (“Digite a idade e o sexo: ”); scanf (“%d %c”, &idade, &sexo); Quando uma instrução como scanf(“%f”, &salario); é realizada a execução do programa é interrompida e o computador fica aguardando que o usuário digite um valor correspondente ao tipo da variável e, em seguida, pressione enter. Ao reconhecer que o usuário pressionou enter o computador armazena o valor digitado na variável e volta à execução do programa. Vale ressaltar que o especificador %c não pula os caracteres brancos (caractere espaço ‘ ‘, caractere de tabulação ‘\t’ ou caractere de nova linha ‘\n’). Assim, se o usuário teclar um caractere branco antes de Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 18 teclar o caractere a ser lido, o código do branco será capturado, e o caractere que realmente interessava somente será capturado em uma nova chamada da função scanf. Para resolver este problema, ou seja, se desejarmos ignorar todas as ocorrências de caracteres brancos que, porventura, antecedam o caractere que desejamos capturar, basta incluir um espaço em branco no formato, antes do especificador. Exemplo: char sexo; printf (“Digite o sexo: ”); scanf (“ %c”, &sexo); Outra forma de resolver o problema é usar a função fflush com o argumento stdin antes da execução de um scanf com o especificador %c. A função fflush (stdin) limpará o buffer associado ao teclado (stdin – standard input). Exemplo: char sexo; printf (“Digite o sexo: ”); fflush (stdin); scanf (“ %c”, &sexo); 10 – Exercícios - Seqüência Simples de Comandos Desenvolveremos agora alguns exercícios que realizam cálculos simples. Estes exercícios são todos de avaliações de fórmulas, e como tais, não sugerem ainda todo o poder da programação. Mas até conhecermos os comandos de seleção e de repetição estes exercícios são tudo o que podemos fazer. Você irá observar que a analise do problema e a confecção da solução é frequentemente mais importante e mais difícil que a implementação. É importante que você faça os programas também no computador, assim você ganhará intimidade com a linguagem. Faça também, após a primeira solução, algumas modificações, aprimorando os seus programas. Ao terminar a implementação verifique se o seu programa fornece resultados corretos. Mas como fazer isto? Na maioria dos problemas não conhecemos a resposta correta, mas podemos aumentar a nossa confiança na correção de um código. Dica: “Podemos raramente dizer com convicção que alguma coisa está correta, mas podemos frequentemente dizer com toda a certeza que ela está errada”. Sendo assim: 1- Raciocine cuidadosamente acerca do algoritmo de solução construído. 2- Verifique casos especiais. 3 - Por intuição de uma solução para uma entrada simples e verifique o resultado. 1. Escreva um código que pede ao usuário a base, altura de um retângulo e em seguida lhe apresente a área e perímetro deste retângulo. 2. Faça um programa que calcule e apresente o volume de uma esfera em função do seu raio R. Sendo o valor de R solicitado ao usuário do programa. Obs.: Volume = 4πR3. 3. Faça um programa que receba do usuário uma temperatura em graus Fahrenheit (F) e a apresente em graus Celsius (C). Obs.: A fórmula para conversão é C = (F-32)* 5/9. 4. Faça um programa que apresente a distância percorrida e a quantidade de litros de combustível gastos em uma viagem por um automóvel que faz 12 quilômetros por litro. Para realizar o cálculo são fornecidos o tempo gasto na viagem e a velocidade média durante a mesma. Obs.: Distância = Tempo*Velocidade média Com sumo = Distância / 12. 5. Escreva um código que pede ao usuário o salário de um funcionário e em seguida lhe apresente o novo salário sabendo-se que este sofreu um aumento de 25%. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 19 6. Faça um programa que pede ao usuário o valor de um depósito e o valor da taxa de juros e em seguida lhe apresente o valor do rendimento e o valor total depois do rendimento (deposito mais rendimento). 7. Escreva um código que pede ao usuário dois valores reais para as variáveis A e B e efetua a troca dos valores de forma que a variável A passe a possuir o valor da variável B e que a variável B posse a possuir o valor da variável A (troque as informações nas posições de memória). Apresente os novos valores de A e B. 8. Faça um programa que solicite ao usuário o ano de nascimento de uma pessoa e o ano atual e apresente a idade dessa pessoa em anos. 9. Escreva um código que retorne o cálculo da equação abaixo (o valor de x). Os valores de a, b, c são solicitados ao usuário. x = ((a + (2* b + c) * c) / a *a 10. Escreva um código que retorne a solução para o sistema de equações lineares abaixo (os valores de x e y). Os valores de a, b, c, d, u, v são solicitados ao usuário. ⎩⎨ ⎧ == =+ vdycx ubyax Dica - Você pode usar os seguintes cálculos: )()()()( bcadcubcadavyebcadbvbcaddux −−−= = − − − 11. Faça um programa que apresente o volume de um cilindro de altura A e raio R. Sendo os valores de R e A solicitados ao usuário do programa. Obs.: Volume = AπR2. 12. Construa um programa que solicite ao usuário o raio de um círculo e retorne o perímetro. Obs.: perímetro = 2πRaio. 13. Faça um programa que solicite ao usuário três notas e retorne a média aritmética entre essas notas. 14. Faça um programa que solicite ao usuário duas notas (n1 e n2) e seus respectivos pesos (p1 e p2) e retorne a média ponderada dessas notas. Obs.: média ponderada = (p1*n1+ p2*n2)/ (p1+p2) 15. Faça um programa que solicite ao usuário o valor do salário de um funcionário e o valor do salário mínimo e apresente quantos salários mínimos ganha esse funcionário. 16. Faça um programa que solicite ao usuário a idade de uma pessoa em anos e apresente essa idade em meses, dias, horas e minutos. 17. Escreva um código que pede ao usuário a base, altura de um triângulo retângulo e em seguida lhe apresente a área. 18. Faça um programa que pede ao usuário o salário de um funcionário e em seguida lhe apresente o valor do imposto de renda a ser pago, sabendo que o imposto equivale a 5% do salário. 19. Sabe-se que o quilowatt de energia custa um quinto do salário mínimo. Faça um programa que pede ao usuário o valor do salário mínimo e a quantidade de quilowatts gasta por uma residência. Calcule e apresente: • O valor de cada quilowatt; • O valor a ser pago por essa residência; • O novo valor a ser pago por essa residência, a partir de um desconto de 15%. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 20 20. Faça um programa que solicite ao usuário o peso de uma pessoa, um valor inteiro, e apresente peso dessa pessoa em gramas. Apresente, também, o novo peso em gramas se essa pessoa engordar 5%. 11 - Operadores Relacionais São usados para comparar dois valores. São eles: Operadores Relacionais Operador Significado = = Igual a != Diferente de > Maior que < Menor que >= Maior ou igual a <= Menor ou igual a As expressões relacionais retornam os valores zero (falso) ou diferente de zero (verdadeiro). A prioridade dos operadores segue a precedência posicional, ou seja, o operador que primeiro aparece na expressão tem maior prioridade. Os parênteses podem ser usados para alterar a prioridade. Exemplo: Supondo A = 10 e B = 5, temos: A > B não retorna 0 - verdadeiro (A = = B) != (5 < B) retorna 0 - falso 12 - Operadores Lógicos São utilizados para combinar expressões booleanas. São eles: Operadores Lógicos Prioridade Símbolo Operador 1 ! Operador unário de negação NÃO 2 && Operador binário E 3 || Operador binário OU Expressões conectadas por !, &&, ou || são avaliadas da esquerda para a direita, e a avalição pára assim que a veracidade ou a falsidade do resultado for conhecida. O resultado obtido será sempre um valor 0 (falso) ou diferente de zero (verdadeiro). Os parênteses podem ser usados para mudar a prioridade das operações. Operador NÃO: ! <operando> Inverte o estado lógico do operando, como mostra a tabela abaixo. Operando: p Resultado: ! p V F F V Exemplo: Supondo a verdadeiro, temos: !a resultando 0 - falso ! !a não resultando 0 - verdadeiro Operador E: <operando 1> && <operando 2> Retorna verdadeiro somente quando todos os operandos são verdadeiros, como mostra a tabela abaixo. Operando 1: p Operando 2: q Resultado: p && q V V V V F F F V F F F F Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 21 Exemplo: Supondo a verdadeiro e b falso, temos: a && b resultando 0 - falso a && !b não resultando 0 - verdadeiro !(b && a) não resultando 0 - verdadeiro Operador OU: <operando 1> || <operando 2> Retorna verdadeiro sempre que um dos operandos for verdadeiro, como mostra a tabela abaixo. Operando 1: p Operando 2: q Resultado: p || q V V V V F V F V V F F F Exemplo: Supondo a verdadeiro e b falso, temos: a || b não resultando 0 - verdadeiro !a || b resultando 0 - falso ! (b || a) resultando 0 - falso a || b && !a não resultando 0 - verdadeiro 13 - Expressões Mistas Como os operadores aritméticos, relacionais e lógicos podem ser combinados dentro de uma mesma expressão a prioridade entre eles deve ser observada. Os parênteses podem ser usados para mudança na prioridade. Prioridade Operador 1 ! 2 *, /, %, && 3 +, -, || 4 = = , !=, >, <, >=, <= Exemplo: Supondo x = 3, y = 1 e b falso, temos: !(x < y + 2) || !b não resultando 0 – verdadeiro. Observe que !b não chega a ser avaliada, pois, independente do seu resultado a expressão terá como resultado verdadeiro, uma vez que !(x < y + 2) tem valor verdadeiro. 14 - Comandos de Seleção São comandos que causam desvio no processamento, permitindo que um determinado bloco de comandos possa ser escolhido ou não para a execução. 14.1 - Comando if Sintaxe: if ( <condição> ) { <bloco de comandos> } A <condição> deve ser uma expressão que retorne um valor falso (0) ou verdadeiro (diferente de 0). Quando a <condição> retorna o valor lógico verdadeiro o <bloco de comandos> é executado. Caso contrário, o comando seguinte ao comando if é executado. As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando. Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 22 14.2 - Comando if/else Sintaxe: if ( <condição> ) { < bloco de comandos 1 > } else { < bloco de comandos 2 > } Quando a <condição> retorna o valor lógico verdadeiro o <bloco de comandos1> é executado. Caso contrário, o < bloco de comandos2> é executado. As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando. 14.3 - Comando switch Sintaxe: switch ( <seletor> ) { case <valor1> : < bloco de comandos executado se seletor = = valor1 >; break; case <valor2> : < bloco de comandos executado se seletor = = valor2 >; break; ... default : < bloco de comandos executado se seletor diferente de todos os valores >; break; } Permite que um ou mais < blocos de comandos> sejam executados, dependendo do valor do <seletor>. O valor do <seletor> é comparado com cada um dos <valores>. Se existir um <valor> igual ao do <seletor> o < bloco de comandos> relacionado é executado até encontrar um break. Se o comando break for omitido a execução continua com os comandos dos case seguintes. Se o valor do <seletor> for diferente de todos os valores dos case o < bloco de comandos> relacionado a clausula default é executado. A clausula default é opcional e pode aparecer em qualquer posição, mas normalmente é colocada no final. O <seletor> deve ser um número inteiro ou um caracter. Quando um mesmo < bloco de comandos> deve ser executado para diferentes valores, devemos encadear uma seqüência de case sem break, e o< bloco de comandos> é colocado no último dos case, que conterá um break. Exemplo: #include <stdio.h> #include <stdlib.h> Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 23 main() { int n; printf("Digite um numero inteiro no intervalo [2, 6]: "); scanf ("%d", &n); switch (n) { case 2 : case 4 : case 6 : printf("numero par\n"); break; case 3 : case 5 : printf("numero impar\n"); break; default : printf("valor fora do intervalo\n"); break; } system("PAUSE"); } 14.4 – Exercícios – Comandos de Seleção 1. Faça um programa que receba 2 números, some-os e retorne o resultado caso a soma seja maior que 10. 2. Faça um programa que receba um número inteiro e mostre a mensagem ‘Número par!’ caso ele seja divisível por 2. 3. Faça um programa que solicite ao usuário 2 números inteiros para as variáveis A e B. Caso A seja maior que B e B seja par, efetue a troca dos valores de forma que a variável A passe a conter o valor da variável B e, a variável B posse a conter o valor da variável A. 4. Faça um programa que solicite ao usuário dois valores numéricos e lhe apresente a diferença do maior pelo menor. 5. Faça um programa que receba um número inteiro e retorne uma mensagem dizendo se ele é par ou impar. 6. Faça um programa que verifique a validade de uma senha fornecida pelo usuário. A senha correta é o número: 12345. O programa deve retornar uma mensagem permitindo ou negando o acesso. 7. Faça um programa que solicite ao usuário dois valores numéricos e retorne o maior deles. Caso os números sejam iguais retorne a mensagem ‘Números iguais!’. 8. Faça um programa solicite o salário de um funcionário, calcule e retorne o desconto feito sobre este salário, sabendo que: a) se salário < R$ 1000, 00, desconto de 5% sobre o salário; b) se salário >= R$ 1000, 00 e <= R$2000,00, desconto de 10% sobre o salário; c) se salário > R$ 2000, 00, desconto de 15% sobre o salário; 9. Faça um programa que receba três números distintos e retorne o maior. 10. Faça um programa que receba a idade de uma pessoa e retorne a sua classificação utilizando a seguinte tabela: Idade Classificação 0 a 2 anos Neném 3 a 11 anos Criança 12 a 19 anos Adolescente 20 a 75 anos Adulto Acima de 75 anos Idoso Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 24 11. Faça um programa que solicite ao usuário três valores numéricos e apresente estes valores em ordem crescente. 12. Faça um programa que solicite uma vogal maiúscula e apresente a vogal subseqüente. 13. Solicite um caracter e retorne a mensagem ‘É uma vogal!’, caso o caracter lido seja uma vogal. Caso contrário retorne ‘O caracter lido não é uma vogal!’. 14. Solicite ao usuário o mês e o ano (em números) e exiba o número de dias do mês digitado. Obs.:- meses com 30 dias: 4, 6, 9, 11 - meses com 31 dias: 1, 3, 5, 7, 8, 10, 12 - fevereiro possui 28 dias em ano não bissexto e 29 dias em ano bissexto. Um ano é identificado como bissexto quando é divisível por 4 e não é divisível por 100; ou, quando é divisível por 400 e por 100. 15. Solicite ao usuário o número de um mês e retorne o nome do mês por extenso. 16. Solicite ao usuário uma data (dia, mês e ano) em valores numéricos e a retorne por extenso como mostrado no exemplo abaixo: Lido: 21/04/1970 Escrito: 21 de abril de 1970 17. Faça um programa que, tendo recebido 3 inteiros correspondentes ao dia, mês e ano de uma data, retorne o número de dias transcorridos do primeiro dia do ano até o dia/mês da data em questão. 18. Faça um programa que solicite ao usuário as 2 notas e o número de faltas semestrais de um determinado aluno e calcule sua média aritmética. Retorne a média e uma mensagem informando a situação final do aluno. O aluno estará aprovado caso sua média seja maior ou igual a 7. O aluno terá direito a uma recuperação caso sua média seja maior ou igual a 3, caso contrário estará reprovado. Mesmo que possua média para aprovação ou recuperação, o aluno estará reprovado caso possua mais de 20 faltas. 19. Faça um programa que solicite a matrícula, o número de horas de trabalho e o salário/hora do funcionário de uma empresa. Calcule e retorne os salários bruto e liquido, que são obtidos através das fórmulas: Bruto = Numero_horas * Salário_hora Liquido = Bruto + Gratificação - Descontos onde : • funcionário com mais de 160 horas de trabalho têm direito a 20% de gratificação; • funcionário com 160 horas ou menos têm direito a 10% de gratificação; • o desconto é igual para todos, isto é: 10% - INPS e 18% - imposto de renda Obs: os percentuais são calculados com base no salário bruto. 20. Faça um programa que solicite a altura e o sexo de uma pessoa, calcule e retorne o seu peso ideal, utilizando as fórmulas abaixo. Assuma M ou F como sendo os valores válidos para o sexo de uma pessoa. • para homens: (72.7 * ALTURA) – 58 • para mulheres: (62.1 * ALTURA) – 44.7 21. Uma empresa decide dar um aumento de 4% aos funcionários cujo salário é inferior a 500 reais. Escreva um programa que receba o salário de um funcionário e retorne o valor do salário reajustado ou uma mensagem caso o funcionário não tenha direito ao aumento. 22. Faça um programa que receba a idade de uma pessoa e informe uma mensagem se esta alcançou ou não a maioridade. Assuma que a maioridade ocorre somente aos 21 anos. 23. Faça um programa que receba a idade de um nadador e informe sua categoria utilizando: Categoria Idade Infantil A menos de 7 anos Centro Universitário Vila Velha Disciplina: Programação I Professores: Elizabeth Klippel Ester Maria Klippel 25 Infantil B 7 a 10 anos Juvenil A 11 a 13 anos Juvenil B 14 a 17 anos Adulto maiores de 18 anos 24. No curso de Introdução a Computação, a nota final do estudante é calculada a partir de 3 notas atribuídas respectivamente a um trabalho de laboratório, a uma avaliação semestral e a um exame final. As notas variam de 0 a 10 e a nota final é a média ponderada das 3 notas mencionadas. A tabela abaixo fornece os pesos das avaliações. Avaliações Peso trabalho de laboratório peso 2 avaliação semestral peso 3 exame final peso 5 Faça um programa que receba as 3 notas, calcule e retorne a média final e o conceito desse estudante. O conceito segue a tabela abaixo. Média Final Conceito 8.0 |___| 10.0 A 7.0 |___ 8.0 B 6.0 |___ 7.0 C 5.0 |___ 6.0 D < 5.0 E 25. Faça um programa que receba o preço de um produto e o seu código de origem (número inteiro) e
Compartilhar