Baixe o app para aproveitar ainda mais
Prévia do material em texto
Faculdade SATC Técnicas de Programação Linguagem C Engenharia Mecânica Profº.: Giovani Martins Cascaes giovani.cascaes@satc.edu.br http://www.satc.edu.br/ versão 1.03.178 2015/2016 Sumário Listas de Figuras ................................................................................................... 5 Lista de Tabelas ................................................................................................... 6 Introdução ............................................................................................................ 7 1.1 Definições de algoritmos ......................................................................................... 8 1.2 Formas de representações de algoritmos ................................................................. 9 1.2.1 Descrição narrativa ........................................................................................... 9 1.2.2 Fluxogramas .................................................................................................... 12 1.2.3 Português estruturado ou pseudocódigo ........................................................ 13 1.3 A linguagem C ...................................................................................................... 15 Tipos, bases, expressões e funções ....................................................................... 19 2.1 Memória ................................................................................................................ 21 2.2 Bases ...................................................................................................................... 22 2.3 Declarações de variáveis ......................................................................................... 25 2.4 Definindo contantes .............................................................................................. 28 2.5 A função printf() .................................................................................................... 30 2.6 A função scanf() ..................................................................................................... 32 2.7 Expressões .............................................................................................................. 34 2.7.1 Expressões Aritméticas ................................................................................... 34 2.7.2 Expressões Condicionais ................................................................................ 38 2.7.3 Funções primitivas .......................................................................................... 41 2.7.4 Prioridade de operadores ................................................................................ 43 O controle do fluxo de execução ......................................................................... 49 3.1 Sequências .............................................................................................................. 49 3.2 Seleção ou if ........................................................................................................... 49 3.3 Switch case ............................................................................................................. 56 3.4 Repetições .............................................................................................................. 62 3.4.1 Comando while .............................................................................................. 62 3.4.2 Comando do while ......................................................................................... 65 3.4.3 Comando for .................................................................................................. 67 Funções .............................................................................................................. 79 4.1 Protótipos de funções ............................................................................................ 81 4.2 Escopo de variáveis ................................................................................................ 82 4.2.1 Variáveis locais ................................................................................................ 83 4.2.3 Variáveis globais ............................................................................................. 86 4.2.4 Parâmetros formais ......................................................................................... 87 4.2.5 Passagem de parâmetros por valor.................................................................. 87 4.2.6 Passagem de parâmetros por referência .......................................................... 87 4.2.7 O comando de returno ................................................................................... 88 4.3 Funções sem retorno (void) ................................................................................... 88 4.4 Funções getche() e getch() ..................................................................................... 91 4.5 Funções getchar() e putchar() ................................................................................ 93 Arranjos ........................................................................................................... 100 5.1 Vetores ................................................................................................................. 102 5.2 Vetores de caracteres ........................................................................................... 106 5.2.1 Funções para manipulação de vetores de caracteres ..................................... 111 5.3 Matrizes ............................................................................................................... 118 5.3.1 Matrizes bidimensionais ............................................................................... 118 5.3.2 Matrizes de cadeias de caracteres ................................................................. 120 5.3.3 Passagem de vetores e matrizes .................................................................... 121 5.4 Definição de estruturas ........................................................................................ 125 5.5 Enumerações ....................................................................................................... 127 5.6 Definição de nomes de tipos ............................................................................... 130 Ponteiros .......................................................................................................... 137 6.1 Aritmética de Ponteiros ....................................................................................... 139 6.2 Ponteiros e Arranjos ............................................................................................ 140 6.3 Ponteiro como argumento de funções ................................................................. 144 Estruturas de dados .......................................................................................... 154 7.1 Filas ...................................................................................................................... 154 7.1.1 Filas com prioridades .................................................................................... 158 7.2 Pilhas ................................................................................................................... 160 Bibliografia ....................................................................................................... 174 Anexo A - Palavras reservadas em C e C++ ....................................................... 176 Anexo B – Tabela de caracteres ASCII ............................................................. 177 Obs.: Este material foi adaptado da apostila do Prof.º Ivan L. M. Ricarte lotado no Departamento de Engenharia de Computação e Automação Industrial da Unicamp. Os exercícios presentes nas listas em cada capítulo desta, foram retirados ou adaptados de livros e páginas da internet e pertencem a seus respectivos donos. Listas de Figuras Figura 1.1 – Etapas que antecedem o desenvolvimento de programas. ................... 7 Figura 1.2 – Fluxograma cálculo do Triplo de um Número. ................................. 12 Figura 1.3 – Fluxo no compilador C. .................................................................. 17 Figura 2.1 – Complemento de base (2) ................................................................ 24 Figura 2.2 – Declarando variáveis. ...................................................................... 25 Figura 2.3 – Declarando constantes. ................................................................... 28 Figura 2.4 – Atribuição. ...................................................................................... 34 Figura 3.1 – Fluxograma para estrutura if. ........................................................... 50 Figura 3.2 – Seleção com if ... else em C. ............................................................ 52 Figura 3.3 – Seleção usando switch ... case em C. ............................................... 60 Figura 3.4 – Seleção usando switch ... case em C, omitindo-se o break. ............... 61 Figura 3.5 – Repetição usando while ... em C. ..................................................... 62Figura 3.6 – Repetição usando for em C. ............................................................ 68 Figura 3.7 – Repetição usando for ... em C. ........................................................ 69 Figura 5.1 – Armazenando caracteres na memória RAM. .................................. 107 Figura 6.1 - Espaço ocupado pelas variáveis. ..................................................... 138 Figura 7.1 – Fila com prioridade descendente. .................................................. 159 Lista de Tabelas Tabela 2.1 – Tipos de dados em C ...................................................................... 19 Tabela 2.2 – Caracteres de controle .................................................................... 21 Tabela 2.3 – Exemplos de nomes de variáveis ...................................................... 26 Tabela 2.4 – Operadores aritméticos ................................................................... 35 Tabela 2.5 – Operadores relacionais .................................................................... 39 Tabela 2.6 – Operadores lógicos ......................................................................... 40 Tabela 2.7 – Tabela verdade dos operadores lógicos &&, || e !. ........................... 40 Tabela 2.8 – Funções Primitivas ......................................................................... 42 Tabela 2.9 – Prioridade de operadores ................................................................ 43 1 Introdução A automatização de tarefas é um aspecto marcante da sociedade moderna. O aperfeiçoamento tecnológico alcançado teve como elementos fundamentais a análise e a obtenção de descrições da execução de tarefas em termos de ações simples o suficiente, tal que pudessem ser automatizadas por uma máquina especialmente desenvolvida para este fim, o Computador. Em ciência da computação houve um processo de desenvolvimento simultâneo e interativo de máquinas (hardware) e dos elementos que gerenciam a execução automática (software) de uma dada tarefa. E essa descrição da execução de uma tarefa, como considerada acima, é chamada Algoritmo. Para se construir algoritmos é necessário desenvolver uma lógica de programação. Figura 1.1 – Etapas que antecedem o desenvolvimento de programas. 7 Problema Solução Algoritmo Lógica de programação é a técnica de encadear pensamentos para atingir determinado objetivo. Quando há um problema e o objetivo é solucioná-lo, é necessário ordenar o pensamento de forma lógica durante a elaboração das ações a serem seguidas para solucionar o problema. Sendo assim, algoritmo não é a solução do problema (fig. 1.1), mais a maneira de representar a solução do problema criada por cada indivíduo. Os caminhos que levam a solução de um determinado problema podem ser inúmeros, estando, assim, a cargo de cada pessoa desenvolver seu raciocínio lógico na elaboração de soluções criativas e inovadoras. A criação de programas de computadores pode ser a escolha seguinte. O programa escrito em uma linguagem de programação não é nada mais do que a representação, obedecendo à sintaxe e semântica da linguagem, do algoritmo que representa a solução do problema proposta pelo programador. O objetivo desse curso é despertar em cada indivíduo o interesse pela lógica de programação dando uma base teórica e prática, para que, o estudante domine a técnica de representação de algoritmos e esteja habilitado a aplicar estes conhecimentos na construção de programas utilizado uma linguagem de programação. 1.1 Definições de algoritmos É a descrição, de forma lógica, dos passos a serem executados no cumprimento de determinada tarefa. O algoritmo pode ser usado como uma ferramenta genérica para representar a solução de tarefas independente do desejo de automatizá-las, mas em geral está associado ao processamento eletrônico de dados, representando o rascunho para a criação de programas (Software). Serve como modelo para programas, pois sua linguagem é intermediária à linguagem humana e às linguagens de programação. É a forma pela qual se descreve soluções de problemas do mundo real, a fim de serem implementadas utilizando os recursos do mundo computacional. Como este possui várias limitações em relação ao mundo real, exige-se que, sejam impostas algumas regras básicas na forma de solucionar os problemas, para que, possamos utilizar 8 os recursos de hardware e software disponíveis. 1.2 Formas de representações de algoritmos Existem diversas formas de representação de algoritmos, mas não há um consenso com relação a melhor delas. O critério usado para classificar hierarquicamente estas formas está diretamente ligado ao nível de detalhe ou, inversamente, ao grau de abstração oferecido. Algumas formas de representação de algoritmos tratam os problemas apenas em nível lógico, abstraindo-se de detalhes de implementação muitas vezes relacionados com alguma linguagem de programação específica. Por outro lado existem formas de representação de algoritmos que possuem uma maior riqueza de detalhes e muitas vezes acabam por obscurecer as ideias principais do algoritmo, dificultando seu entendimento. Dentre as formas de representação de algoritmos mais conhecidas pode-se citar: i) Descrição Narrativa; ii) Fluxogramas; iii) Pseudocódigo, também conhecido como Português Estruturado. 1.2.1 Descrição narrativa Nesta forma de representação os algoritmos são expressos diretamente em linguagem natural. Como exemplo, têm-se os algoritmos a seguir: Exemplo 1.1 – Algoritmos em linguagem natural. Algoritmo 1 - Substituição de um pneu furado Afrouxar ligeiramente as porcas Suspender o carro Retirar as porcas e o pneu Colocar o pneu reserva 9 Apertar as porcas Abaixar o carro Dar o aperto final nas porcas Algoritmo 2 - Cálculo da média de um aluno Obter as suas três notas de provas Calcular a média aritmética Se (média for maior que 6) Aluno foi aprovado Senão ele foi reprovado Algoritmo 3 - Substituição de lâmpadas queimadas Se (Circuito desenergizado) Se (lâmpada estiver fora de alcance) Pegar escada; Retirar lâmpada queimada; Pegar lâmpada nova; Colocar lâmpada nova; Senão Situação de risco Algoritmo 4 – Realizar uma prova Ler a prova; Pegar a caneta; Enquanto ((houver questão em branco) e (tempo não terminou)) faça Se (souber a questão) Resolvê-la; Senão Pular para próxima; Entregar a prova. 10 Exercícios propostos Exercício 1.1 – Um homem precisa atravessar um rio utilizando um barco que possui capacidade de carregar apenas ele mesmo e uma de suas três cargas, que são: uma galinha, uma raposa e um saco de milho. O que o homem deve fazer para conseguir atravessar o rio sem perder suas cargas? Exercício 1.2 – Construa a sequência/solução que mova três discos de uma Torre de Hanói, que consiste em três hastes (a - b - c), uma das quais serve de suportepara três discos de tamanhos diferentes (1 – 2 - 3), os menores sobre os maiores. Pode-se mover um disco de cada vez para qualquer haste, contanto que nunca seja colocado um disco maior sobre um menor. O objetivo é transferir os três discos para outra haste. Exercício 1.3 – Três jesuítas e três canibais precisam atravessar um rio; para tal, dispõem de um barco com capacidade para duas pessoas. Por medidas de segurança não se permite que em alguma margem a quantidade de jesuítas seja inferior à de canibais. Qual a sequência de passos que permitiria a travessia com segurança? Exercício 1.4 – Bruce Willis se meteu numa tremenda enrascada: está em uma fonte, na qual está armada uma bomba que explodirá em alguns minutos. Se ele tentar sair da fonte, tudo vai pelos ares, mas ele tem uma chance: conectada à bomba existe uma balança, e esta balança desarma a bomba quando se põem exatamente 4 litros de água sobre ela. Bruce 11 Willis tem 2 recipientes: um com capacidade para 3 litros e outro com capacidade para 5 litros, como ele deve fazer para sair vivo dessa? Esta representação é pouco usada na prática porque o uso da linguagem natural muitas vezes dá oportunidade a más interpretações, ambiguidades e imprecisões. Por exemplo, a instrução “afrouxar ligeiramente as porcas” no algoritmo da troca de pneus está sujeita a interpretações diferentes por pessoas distintas. Uma instrução mais precisa seria: “afrouxar a porca, girando-a 30º no sentido anti-horário”. 1.2.2 Fluxogramas É a utilização de símbolos gráficos para representar algoritmos. Nos fluxogramas existem símbolos padronizados para início, entrada de dados, cálculos, saída de dados, fim, etc. Estes símbolos são combinados para exibir uma representação de uma solução de um problema. As setas indicam a direção do fluxo de execução. Exemplo 1.2 – Fluxograma para calcular o triplo de um número qualquer, fornecido pelo usuário. Figura 1.2 – Fluxograma cálculo do Triplo de um Número. 12 Início �um Triplo = �um * 3 Triplo Fim 1.2.3 Português estruturado ou pseudocódigo Esta forma de representação de algoritmos é rica em detalhes, como a definição dos tipos das variáveis usadas no algoritmo. Por assemelhar-se bastante à forma em que os programas são escritos, encontra muita aceitação no meio acadêmico. Na verdade, esta representação é suficientemente geral para permitir a tradução de um algoritmo nela representado para uma linguagem de programação específica, praticamente de maneira direta. Após a criação do algoritmo que representa a solução do problema, o mesmo deverá ser testado em papel ou em uma ferramenta que interprete as ações do algoritmo, com a finalidade de validar a solução descrita no algoritmo. Cada ação contida nas linhas do algoritmo pode ser chamada de instrução. Desta maneira, pode-se dizer que um algoritmo é formado por um conjunto finito de instruções. E um programa o que é? Um programa de computador nada mais é do que a representação do algoritmo numa linguagem de programação, seja ela C, Pascal, Delphi, C# (sharp), etc. Como a maioria das linguagens de computadores está escrita em inglês, a tarefa dos programadores consiste em traduzir os algoritmos escritos em português para a linguagem de programação, em inglês. Exemplo 1.3 – Algoritmo para calcular a média aritmética simples de duas notas. Inicialmente será mostrado como algoritmo generalizado e em seguida, como deverá estar ao longo desta apostila. Usando a sintaxe da linguagem C e o C Quietly. Situação 1: Apresentado como algoritmo presente em vários livros de estrutura de dados e algoritmos: Algoritmo Calculo_Media inteiro nota1, nota2; real media; Inicio 13 Leia(nota1, nota2); media <- (nota1 + nota2)/2; Se (media >= 6) Então Escreva (‘Aprovado‘) Senão Escreva (‘Reprovado‘); Fim Situação 2: Apresentado como algoritmo com a sintaxe da linguagem C e podendo ser utilizado no C Quietly: #incluir <stdio.h> #incluir <conio.h> principal () inicio inteiro nota1, nota2; real media; leia("%d",¬a1); leia("%d",¬a2); media = (nota1 + nota2)/2.0; se (media >= 6.0) inicio imprima ("Aprovado\n"); fim senao inicio imprima ("Reprovado\n"); fim getch(); /* Aguarda uma tecla para finalizar */ retorno (0); fim Situação 3: Apresentado como um programa com a sintaxe da linguagem C. #include <stdio.h> #include <conio.h> 14 main () { int nota1, nota2; float media; scanf("%d",¬a1); scanf("%d",¬a2); media = (nota1 + nota2)/2.0; if (media >= 6.0) { printf ("Aprovado\n"); } else { printf ("Reprovado\n"); } getch(); /* Aguarda uma tecla para finalizar */ return (0); } 1.3 A linguagem C A linguagem de programação C foi desenvolvida no início dos anos 70 nos Laboratórios AT&T Bell, nos Estados Unidos. A motivação para que o autor de C, Dennis Ritchie, criasse uma nova linguagem de programação foi o desenvolvimento do sistema operacional Unix. C é uma ferramenta tão básica que praticamente todas as ferramentas suportadas por Unix e o próprio sistema operacional foram desenvolvidas em C. C acompanhou o ritmo da distribuição do sistema operacional Unix, que foi amplamente divulgado e livremente distribuído na década de 70. Apesar de haver compiladores para linguagens mais “tradicionais” na distribuição Unix, aos poucos C foi ganhando simpatizantes e adeptos. Atualmente, não há dúvidas de que C é uma das linguagens de programação de maior aceitação para uma ampla classe de aplicações. A simplicidade de C não restringe, no entanto, a potencialidade de suas aplicações. Esta habilidade de construir aplicações complexas a partir de elementos 15 simples é um dos principais atrativos da linguagem. O sucesso de C foi tão grande que diversas implementações de compiladores surgiram, sendo que nem todos apresentavam o mesmo comportamento em pontos específicos, devido a características distintas da arquitetura dos computadores ou a “extensões” que se incorporavam à linguagem. Para compatibilizar o desenvolvimento de programas em C, o Instituto Norte-Americano de Padrões (ANSI) criou em 1983 um comitê com o objetivo de padronizar a linguagem. O resultado deste trabalho foi publicado em 1990, e foi prontamente adotado como padrão internacional. Criando, compilando e executando programas em linguagem C Após as etapas de entendimento do problema e definição de uma ou mais soluções para o mesmo é chegado o momento de criar a representação da solução do problema por meio do código fonte. Este por sua vez nada mais é do que a representação de uma solução utilizando a sintaxe correta de uma linguagem de programação, tal qual o C. Uma ferramenta de edição de texto se faz necessária. Prefira editores de texto que tenha poucos recursos e que sejam capazes de salvar seus arquivos fontes em modo caractere, ou seja, ASCII - American Standard Code for Information Interchange. Evite utilizar editores muito sofisticados tais como Microsoft Word, Open Office Writer, etc. estes armazenam caracteres extras (de controle) que não interessam ao programa ou código fonte. Por convenção o arquivo fonte deve ter a extensão .c, em minúsculo. Esta atitude facilita o reconhecimento imediato de um arquivo com código C, assim como extensões .pas para Pascal ou .cpp para C++. Como mostra a figura anterior (fig 1.3) o código fonte é somente o início do trabalho de criação de programas executáveis. Ainda na mesma figura (fig. 1.3) pode-se observar outras etapas. O conceito de cada uma destas etapas é apresentado a seguir. pré-processador – este é recebe o arquivo com o código fonte (ex.: 1.4) e é responsável por retirar os comentários e interpretar diretivas especiais denotadas por #.Por exemplo: 16 #include <math.h> - arq da biblioteca math. #include <stdio.h> - arq da biblioteca padrão de E/S. #define TAM_MAX 100 headers (.h) código fonte código assembly bibliotecas (.obj) código objeto código executável Figura 1.3 – Fluxo no compilador C. compilador – o compilador C traduz o código fonte em código assembly. Ele recebe o arquivo fonte do pré-processador. montador (assembler) – cria o código objeto. No UNIX estes arquivos são encontrados com a extensão .o e no MS DOS com .obj. editor de ligação – se o arquivo fonte referencia alguma função de alguma biblioteca ou de algum arquivo externo cabe ao editor de ligação combinar estes arquivos com a função main() para criar o arquivo executável. Exemplo 1.4 - Calcular a área de um círculo. O usuário deve fornecer o valor fracionário do raio. 17 Editor de Ligação Compilador Pré-processador Montador #include <conio.h>> // biblioteca console de Input/Output #include <stdio.h> // biblioteca standard de Input/Output #define PI 3.14159 // constante pi // a seguir a funcao main() main(){ float raio, area; // duas variaveis declaradas // mostra na tela uma mensagem printf("Digite o valor do raio do circulo: "); // le do teclado o valor do raio scanf("%f", &raio); // exemplos: 1.23 12.3e-1 // a seguir mostra na tela o valor do raio lido // usando 12 colunas, e 2 decimais arredondados // por ex. 1.576 e' arredondado 1.58, so' na tela printf("Raio digitado e' %12.2f\n", raio); area= PI*raio*raio; // calculo da area printf("Area com raio %f e' %f\n", raio, area); getch(); //aguarda uma tecla para prosseguir } // fim main 18 2 Tipos, bases, expressões e funções Desenvolver programas requer o conhecimento do conceito de alguns itens indispensáveis na representação da solução de um problema qualquer. A compreensão ou entendimento destes conceitos e das possibilidades de utilização de cada um dos conceitos acima, permite a precisa definição de quais elementos farão parte da solução proposta durante a elaboração da mesma. A linguagem C suporta os tipos de dados básicos usualmente suportados pelos computadores. Na linguagem padrão, os tipos básicos suportados são char, int, float e double. A seguir a tabela completa dos tipos de dados em C (tab. 2.1). Tabela 2.1 – Tipos de dados em C Tipo Tamanho (Byte) Valor inicial Valor final char 1 -128 +127 unsigned char 1 0 255 int 2 -32.768 +32.767 unsigned int 2 0 65535 long int 4 -2.147.483.648 +2.147.483.647 unsigned long int 4 0 4.294.264.295 short int 2 -32.768 +32.767 unsigned short int 2 0 65535 float 4 -3.4E-38 +3.4E+38 double 8 -1.7E-308 +1.7E+308 long double 10 -3.4E-4932 +3.4E+4932 19 O tipo char ocupa um único byte, sendo adequado para armazenar um caractere do conjunto ASCII e pequenos valores inteiros. O tipo int representa um valor inteiro que pode ser positivo ou negativo. O número de bytes ocupado por este tipo (e, consequentemente, a faixa de valores que podem ser representados) reflete o tamanho “natural” do inteiro na máquina onde o programa será executado. Os tipos float e double representam valores reais, limitados apenas pela precisão da máquina que executa o programa. O tipo float oferece cerca de seis dígitos de precisão enquanto que double suporta o dobro da precisão de um float. Alguns destes tipos básicos podem ser modificados por qualificadores. Por exemplo, o tipo char pode ser acompanhado pelo qualificador signed ou unsigned. O tipo signed char seria utilizado para indicar que a variável do tipo char estaria representando pequenos números inteiros (na faixa de -128 a +127). O tipo unsigned char seria utilizado para indicar que a variável estaria armazenando valores inteiros exclusivamente positivos (sem sinal) na faixa de 0 a 255. O tipo int também pode ser qualificado. Um tipo unsigned int indica que a variável apenas armazenará valores positivos. Um tipo short int indica que (caso seja possível) o compilador deverá usar um número menor de bytes para representar o valor numérico - usualmente, dois bytes são alocados para este tipo. Uma variável do tipo long int indica que a representação mais longa de um inteiro deve ser utilizada, sendo que usualmente quatro bytes são reservados para variáveis deste tipo. Estas dimensões de variáveis denotam apenas uma situação usual definida por boa parte dos compiladores, sendo que não há nenhuma garantia quanto a isto. A única coisa que se pode afirmar com relação à dimensão de inteiros em C é que uma variável do tipo short int não terá um número maior de bits em sua representação do que uma variável do tipo long int. Valores com representação em ponto flutuante (reais) são representados em C por meio do uso do ponto decimal, como em 1.5 para representar o valor um e meio. A notação exponencial também pode ser usada, como em 1.2345e-6 ou em 0.12E3. Caracteres ASCII são denotados entre aspas simples, tais como ’A’. Cada caractere ASCII corresponde também a uma representação binária usada internamente. Por exemplo, o caractere ASCII A equivale a uma sequência de bits que corresponde ao 20 valor hexadecimal 41H ou decimal 65. Os valores definidos para os caracteres ASCII são apresentados na tabela localizada no anexo A. Além dos caracteres alfanuméricos e de pontuação, que podem ser representados em uma função diretamente pelo símbolo correspondente entre aspas, C também define representações para caracteres especiais de controle do código ASCII por meio de sequências de escapes iniciados pelo símbolo \ (contra barra). As principais sequências são encontradas na tabela a seguir (tab. 2.2). Tabela 2.2 – Caracteres de controle Caractere de Controle Finalidade \n Nova linha \t Tabulação \b Retrocesso \r Retorno de carro \f Salto de página \a Sinal sonoro \\ Contra barra \’ Apóstrofo \” Aspas \0 O caractere nulo 2.1 Memória Todo computador é dotado de uma quantidade de memória a qual se constitui de um conjunto de circuitos capazes de armazenar (temporariamente ou por longos períodos de tempo) as unidades de dados e os programas a serem executados pela máquina. Nos computadores de uso geral, é possível encontrar diferentes denominações para as diferentes categorias de memória que neles são encontradas: a memória principal, ou memória de trabalho, onde normalmente devem estar armazenados os programas e dados a serem manipulados pelo processador; 21 a memória secundária que permitem armazenar uma maior quantidade de dados e instruções por um período de tempo mais longo; os discos rígidos são os exemplos mais evidentes de memória secundária de um computador, mas podem ser citados outros dispositivos como CD-ROM, DVD, cartões de memória, etc; 2.2 Bases A representação de um número depende da base escolhida ou disponível na máquina em uso. A base Decimal é a mais empregada atualmente. Na antiguidade, foram utilizadas outras bases como a base 12, a base 60, etc. Já um computador opera na base 2. (Por quê?) O que ocorre na interação entre o usuário (aplicação) e o computador? O usuário passa seus dados no sistema decimal e estes são convertidos em binário pelo computador. Os resultados numéricos obtidos no sistema binário são convertidos para o sistema decimal e finalmente são transmitidos ao usuário. A seguir os processos de conversão do sistema binário e decimal. Binário para Decimal (347)10 = 3 x 10 2 + 4 x 101 + 7 x 100 (10111)2 = 1 x 2 4 + 0 x 23 + 1 x 22 + 1 x 21 + 1 x 20 de modo geral, dado um número N na base b, na forma polinomial é: N = an b n + an-1 b n-1 + ... + a2 b 2 + a1 b 1 + a0 b 0 com esta representação pode-se facilmente converter um número do sistemabinário para o sistema decimal, por exemplo: 22 (10111)2 = 1 x 2 4 + 0 x 23 + 1 x 22 + 1 x 21 + 1 x 20 = 16 + 0 + 4 +2 +1 = (23)10 Decimal para Binário Método da Divisão Sucessiva por 2. (11)10 = (?)2 11 2 1 5 2 1 2 2 0 1 (1011)2 Representação de números Como o computador armazena inteiros positivos? Usando todos os bits disponíveis para armazenamento. [0, b n] -1 Como o computador armazena inteiros negativos? Sinal-magnitude 0 = ‘+’ e 1 = ‘-‘ Ex.: 1111, ..., 1000 = - 7, ..., - 0; 0000, ..., 0111 = 0, ..., 7; Complemento da Base 23 Veja figura (fig. 2.1). N = b n-1 - a Ex.: 1000, ..., 1111 = - 8, ..., - 1; 0000, ..., 0111 = 0, ..., 7; Figura 2.1 – Complemento de base (2) Como o computador armazena os caracteres? ?“não existe”? Exercícios 2.1 – Sabe-se que os computadores têm a sua disposição apenas zeros e uns para representarem os mais diversos dados. Abaixo vemos números em notação decimal, normalmente utilizada pelo ser humano no seu cotidiano. Converter esses números, em uma notação que o computador possa trabalhar, ou seja, em números binários. 57d 79d 010d 33d 44d 67d 89d 204d 03d 99d 224d 27d 75d 101d 73d 94d 62d 19d 106d 13d 39d 020d Exercícios 2.2 – Os números binários abaixo, que bem poderiam estar na memória de um computador, estão representando quais números decimais? 11011010b 11101010b 01011101b 00100011b 11010001b 11011110b 10001010b 01110101b 00110011b 11010010b 24 10011010b 10101010b 01010111b 00110111b 11010100b 2.3 Declarações de variáveis Toda variável ou identificador que for utilizada em uma função C deve ser previamente declarada. A forma geral (fig. 2.2) de uma declaração de variável é: Figura 2.2 – Declarando variáveis. Desde modo nome da variavel, ... são variáveis de um mesmo tipo de dado. Os identificadores representam os nomes escolhidos para rotular as variáveis, as constantes e as funções, obedecendo as seguintes regras: i) O primeiro caractere deve ser uma letra; ii) Se houver outros caracteres, estes só poderão ser letra, algarismo e o _ (sublinha); iii) Os nomes das variáveis escritas com letras maiúsculas são diferentes das letras minúsculas. Assim, nota1 é diferente de NOTA1. iv) Palavras chaves ou reservadas de cada linguagem também não podem ser utilizadas, facilitando a conversão do algoritmo para o código fonte da linguagem a ser utilizada. A seguir (tab. 2.3), alguns exemplos de nomes de variáveis permitidos, além de alguns dos erros que poderiam ser cometidos durante a escolha do nome de um identificador, seja ele, uma variável, uma constante ou de funções. Nomes válidos também posem ser observados no exemplo mais a frente (ex.: 2.1). 25 Tabela 2.3 – Exemplos de nomes de variáveis Nomes Válidos Nomes Não-Válidos valor, IDADE, nota1, Nome a, X, x 4mes /* inválido */ main /* inválido */ fim /* inválido para o C Quietly, pois este o traduziria para } */ Declarar uma variável consiste em reservar espaço na memória principal (RAM – Random Access Memory) do computador. Desta forma, um endereço de memória é alocado e pode-se ter acesso a este endereço por meio do nome da variável. Esta é uma característica das linguagens de alto nível como a linguagem C e Pascal. Nos algoritmos/programas destinados a representar soluções de problema no computador, cada variável corresponde a uma posição de memória, cujo conteúdo pode variar ao longo do tempo durante a execução do algoritmo/programa. Embora a variável possa assumir diferentes valores, ela só pode armazenar um único valor a cada instante. Exemplo 2.1 - Nomes válidos de declaração de variáveis em C. int um_inteiro, num, valor; unsigned int outro_inteiro; char c1, c2; float salario, nota1; double x, y, z, h, d, g; Nomes de variáveis podem ser de qualquer tamanho, sendo que usualmente nomes significativos devem ser utilizados, mas somente os 31 primeiros caracteres são considerados. C faz distinção entre caracteres maiúsculos e caracteres minúsculos, de forma que Salario é diferente de salario. Há restrições aos nomes de variáveis. Palavras associadas a comandos e definições da linguagem (tais como if, for e int) são reservadas, não podendo ser utilizadas para o nome de variáveis. A lista de palavras reservadas em C é apresentada no Anexo A. O nome de uma variável pode conter letras, números e o sublinha ( _ ), mas 26 deve começar com uma letra, conforme apresentado anteriormente. Como se pode observar no exemplo (ex.: 2.1) anterior, diversas variáveis de um mesmo tipo podem ser declaradas em um mesmo comando, sendo que o nome de cada variável neste caso estaria separado por vírgulas. Além disto, variáveis podem ser também inicializadas enquanto declaradas, como em: Exemplo 2.2 - Declaração de variáveis em C com inicialização destas. #include <stdio.h> #include <conio.h> main (){ int a = 0, b = 20; char c = ’X’; long int d = 12345678; ... } Exemplo 2.3 - Programa com o uso de variáveis inteiras. #include <stdio.h> #include <conio.h> main (){ int num, dobro; printf ("Entre com um numero: "); scanf ("%d",&num); dobro = num * 2; printf ("%d, e seu dobro = %d\n",num,dobro); printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } 27 2.4 Definindo contantes Outra maneira de se declarar constantes (fig. 2.3) é muito semelhante à declaração de variáveis com inicialização, exceto que o seu valor permanecerá inalterado. Uma variável cujo valor não será alterado pelo programa pode ser qualificada como const, como no exemplo (ex.: 2.4) a seguir. Figura 2.3 – Declarando constantes. Neste caso (ex.: 2.4), a variável NotaMaxima não poderá ter seu valor alterado. Evidentemente, variáveis deste tipo devem ser inicializadas no momento de sua declaração. Exemplo 2.4 - Declaração de contantes em C com inicialização destas. #include <stdio.h> #include <conio.h> main (){ const int NotaMaxima = 10; ... } Outra forma de declarar constantes simbólicas é por meio da cláusula #define logo no início do programa, como pode ser observado nos exemplos seguintes (ex.: 2.5 e ex.: 2.6), sendo este último um programa completo. Exemplo 2.5 - Declaração de contantes em C usando #define. #include <stdio.h> #include <conio.h> 28 #define MAX 1024 #define PI 3.1415926 main (){ ... } Exemplo 2.6 – Programa em linguagem C com o uso de constantes simbólicas. #include <stdio.h> #include <conio.h> #define MEDIA_APROVADO 7 main () { int nota1, nota2; real media; scanf("%d",¬a1); scanf("%d",¬a2); media = (nota1 + nota2)/2.0; if (media >= MEDIA_APROVADO) { printf ("Voce foi Aprovado\n"); } else { printf ("Voce foi Reprovado\n"); } printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } Lógicos Também conhecido como tipo booleano. Pode representar apenas dois valores: Verdadeiro ou Falso. Pode ser utilizado em algumas linguagens de programação com 29 outras denominações, tais como Sim/Não, True/False, 1/0, Verdadeiro/Falso. A linguagem C utiliza o tipo int para representar o tipo lógico, assumindo 0 (zero) como falso e os demais quaisquer valores como verdadeiro. 2.5 A função printf() A função printf é parte de um conjunto de funções pré-definidas armazenadas em uma biblioteca padrão <stdio.h> de rotinas da linguagem C. Ela permite apresentar na tela os valores de qualquer tipo de dado. Para tanto, printf utiliza o mecanismo de formatação, que permite traduzir a representação interna de variáveis para a representação ASCII que pode ser apresentada na tela. Sintaxe: printf("string de controle", lista deargumentos); O primeiro argumento de printf é uma string de controle, uma sequência de caracteres entre aspas. Esta string, que sempre deve estar presente, pode especificar através de caracteres especiais (as sequências de conversão) quantos outros argumentos estarão presentes nesta invocação da função. Estes outros argumentos serão variáveis cujos valores serão formatados e apresentados na tela. Por exemplo, se o valor de uma variável inteira x é 10, então a execução da função, printf("Valor de x = %d", x); imprime na tela a frase Valor de x = 10. Se y é uma variável do tipo caractere com valor ’G’, então a execução de printf("x = %d e y = %c\n", x, y); imprime na tela a frase x = 10 e y = G seguida pelo caractere de nova linha (\n), ou seja, a próxima saída para a tela aconteceria na linha seguinte. Observe que a sequência de conversão pode ocorrer dentro de qualquer posição dentro da string de controle. 30 A função printf não tem um número fixo de argumentos. Em sua forma mais simples, pelo menos um argumento deve estar presente — a string de controle. Uma string de controle sem nenhuma sequência de conversão será literalmente impressa na tela. Com variáveis adicionais, a única forma de saber qual o número de variáveis que será apresentado é por inspeção da string de controle. Desta forma, cuidados devem ser tomados para que o número de variáveis após a string de controle esteja de acordo com o número de sequências de conversão presente na string de controle. Além de ter o número correto de argumentos e sequências de conversão, o tipo de cada variável deve estar de acordo com a sequência de conversão especificada na string de controle. A sequência de conversão pode ser reconhecida dentro da string de controle por iniciar sempre com o caráter %. Exemplo completo (ex.: 2.7) a seguir. Exemplo 2.7 – Desenvolver um programa para determinar o maior número entre dois números quaisquer. #include <stdio.h> #include <conio.h> main (){ float n1, n2; printf ("Entre com um numero: "); scanf ("%f",&n1); printf ("Entre com um outro numero: "); scanf ("%f",&n2); if (n1 > n2) { printf ("%f eh maior que %f!\n", n1, n2); } else { printf ("%f eh maior que %f!\n", n2, n1); } printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } 31 As principais sequências de conversão para variáveis caracteres e inteiras são: %c imprime o conteúdo da variável com representação ASCII; %d imprime o conteúdo da variável com representação decimal com sinal; %u imprime o conteúdo da variável com representação decimal sem sinal; %o imprime o conteúdo da variável com representação octal sem sinal; %x imprime o conteúdo da variável com representação hexadecimal sem sinal. Uma largura de campo pode ser opcionalmente especificada logo após o caractere %, como em %12d para especificar que o número decimal terá reservado um espaço de doze caracteres para sua representação. Se a largura de campo for negativa, então o número será apresentado alinhado à esquerda ao invés do comportamento padrão de alinhamento à direita. Para a conversão de variáveis do tipo long, o caractere l também deve ser especificado, como em %ld. Para converter variáveis em ponto flutuante, as sequências são: %f imprime o conteúdo da variável com representação com ponto decimal; %e imprime o conteúdo da variável com representação em notação científica (exponencial); %g formato geral, escolhe a representação mais curta entre %f e %e. Como para a representação inteira, uma largura de campo pode ser especificada para números reais. Por exemplo, %12.3f especifica que a variável será apresentada em um campo de doze caracteres com uma precisão de três dígitos após o ponto decimal. Finalmente, se a variável a ser apresentada é uma sequência de caracteres (uma string), então o formato de conversão %s pode ser utilizado. Para apresentar o caractere %, a sequência %% é utilizada. 2.6 A função scanf() A função scanf() é definida em <stdio.h> como segue: 32 scanf("expressão de controle", lista de argumentos); Esta lê caracteres da entrada padrão e coloca os valores lidos e convertidos nas variáveis cujos endereços são passados na lista de argumentos seguintes à indicação do formato; retorna o número de caracteres lidos e convertidos. A indicação do formato é muito semelhante à especificada para printf(). A única exceção diz respeito aos especificadores f, e ou g, que aqui se referem exclusivamente a valores do tipo float (os valores lidos e convertidos deverão ser passados a apontadores para variáveis do tipo float). Para especificar valores do tipo double deverão ser usados os especificadores lf, le ou lg. A lista de argumentos, que irão receber os valores lidos, deverá conter apenas apontadores ou endereços de variáveis. Por exemplo, para ler um valor inteiro do teclado e colocá-lo na variável de tipo int i. scanf("%d", &i); %c lê uma variável com representação ASCII; %d lê uma variável com representação decimal com sinal; %u lê uma variável com representação decimal sem sinal; %o lê uma variável com representação octal sem sinal; %x lê uma variável com representação hexadecimal sem sinal; %f lê uma variável com representação com ponto decimal; %e lê uma variável com representação em notação científica (exponencial); %s lê uma variável string (cadeia de caracteres); %lf lê uma variável com representação com ponto decimal de precisão dupla (double); Exemplo 2.8 - Programa para ler um caractere e exibir seu correspondente em decimal, octal e hexadecimal. #include <stdio.h> #include <conio.h> main(){ char a; 33 printf ("\nEntre com um caractere:"); scanf ("%c", &a); printf ("\n%c = %d em decimal,", a, a); printf ("\n%o em octal, %x em hexadecimal", a, a); printf ("\npressione qualquer tecla..."); getch(); return(0); } outros exemplos, int num; scanf("%d", &num); char letra; scanf("%c", &letra); 2.7 Expressões Após a declaração das variáveis, o corpo de uma função é definido através dos comandos que serão executados pela função. Estes comandos devem ser expressos sob a forma de uma sequência de expressões válidas da linguagem C. As expressões na linguagem C são sempre terminadas pelo símbolo ; (ponto e vírgula). 2.7.1 Expressões Aritméticas O comando de atribuição (fig. 2.4) em C é indicado pelo símbolo =, como pode ser visto no exemplo (ex.: 2.9), a seguir. Figura 2.4 – Atribuição. 34 Exemplo 2.9 - Declaração de variáveis em C, inicializando-as mais tarde. #include <stdio.h> #include <conio.h> main (){ int a, b, c; a = 10; /* a recebe valor 10 */ b = c = a; /* b e c recebem o valor de a (10) */ ... } Observe neste exemplo que a atribuição pode ser encadeada - na última linha da função acima, c recebe inicialmente o valor da variável a, e então o valor de c será atribuído à variável b. Expressões aritméticas em C podem envolver os operadores binários (isto é, operadores que tomam dois argumentos) de soma (+), subtração (-), multiplicação (*), divisão (/), lista completa na tabela a seguir (tab 2.4). Valores negativos são indicados pelo operador unário -. Adicionalmente (ex.: 2.10), para operações envolvendo valores inteiros são definidos os operadores de resto da divisão inteira ou módulo (%), incremento (++) e decremento (--). Tabela 2.4 – Operadores aritméticos Símbolo Significado + adição * multiplicação - subtração ou inversor do sinal / divisão % resto da divisão de inteiros ++ incremento -- decremento = atribuição +=, -=, *=, /= formas compactas para operações aritméticas 35 Exemplo 2.10 - Declaração de variáveis em C, inicializando-asmais tarde. #include <stdio.h> #include <conio.h> main (){ int a = 10, b, c, d; b = 2 * a; /* b = 20 */ a++; /* a = a + 1 (11) */ c = b / a; /* divisao inteira: c = 1 */ d = b % a; /* resto da divisao: d = 9 */ ... } Cada um dos operadores de incremento e decremento tem duas formas de uso, dependendo se eles ocorrem antes do nome da variável (pré-incremento ou pré- decremento) ou depois do nome da variável (pós-incremento ou pós-decremento). No caso do exemplo anterior (ex.: 2.10), o operador de incremento ocorre de forma isolada em uma expressão (sozinho na linha), as duas formas possíveis são equivalentes. A diferença entre eles ocorre quando estes operadores são combinados com outras operações. No exemplo anterior (ex.: 2.10), as linhas de atribuição à b e incremento de a poderiam ser combinados em uma única expressão, Exemplo 2.11 – Usando pós-incremento em C. #include <stdio.h> #include <conio.h> main (){ int a = 10, b; b = 2*(a++); /* b recebe 2*a e então a recebe a+1 */ ... } Observe como esta expressão (ex.: 2.11) é diferente da expressão do exemplo seguinte (ex.:2.12). Exemplo 2.12 – Usando pré-incremento em C. 36 #include <stdio.h> #include <conio.h> main (){ int a = 10, b; b = 2*(++a); /* a recebe a+1 e então b recebe 2*a*/ ... } Na prática, os parênteses nas duas expressões acima poderiam ser omitidos uma vez que a precedência do operador de incremento é maior que da multiplicação, ou seja, o incremento será avaliado primeiro. A subseção 2.4.4 apresenta a ordem de avaliação para todos os operadores da linguagem C (tab. 2.8). A linguagem C tem também uma forma compacta de representar expressões na forma: var = var op (expr); Deste modo uma mesma variável var aparece nos dois lados de um comando de atribuição. A forma compacta é: var op= expr; Exemplo 2.13 – Usando formas compactas de operadores aritméticos em C. #include <stdio.h> #include <conio.h> main (){ int a = 4, b = 3, c = 5; a += b; /* equivale a a = a + b */ c *= 2; /* equivale a c = c*2 */ ... } O operador % trabalha somente com operadores int. Já a / (barra) funciona para int e float. Mas esteja atento, pois r = 5/2 será igual a 2, mesmo que r tenha 37 sido declarado como float. Esteja certo de especificar r = 5/2.0 ou r = 5.0/2, ou ainda melhor r = 5.0/2.0. Se preferir, r = (float) 5/2; Exemplo 2.14 - Programa para obter números inteiros e realizar diversas operações com estes números. #include <stdio.h> #include <conio.h> main (){ int a, b, r; float r2; printf ("Digite o primeiro numero: "); scanf ("%d", &a); printf ("Digite o segundo numero: "); scanf ("%d", &b); r = a + b; printf ("A soma de %d e %d = %d\n",a,b,r); r2 = (real) a / b; printf ("A Divisao de %d e %d = %0.2f\n",a,b,r2); r = a - b; printf ("A subtracao de %d e %d = %d\n",a,b,r); r = a * b; printf ("A multiplic de %d e %d = %d\n",a,b,r); r = a / b; printf ("A Divisao int %d e %d = %d\n",a,b,r); r = a resto b; printf ("O Resto Div de %d e %d = %d\n",a,b,r); printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } 2.7.2 Expressões Condicionais 38 Um tipo muito importante de expressão em C é a expressão condicional, cujo resultado é um valor que será interpretado como falso ou verdadeiro. Como a linguagem C não suporta diretamente o tipo de dado booleano, ela trabalha com representações inteiras para denotar estes valores. O resultado de uma expressão condicional é um valor inteiro que será interpretado como falso quando o valor resultante da expressão é igual a 0, e como verdadeiro quando o valor resultante é diferente de 0. Assim, qualquer expressão inteira pode ser interpretada como uma expressão condicional. A situação mais comum, entretanto, é ter uma expressão condicional comparando valores através dos operadores relacionais. Os operadores relacionais (tab. 2.5) em C são: Tabela 2.5 – Operadores relacionais Operador Operação == igual a != diferente de < menor que > maior que <= menor que ou igual a >= maior que ou igual a Observe que o operador de igualdade é ==, e não = que é o símbolo de atribuição conforme mostra a tabela anterior (tab. 2.3). Esta é uma causa comum de erros para programadores que estão acostumados com outras linguagens, sendo o sinal de = um operador relacional. Exemplo 2.15 - Programa com o uso de operadores relacionais. #include <stdio.h> #include <conio.h> main (){ int idade; printf("Entre com sua idade: "); scanf("%d", &idade); 39 if (idade >= 18) { printf ("Voce já pode fazer sua CNH\n"); } printf("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return(0); } Expressões condicionais elementares (comparando duas variáveis ou uma variável e uma constante) podem ser combinadas para formar expressões complexas através do uso de operadores booleanos. Estes operadores (tab. 2.6) são: Tabela 2.6 – Operadores lógicos Operador Operação && conjunção (and) || disjunção (or) ! negação (not) O operador && (and) resulta verdadeiro (tab. 2.7) quando as duas expressões envolvidas são verdadeiras (ou diferente de 0). O operador || (or) resulta verdadeiro quando pelo menos uma das duas expressões envolvidas é verdadeira. Além destes dois conectores binários, há também o operador unário de negação, !, que resulta falso quando a expressão envolvida é verdadeira (diferente de 0) ou resulta verdadeiro quando a expressão envolvida é falsa (igual a 0). Tabela 2.7 – Tabela verdade dos operadores lógicos &&, || e !. A B Operador && Operador || Operador ! (A) 1 1 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 0 0 1 40 Expressões lógicas complexas, envolvendo diversos conectores, são avaliadas da esquerda para a direita. Além disto, && tem precedência maior que ||, e ambos têm precedência menor que os operadores lógicos relacionais e de igualdade. Entretanto, recomenda-se sempre a utilização de parênteses em expressões para tornar claro quais operações são desejadas. A exceção a esta regra ocorre quando um número excessivo de parênteses pode dificultar ainda mais a compreensão da expressão; em tais casos, o uso das regras de precedência da linguagem pode facilitar o entendimento da expressão. Exemplo 2.16 - Programa com o uso de operadores lógicos e relacionais. #include <stdio.h> #include <conio.h> main (){ int idade; char sexo; printf("Qual o seu sexo: "); scanf("%c", &sexo); printf("Qual a sua idade: "); scanf("%d", &idade); if (idade >= 18 && sexo == 'M') { printf ("Voce precisa alistar-se!\n"); } printf("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return(0); } 2.7.3 Funções primitivas Uma linguagem de programação oferece um conjunto de funções pré-definidas, que são usadas com vários tipos de dados simples. As funções estão intimamente ligadas ao conceito de função (ou fórmula) matemática, na maioria das vezes, necessitam de dados como parâmetro (dados de entrada). Em algoritmos utilizam-se as funções facilmente encontradas nas principais linguagens de programação. Veja (tab. 2.8) 41 algumas dessas funções a seguir. Exemplo 2.17 – Usando funções pré-definidas, para determinar o valor da hipotenusa. #include <stdio.h> #include <conio.h> #include <math.h> main (){ int a, b; float q1, q2, hipotenusa; printf ("Entre com o cateto A: "); scanf ("%d", &a); printf ("Entre com o cateto B: "); scanf ("%d", &b); q1 = pow(a, 2); q2 = pow(b, 2); hipotenusa = sqrt(q1 + q2); printf ("CA = %d e CB = %d\n", a, b); printf ("Hipo = %0.4f\n", hipotenusa); printf ("\npressione qualquer tecla..."); getch(); /* Aguardauma tecla para finalizar */ return (0); } Tabela 2.8 – Funções Primitivas Função Finalidade sin (x); Seno do ângulo x cos (x); Cosseno do ângulo x tan (x); Tangente do ângulo x abs (x); Valor absoluto int de x fabs (x); Valor absoluto float de x pow (y,x); Eleva y a x sqrt (x); Raiz quadrada de x log (x) Logaritmo Natural de x 42 2.7.4 Prioridade de operadores Durante a execução de uma expressão que envolve vários operadores, é necessário existir certas prioridades, caso contrário pode-se obter valores que não representam o resultado esperado. A linguagem C utiliza as seguintes prioridades de operadores (tab. 2.9). Tabela 2.9 – Prioridade de operadores Alta prioridade ( ) [ ] -> . ! - * & sizeof (type) ++ -- da direita para esquerda * / % + - << >> < <= >= > == != & ^ | && || ?: da direita para esquerda = += -= etc. da direita para esquerda , vírgula Baixa prioridade Exercícios propostos Exercício 2.3 – Exemplifique o uso dos comandos de Entrada e Saída. Exercício 2.4 – Qual a diferença entre os comandos printf e scanf? 43 Exercício 2.5 – Como podemos imprimir a mensagem “Linha inicial”, seguida de duas linhas em branco e uma outra mensagem “Linha final”? É possível realizar esta tarefa em um único comando? Dê exemplos. Exercício 2.6 – Como podemos orientar o usuário na digitação dos dados? Exemplifique. Exercício 2.7 – Escreva os comandos necessários para ler: i) as 3 notas de um aluno ii) o peso e altura de uma pessoa Exercício 2.8 – Escreva os comandos necessários para exibir: i) o conteúdo da variável x ii) o resultado da expressão 2+3 Exercício 2.9 – Determine os valore finais de a, b e c após a execução do trecho do programa abaixo: a = 0; b = 1; c = a + b; a = a + 1; b = a + b + c; Exercício 2.10 – A ordem das atribuições é importante? a = b e c = a tem o mesmo efeito de c = a e a = b ? Exercício 2.11 – Desenvolver um programa que dadas às dimensões de um retângulo, calcule a sua área e mostre na tela. #include <stdio.h> #include <conio.h> main (){ 44 int base, altura, area; printf ("Digite o valor da base do retangulo: "); scanf ("%d", &base); printf ("Digite o valor da altura do retangulo: "); scanf ("%d", &altura); area = base * altura; printf ("Area = %d\n", area); printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } Exercício 2.12 – Desenvolva um programa que leia um número inteiro positivo e exiba o dobro do mesmo. Exercício 2.13 – Crie um programa para calcular e exibir o comprimento de uma circunferência, sendo dado o valor de seu raio. (C = 2 pi R) Exercício 2.14 – Escreva um programa para ler uma temperatura dada na escala Fahrenheit e exibir o equivalente em Celsius. (C = 5 (F – 32)) 9 Exercício 2.15 – Desenvolva um programa para calcular e exibir a média ponderada de duas notas dadas. (nota1 = peso 6 e nota2 = peso 4) Exercício 2.16 – Escreva um programa que leia duas variáveis inteiras e troque o conteúdo entre elas. Exercício 2.17 – Crie um programa para calcular e exibir o valor de x y, sendo dados a base (x) e o expoente (y). Exercício 2.18 - Faça um programa que calcule o perímetro de um retângulo, sendo dado o comprimento e a largura desse retângulo. P = 2 x (c + l) 45 Exercício 2.19 - Desenvolva um programa que leia dois valores numéricos inteiros para duas variáveis e que troque o conteúdo dessas variáveis, visualizando o valor das mesmas antes e depois da troca. Exercício 2.20 - Faça um programa que leia dois números reais e que calcule a soma, produto e a média desses números. Exercício 2.21 - Crie um programa que determine o volume de uma esfera, sendo dado o respectivo raio. (V = 4/3 x pi x r3). Repare que, em C, a divisão de 4 por 3 dá um valor inteiro se não tomar medidas adequadas. Exercício 2.22 – Entre com dois números e dê como resultado a divisão, a subtração e a multiplicação dos números. Exercício 2.23 – Entre com três números e dê como resultado a soma, a média e o somatório dos quadrados dos números. Exercício 2.24 – Escreva um programa que mostre o maior e o menor valor de um conjunto de 3 valores inteiros fornecidos. Exercício 2.25 – Escreva um programa que leia um número fracionário representado um número de grau Celsius e exiba como um número fracionário à temperatura equivalente em Fahrenheit. Mostre o resultado como segue: 100.0 graus Celsius convertido para 212.0 graus Fahrenheit. Exercício 2.26 – Escreva um programa para ler um número de unidade de comprimento (um fracionário) e mostre a área do círculo deste raio. Assuma com valor do pi 3.14159 (uma apropriada declaração deve ser dado a esta constante). A saída deveria ter a seguinte forma: 46 A área do círculo de raio ___ unidades e ___ unidades. Se você desejar melhorar este código, exiba a mensagem: Erro: valores negativos não são permitidos. Se o valor de estrada for negativo. Exercício 2.27 – Dada uma entrada de um número de centímetros em fracionário, mostre o equivalente em número de pés e polegadas (fracionário, 1 decimal), isto é, uma precisão de uma casa decimal. Assuma 2.54 centímetros por polegada e 12 polegadas por pé. Se a entrada for 333.3, a saída deveria ser: 333.33 centímetros e 10 pés ou 11.2 polegadas. Exercício 2.28 – Dada uma entrada de um número de segundos, exibir como saída o equivalente em horas, minutos e segundos. Recomenda-se o formato de saída alguma coisa como: 7322 segundos e equivalente a 2 horas, 2 minutos e 2 segundos. Exercício 2.29 – Faça um programa que, dada a área de um círculo, calcule o perímetro da circunferência que o limita. Use precisão simples. A = pi r2, portanto r = raiz (A / pi) e P = 2 pi r. Exercício 2.30 – Faça um programa que determine o volume de uma esfera, sendo dado o respectivo raio. (V = 4 / 3 pi r3). Repare que, em C, a divisão de 4 por 3 dá um valor inteiro se não tomar medidas adequadas. Exercício 2.31 – Faça um programa que determine se um ano introduzido pelo usuário é ou não bissexto. Um ano é bissexto se for múltiplo de 4 sem ser de 100 ou se for múltiplo de 400. 47 Exercício 2.32 – Fazer um programa em C que pergunta um valor em metros e imprime o correspondente em decímetros, centímetros e milímetros. Exercício 2.33 – Fazer um programa que solicita um número decimal e imprime o correspondente em hexa e octal. Exercício 2.34 – Fazer um programa em C que solicite 2 números e informe: a) A soma dos números; b) O produto do primeiro número pelo quadrado do segundo; c) O quadrado do primeiro número; d) A raiz quadrada da soma dos quadrados; e) O seno da diferença do primeiro número pelo segundo; f) O módulo do primeiro número. Exercício 2.35 – Desenvolver um programa em linguagem C que leia a velocidade máxima permitida em uma avenida e a velocidade com que o motorista estava dirigindo por ela. Em seguida calcule o valor da multa que uma pessoa receberá, sabendo que são pagos: a) R$ 85,13 se o motorista ultrapassar em até 10 km/h a velocidade permitida; b) R$ 127,69 se o motorista ultrapassar de 11 a 30 km/h a velocidade permitida; c) R$ 574,62 se estiver acima de 31 km/h da velocidade permitida. Informe também os pontos que serão inseridos na carteira e o tipo de multa que será aplicado de acordo com a relação a seguir: Leve, Media e Gravíssima com 3, 5 e 7 pontos, respectivamente. Caso o motorista passe dentro da velocidade permitida, exibir “Vel. Normal“. 48 3 O controle do fluxo de execução C é uma linguagem que suporta a programação estruturada, ou seja, permite agrupar comandos na forma de sequência, seleção e repetição. 3.1 Sequências Uma sequência de comandosem uma função C é denotada simplesmente como uma sequência de expressões, como exemplo (ex.: 3.1) a seguir. Há duas possibilidades: usar comandos isolados (a forma mais utilizada) ou usar uma única expressão com a sequência de comandos separados pelo operador , (vírgula). Exemplo 3.1 - Sequências. a = 10; b = a*5; c = a+b; ou a=10, b=a*5, c=a+b; 3.2 Seleção ou if Usada para tomar decisões, ou seja, desviar a execução do programa de acordo com uma condição (Expressão Lógica), podendo ser simples (fig. 3.1) ou composta (fig. 49 3.2). A seguir, a sintaxe de uma estrutura de decisão simples. Os colchetes [...] delimitam uma parte opcional da estrutura. Sintaxe: if (condicao) { comando ; [ou sequencia1 ;] } Figura 3.1 – Fluxograma para estrutura if. Veja as afirmações a seguir: i) Todos os alunos terão bolsas de estudos integrais; ii) Somente alunos com renda inferior ou igual a dois salários mínimos, receberão a bolsa de estudos; iii) Os alunos com renda superior a dois salários mínimos, portanto, sem direito à bolsa de estudo, receberão auxílio transporte, o qual não é concedido aos alunos que possuem a bolsa integral; iv) Os alunos com renda inferior a um salário mínimo receberão bolsa integral e para os alunos com renda superior a este e de não mais que dois salários mínimos as bolsas serão de 50%. Demais alunos com renda superior a dois salários mínimos ganham somente o auxílio transporte. O primeiro item refere-se a uma sequência de instruções sem que nenhuma 50 decisão será tomada, pois todos os alunos receberão a bolsa de estudos. Os primeiros exemplos deste capítulo demonstram este conceito. Já na segunda afirmação, aparece uma situação de decisão simples (fig. 3.1), para estar habilitado a receber a bolsa de estudos cada aluno precisa preencher o requisito de renda mínima exigido. Exemplo 3.2 - Validando a entrada de um inteiro que representa um dia do mês. #include <stdio.h> #include <conio.h> main(){ int dia; printf("Entre com o dia de hoje: "); scanf("%d", &dia); if (dia > 31 || dia < 1) /* || significa ou */ printf("Dia invalido\n"); getch(); return(0); } A terceira afirmação apresenta uma situação um pouco mais complexa, o que exige uma estrutura de decisão composta (fig. 3.2). Levando em consideração que somente os alunos com renda superior a dois salários mínimos receberão o auxílio transporte, se faz necessário informar que os alunos que recebem a bolsa de estudos, não serão contemplados com este auxílio. Na sequência a sintaxe de uma estrutura de decisão composta. Os colchetes [...] delimitam uma parte opcional da estrutura. Sintaxe: if (condicao) { comando ; [ou sequencia1 ;] } else { comando ; [ou sequencia2 ;] } 51 Figura 3.2 – Seleção com if ... else em C. Exemplo 3.3 - Teste com um número inteiro, indicando se este é positivo ou negativo. #include <stdio.h> #include <conio.h> main(){ int numero; printf("Entre com um numero: "); scanf("%d", &numero); if (numero >= 0) printf("Numero positivo\n"); else printf("Numero negativo\n"); getch(); return(0); } Exemplo 3.4 - Determinando a alíquota a ser calculada sobre a variável fracionária salario. 52 #include <stdio.h> #include <conio.h> main(){ float salario; printf("Entre com valor do salario: "); scanf("%f", &salario); if (salario < 1499.15) { printf("Aliquota de imposto 15,0%\n"); imposto = salario * 0.15; } else { printf("Aliquota de imposto 27,5%\n"); imposto = salario * 0.275; } getch(); return(0); } Exemplo 3.5a – Desenvolver um algoritmo para determinar o maior número entre dois números quaisquer. #include <stdio.h> #include <conio.h> main(){ float n1, n2; printf ("Entre com um numero: "); scanf ("%f", &n1); printf ("Entre com um outro numero: "); scanf ("%f", &n2); if (n1 > n2) { printf ("%f eh maior que %f!\n", n1, n2); } else { printf ("%f eh maior que %f!\n", n2, n1); } printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ 53 return (0); } Exemplo 3.5b – Desenvolver um programa para determinar o maior número entre três números quaisquer. #include <stdio.h> #include <conio.h> main(){ float n1, n2, n3; printf ("Entre com um numero: "); scanf ("%f", &n1); printf ("Entre com um outro numero: "); scanf ("%f", &n2); printf ("Entre com um outro numero: "); scanf ("%f", &n3); if (n1 > n2) { if (n1 > n3) { printf ("%f eh maior!\n", n1); } else { printf ("%f eh maior!\n", n3); } } else { if (n2 > n3) { printf ("%f eh maior!\n", n2); } else { printf ("%f eh maior!\n", n3); } } printf ("\npressione qualquer tecla..."); getch(); /* Aguarda uma tecla para finalizar */ return (0); } Uma outra construção que pode aparecer são os comandos if's aninhados ou 54 encaixados, cuja forma geral é a seguinte: if (expressao) comando; else if (expressao) comando; else if (expressao) comando; else comando; Exemplo 3.6 - O programa, Calculadora Simples, a seguir mostra um exemplo com if's encaixados e aninhados. #include <stdio.h> #include <conio.h> main(){ float num1,num2,res; char oper; printf("\nCalculadora simples\n"); printf("Por favor entre com os dois operandos.\n"); scanf("%f %f", &num1, &num2); printf("Voce digitou %.2f e %.2f\n", num1, num2); printf("Qual a operacao \n"); oper = getch(); printf("A operacao e %c\n", oper); if (oper == '+') res = num1 + num2; else if (oper == '-') res = num1 - num2; else if (oper == '*') res = num1 * num2; else if (oper == '/') if (num2 == 0.0){ printf("Divisao por 0 invalida"); getch(); return(1); } else res = num1 / num2; else{ printf("Operacao invalida!\n"); getch(); return(1); } 55 printf("O resultado da %c vale %f.\n", oper, res); getch(); return(0); } 3.3 Switch case A construção estruturada de seleção entre várias opções é suportada em C pelo comando switch ... case. Neste caso, após a palavra-chave switch deve haver uma variável do tipo inteiro ou caractere entre parênteses. Após a variável, deve e uma lista de casos que devem ser considerados, cada caso iniciando com a palavra-chave case seguida por um valor ou uma expressão inteira. O comando if, em todas suas formas, é suficiente para resolver problemas de seleção de comandos. Porém em alguns casos, como no exemplo anterior (ex. 3.6) o programa se torna mais trabalhoso para ser escrito. O comando switch facilita a escrita de partes de programa (ex.: 3.7) em que a seleção deve ser feita entre várias alternativas. A forma geral do comando switch é a seguinte: switch (expressao) { case constante1 : comandos; break; case constante2 : comandos; break; case constante3 : comandos; break; ... [default: comandos;] } 56 A execução do comando segue os seguintes passos: 1. A expressão é avaliada; 2. O resultado da expressao é comparado com os valores das constantes que aparecem nos comandos case; 3. Quando o resultado da expressao for igual a uma das constantes, a execução se inicia a partir do comando associado com esta constante. A execução continua com a execução de todos os comandos até o fim do comando switch, ou até
Compartilhar