Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Programas em C: Conversão de Números e Laços de Repetição, Notas de estudo de Informática

Neste documento, aprenderá a criar programas em c que realizam a conversão de números decimais para hexadecimais e vice-versa, além de aprender a utilizar diferentes tipos de laços de repetição, como for, if-else, switch e do-while.

Tipologia: Notas de estudo

2013

Compartilhado em 28/08/2013

Garoto
Garoto 🇪🇸

4.6

(89)

446 documentos

1 / 52

Documentos relacionados


Pré-visualização parcial do texto

Baixe Programas em C: Conversão de Números e Laços de Repetição e outras Notas de estudo em PDF para Informática, somente na Docsity! Faculdade de Ciências Aplicadas de Cascavel – FACIAP Curso de Ciência da Computação LINGUAGEM C/C++ CASCAVEL - PR 2004 SUMÁRIO UNIDADE 1 – CONSIDERAÇÕES INICIAIS SOBRE A LINGUAGEM C _______________1 1.1 AS ORIGENS DO C/C++ _________________________________________________1 1.2 COMPILADORES E INTERPRETADORES ___________________________________2 1.3 WARNINGS E ERROS ___________________________________________________3 1.4 A LINGUAGEM C/C++ É CASE-SENSITIVE __________________________________3 1.5 FUNÇÕES EM C________________________________________________________3 1.5.1 FUNÇÕES COM ARGUMENTOS _________________________________________4 1.5.2 FUNÇÕES QUE RETORNAM VALORES ___________________________________5 1.5.3 A FORMA GERAL DE UMA FUNÇÃO______________________________________6 1.6 PALAVRAS RESERVADAS DA LINGUAGEM C _______________________________6 UNIDADE 2 – TIPOS DE DADOS, CONSTANTES, OPERADORES E EXPRESSÕES ____7 2.1 NOMES DE IDENTIFICADORES ___________________________________________7 2.2 TIPOS DE DADOS ______________________________________________________7 2.2.1 MODIFICADORES DE TIPOS ____________________________________________8 2.3 DEFINIÇÃO DE VARIÁVEIS_______________________________________________9 2.4 DEFINIÇÃO DE CONSTANTES ____________________________________________9 2.4.1 CONSTANTES HEXADECIMAIS E OCTAIS________________________________10 2.4.2 CONSTANTES STRING _______________________________________________11 2.4.3 CÓDIGOS DE BARRA INVERTIDA_______________________________________11 2.5 OPERADORES ________________________________________________________11 2.5.1 OPERADOR DE ATRIBUIÇÃO __________________________________________12 2.5.2 OPERADORES ARITMÉTICOS__________________________________________12 2.5.3 OPERADORES RELACIONAIS__________________________________________12 2.5.4 OPERADORES LÓGICOS______________________________________________12 2.5.5 MANIPULAÇÃO DE BITS ______________________________________________13 2.5.6 OPERADORES DE ASSINALAMENTO____________________________________13 2.5.7 OPERADORES DE PRÉ E PÓS-INCREMENTO ____________________________14 2.5.8 OPERADORES DE ENDEREÇO_________________________________________14 2.6 TABELA DE OPERADORES DO C ________________________________________14 2.7 EXPRESSÕES ________________________________________________________15 2.7.1 CONVERSÕES DE TIPOS EM EXPRESSÕES _____________________________15 2.7.2 MODELADORES (CASTS) _____________________________________________16 2.7.3 ESPAÇAMENTO E PARÊNTESES _______________________________________16 2.8 ESQUELETO DE UM PROGRAMA EM C ___________________________________17 UNIDADE 3 – ESTRUTURAS BÁSICAS DE PROGRAMAÇÃO (FLUXO DE CONTROLE)18 3.1 COMANDOS E BLOCOS ________________________________________________18 3.2 PRINTF( ) ____________________________________________________________18 3.3 SCANF( )_____________________________________________________________20 3.4 A DECLARAÇÃO if _____________________________________________________23 3.4.1 USANDO A DECLARAÇÃO else _________________________________________24 3.4.2 O ENCADEAMENTO if-else-if ___________________________________________25 3.4.3 A EXPRESSÃO CONDICIONAL _________________________________________26 3.4.4 ifs ANINHADOS ______________________________________________________27 3.5 A DECLARAÇÃO switch _________________________________________________28 3.5.1 A DECLARAÇÃO break ________________________________________________29 3.5.2 DECLARAÇÕES switch ANINHADAS _____________________________________30 3.6 LAÇOS DE REPETIÇÃO_________________________________________________33 3.7 O LAÇO for ___________________________________________________________33 3.7.1 VARIÁVEIS DO LAÇO for ______________________________________________35 3.7.2 O LAÇO INFINITO ____________________________________________________37 1 UNIDADE 1 – CONSIDERAÇÕES INICIAIS SOBRE A LINGUAGEM C 1.1 AS ORIGENS DO C/C++ A história do C/C++ começa nos anos 70 com a invenção da linguagem C. A linguagem C foi inventada e implementada pela primeira vez por Dennis Ritchie em um DEC PDP-11, usando o sistema operacional UNIX. A linguagem C é o resultado do processo de desenvolvimento iniciado com outra linguagem, chamada BCPL, desenvolvida por Martin Richards. Esta linguagem influenciou a linguagem inventada por Ken Thompson, chamado B, a qual levou ao desenvolvimento da linguagem C. A linguagem C tornou-se uma das linguagens de programação mais usadas. Flexível, ainda que poderosa, a linguagem C tem sido utilizada na criação de alguns dos mais importantes produtos de software dos últimos anos. Entretanto, a linguagem encontra seus limites quando o tamanho de um projeto ultrapassa um certo ponto. Ainda que este limite possa variar de projeto para projeto, quanto o tamanho de um programa se encontra entre 25.000 e 100.000 linhas, torna-se problemático o gerenciamento, tendo em vista que é difícil compreende-lo como um todo. Para resolver este problema, em 1980, enquanto trabalhava nos laboratórios da Bell, em Murray Bill, New Jersey, Bjarne Stroustrup acrescentou várias extensões à linguagem C e chamou inicialmente esta nova linguagem de “C com classes”. Entretanto, em 1983, o nome foi mudado para C++. Muitas adições foram feitas pós-Stroustrup para que a linguagem C pudesse suportar a programação orientada a objetos, às vezes referenciada como POO. Stroustrup declarou que algumas das características da orientação a objetos do C++ foram inspiradas por outra linguagem orientada a objetos chamada de Simula67. A linguagem C é freqüentemente referenciada como uma linguagem de nível médio, posicionando-se entre o assembler (baixo nível) e o Pascal (alto nível)1. Uma das razões da invenção da linguagem C foi dar ao programador uma linguagem de alto nível que poderia ser utilizada como uma substituta para a linguagem assembly. Como você provavelmente sabe, a linguagem assembly utiliza a representação simbólica das instruções executadas pelo computador. Existe um relacionamento de um para um entre cada instrução da linguagem assembly e a instrução de máquina. Ainda que este relacionamento possibilite escrever programas altamente eficientes, isso torna a programação um tanto quanto tediosa e passível de erro. Por outro lado, linguagens de alto nível, como Pascal, estão extremamente distantes da representação de máquina. Uma instrução em Pascal não possui essencialmente nenhum relacionamento com a seqüência de instruções de máquina que são executadas. Entretanto, ainda que a linguagem C possua estruturas de controle de alto nível, como é encontrado na Pascal, ela também permite que o programador manipule bits, bytes e endereços de uma maneira mais proximamente ligada à máquina, ao contrário da abstração apresentadas por outras linguagens de alto nível. Por esse motivo, a linguagem C tem sido ocasionalmente chamada de “código assembly de alto nível”. Por sua natureza dupla, a linguagem C permite que sejam criado programas rápidos e eficientes sem a necessidade de se recorrer a linguagem 1 SCHILDT, H. Turbo C++: guia do usuário. São Paulo : Makron Books,1992. 2 assembly. A filosofia que existe por trás da linguagem C é que o programador sabe realmente o que está fazendo. Por esse motivo, a linguagem C quase nunca “coloca- se no caminho” do programador, deixando-o livre para usar (ou abusar) dela de qualquer forma que queira. Existe uma pequena verificação de erro de execução runtime error. Por exemplo, se por qualquer motivo você quiser sobrescrever a memória na qual o seu programa está atualmente residindo, o compilador nada fará para impedi-lo. O motivo para essa “liberdade na programação” é permitir ao compilador C criar códigos muito rápidos e eficientes, já que ele deixa a responsabilidade da verificação de erros para você. Em outras palavras, a linguagem C considera que você é hábil o bastante para adicionar suas próprias verificações de erro quando necessário. Quando C++ foi inventado, Bjarne Stroustrup sabia que era importante manter o espírito original da linguagem C, incluindo a eficiência, a natureza de nível médio e a filosofia de que o programador, não a linguagem, está com as responsabilidades, enquanto, ao mesmo tempo, acrescentava o suporte à programação orientada a objetos. Assim, o C++ proporciona ao programador a liberdade e o controle da linguagem C junto com o poder dos objetos. As características da orientação a objetos em C++, usando as palavras de Stroustrup, “permite aos programas serem estruturados quanto à clareza e extensibilidade, tornando fácil a manutenção sem perda de eficiência”. 1.2 COMPILADORES E INTERPRETADORES Os termos compilador e interpretador referem-se à maneira pela qual um programa é executado. Na teoria, qualquer linguagem de programação pode ser tanto compilada como interpretada, mas algumas linguagem são usualmente executadas de uma forma ou de outra. Por exemplo, o BASIC geralmente é interpretado e o C++, compilado. A maneira como um programa é executado não é definida pela linguagem na qual ele é escrito. Tanto compiladores como interpretadores são simplesmente programas sofisticados que agem sobre o código- fonte do seu programa. Um interpretador lê o código-fonte do seu programa uma linha por vez e executa uma instrução específica contida naquela linha. O interpretador deverá estar presente toda vez que o programa estiver sendo executado. Um compilador lê o programa inteiro e converte-o em um código executável. O código executável também é referenciado como código objeto, binário ou de máquina. Entretanto, neste contexto, o termo objeto não tem nenhuma relação com os objetos definidos em um programa C++. Uma vez o programa compilado, uma linha de código-fonte está significativamente distante do código executável. O compilador não é necessário para executar o programa, desde que ele já esteja compilado. Existem dois termos que você verá freqüentemente: tempo de compilação e tempo de execução. O termo tempo de compilação refere-se aos eventos que acontecem durante o processo de compilação e tempo de execução, aos eventos que ocorrem enquanto o programa está sendo executado. Infelizmente, você verá constantemente esses termos relacionados a mensagens de erros, como em erros de tempo de compilação e erros de tempo de execução. Mas, por sorte, após adquirir experiência na programação em C/C++, você verá essas mensagens raras vezes. 3 1.3 WARNINGS E ERROS A linguagem C foi projetada para ser uma linguagem bastante tolerante e para permitir que qualquer coisa que sintaticamente esteja correta seja compilada. Entretanto, algumas declarações, ainda que sintaticamente corretas, são suspeitas. Quando o compilador C/C++ encontra uma situação dessas, imprime um warning (advertência). Você, como programador, decide, então, se a suspeita é justificada. Algumas vezes, mensagens de advertência falsas são geradas como um efeito colateral de um erro real, mas você indubitavelmente encontrará muitas advertências enquanto continuar a escrever programas em C. 1.4 A LINGUAGEM C/C++ É CASE-SENSITIVE É importante saber que as letras maiúsculas e minúsculas são tratadas como caracteres distintos. Por exemplo, em algumas linguagens, os nomes de variáveis count, Count e COUNT são três maneiras de se especificar a mesma variável. Entretanto na linguagem C/C++, serão três variáveis diferentes. Então, quando você digitar programas em C/C++ seja cuidadoso na utilização correta das letras. 1.5 FUNÇÕES EM C A linguagem C é baseada no conceito de blocos de construção. Os blocos de construção são chamados de funções. Um programa em C é uma coleção de uma ou mais funções. Para escrever um programa, você primeiro cria funções e, então, coloca-as juntas. Em C, uma função é uma sub-rotina que contém uma ou mais declarações e realiza uma ou mais tarefas. Em programas bem-escritos, cada função realiza somente uma tarefa. Cada função tem um nome e uma lista de argumentos que receberá. Em geral, pode-se dar qualquer nome a uma função, com exceção de main, que é reservada para a função que começa a execução dos programas. Uma convenção notacional tornou-se padrão quando se escreve sobre a linguagem C. Haverá parênteses depois do nome da função. Por exemplo, se o nome de uma função é max( ), ela será escrita como max( ) quando referenciada no texto. Essa notação ajudará você a distinguir nomes de variáveis de nomes de funções neste texto. Segue um primeiro programa exemplo em linguagem C: #include <stdio.h> void main(){ printf (“Meu primeiro programa em C!!!\n”); } Neste exemplo temos a função main( ) que, ao ser executada, exibirá uma mensagem na tela. A impressão da mensagem é executada pela função printf( ) que recebe como parâmetro a mensagem “Meu primeiro programa em C!!!\n”. 6 declaração return. Então, esse valor é atribuído a resposta. Isto é, o valor retornado pela declaração return torna-se o valor de mul( ) na chamada de rotina. Assim como existem tipos diferentes de variáveis, existem tipos diferentes de valor de retorno. Certifique-se de que a variável que recebe o valor de retorno de uma função seja do mesmo tipo que o valor retornado pela função. O tipo retornado pela rotina mul( ) é int. Quando não explicitamos o tipo retornado por uma função, a linguagem C assume que é um int. É possível fazer com que uma função retorne usando-se a declaração return sem qualquer valor associada a ela, tornando o valor retornado indefinido. Também pode haver mais que um return numa função. 1.5.3 A FORMA GERAL DE UMA FUNÇÃO A forma geral de uma função é mostrada aqui: tipo_de_retorno nome_da_função (lista de parâmetros) { corpo do código da função } Para funções sem parâmetros, não haverá lista de parâmetros. 1.6 PALAVRAS RESERVADAS DA LINGUAGEM C A linguagem C, como todas as outras linguagens de programação, consiste de palavras reservadas e regras de sintaxe que se aplicam a cada palavra reservada. Uma palavra reservada é essencialmente um comando e, na maioria das vezes, as palavras reservadas de uma linguagem definem o que pode ser feito e como pode ser feito. O conjunto de palavras reservadas especificado pelo padrão ANSI C são as seguintes: auto Double int struct break Else long switch case Enum register typedef char Extern return union const Float short unsigned continue For signed void default Goto sizeof volatile do If static while Todas as palavras reservadas na linguagem C estão em letras minúsculas. Como definido anteriormente, a linguagem C faz diferenciação entre letras maiúsculas e minúsculas: portanto, else é uma palavra reservada, ELSE não. Uma palavra reservada não pode ser usada para outro propósito em um programa C. Por exemplo, ela não pode ser usada como nome de uma variável. 7 UNIDADE 2 – TIPOS DE DADOS, CONSTANTES, OPERADORES E EXPRESSÕES Variáveis e constantes são manipuladas pelos operadores para formar expressões. Estes são os alicerces da linguagem C. Ao contrário de outras linguagens de programação, notavelmente BASIC, que possui uma abordagem simples (e limitada) para variáveis, operadores e expressões, a linguagem C oferece muito maior poder e importância a esses elementos. 2.1 NOMES DE IDENTIFICADORES A linguagem C chama o que é usado para referenciar variáveis, funções, rótulos e vários outros objetos definidos pelo usuário de identificadores. Quanto aos nomes ou identificadores usados na declaração de variáveis, deve-se considerar as seguintes regras: • nomes de variáveis começam com uma letra ('A'..'Z', 'a'..'z') ou pelo underscore ('_'); • após podem ser seguidos dígitos, letras e underscores; • evite o uso do '_' no primeiro caractere do identificador de uma variável, pois este tipo de identificadores é de uso do sistema; • normalmente ao declararmos uma variável esta será inicializada com zero. Não se deve, no entanto, contar que isto sempre seja verdadeiro, portanto inicialize sempre as variáveis. Aqui estão alguns exemplos de nomes de identificadores corretos e incorretos: Correto Incorreto count test23 high_balance 1count Olá! Aqui high..balance Em C os primeiros 32 caracteres de um nome de identificador são significantes. Isso quer dizer que duas variáveis com os 32 primeiros caracteres em comum, diferindo somente no 33o, são consideradas iguais. Como você deve lembrar, em C, letras maiúsculas e minúsculas são tratadas como diferentes e distintas umas das outras. Por isso, count, Count e COUNT são três identificadores distintos. Um identificador não pode ser o mesmo que uma palavra reservada e não devem ter o mesmo nome de uma função – tanto uma função que você tenha escrito como uma função de biblioteca da linguagem C. 2.2 TIPOS DE DADOS Em C, os tipos básicos de dados são: 8 Tipo Tamanho (em bits) Intervalo char int float double void 8 16 32 64 0 -128 a 127 -32768 a 32767 3,4E-38 a 3,4E+38 1,7E-308 a 1,7E+308 sem valor Ao contrário do que ocorre nas maioria das linguagens de programação, como Pascal, C não possui um tipo para cadeias de caracteres (strings). Para utilizar strings em C é necessário declarar uma variável como sendo um vetor de caracteres. Desta forma para armazenar um nome de 30 caracteres usa-se o seguinte trecho de programa: char nome[31]; /*Não se esqueça que além dos 30 caracteres, deve-se reservar espaço para o final de string: 0, '\0' ou NULL */ 2.2.1 MODIFICADORES DE TIPOS Com a exceção do tipo void, os tipos básicos de dados podem ter vários modificadores precedendo-os. Um modificador é usado para alterar o significado do tipo base para adequá-los melhor às necessidades das várias situações. Uma lista de modificadores é mostrada aqui: signed unsigned long short Os modificadores signed, unsigned, long e short podem ser aplicados aos tipos de base caractere e inteira. Entretanto, long, também pode ser aplicado ao tipo double. A tabela a seguir mostra todas as combinações permitidas dos tipos básicos e dos modificadores de tipo. Tipo Tamanho (em bits) Intervalo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int float double long double 8 8 8 16 16 16 16 16 16 32 32 32 32 64 80 -128 a 127 0 a 255 -128 a 127 -32768 a 32767 0 a 65535 -32768 a 32767 -32768 a 32767 0 a 65535 -32768 a 32767 -2147483648 a 2147483647 -2147483648 a 2147483647 0 a 4294967295 3,4E-38 a 3,4E+38 1,7E-308 a 1,7E+308 3,4E-4932 a 1,1E+4932 11 2.4.2 CONSTANTES STRING A linguagem C suporta outro tipo de constante em adição àquelas dos tipos predefinidos: a string. Uma string é um conjunto de caracteres entre aspas. Por exemplo, “este é um teste” é uma string. Não confunda strings com caractere. Uma constante caractere simples fica entre dois apóstrofos, por exemplo ‘a’. Entretanto “a” é uma string que contém somente uma letra. 2.4.3 CÓDIGOS DE BARRA INVERTIDA Colocar todas as constantes caractere entre aspas funciona para muitos caracteres, mas alguns, como o retorno de carro, são impossíveis de serem inseridos em uma string a partir do teclado. Por isso, a linguagem C fornece constantes caractere mais barra invertida especiais. Estes códigos são mostrados na tabela a seguir. Código Significado \b \f \n \r \t \” \’ \0 \\ \v \a \N \xN Retrocesso Alimentação de formulário Nova linha Retorno de carro Tabulação horizontal Aspas Apóstrofo Nulo Barra invertida Tabulação vertical Sinal sonoro Constante octal Constante hexadecimal Você usa um código de barra invertida exatamente da mesma maneira como usa qualquer outro caractere. Por exemplo: ch = ‘\t’; printf (“este é um teste\n”); Esse fragmento de código primeiro atribui uma tabulação a ch e, então, imprime “este é um teste” na tela, seguido de uma nova linha. 2.5 OPERADORES A linguagem C é muito rica em operadores internos. Um operador é um símbolo que diz ao compilador para realizar manipulações matemáticas e lógicas específicas. A linguagem C possui três classes gerais de operadores: aritméticos, relacionais e lógicos e bit-a-bit. 12 2.5.1 OPERADOR DE ATRIBUIÇÃO O operador “=“ atribui um valor ou resultado de uma expressão contida a sua direita para a variável especificada a sua esquerda. Exemplos: a = 10; b = c * valor + getval(x); a = b = c = 1; /*Aceita associação sucessiva de valores*/ 2.5.2 OPERADORES ARITMÉTICOS Operam sobre números e expressões, resultando valores numéricos. Operador Ação + - * / % - soma subtração multiplicação divisão módulo da divisão (resto da divisão inteira) sinal negativo (operador unário) 2.5.3 OPERADORES RELACIONAIS Operam sobre expressões, resultando valores lógicos de TRUE ou FALSE. Operador Ação > >= < <= == != Maior maior ou igual Menor menor ou igual Igual não igual (diferente) Cuidado! Não existem os operadores relacionais: “=<“, “=>“ e “<>“. Não confunda a atribuição (“=“) com a comparação (“==“). 2.5.4 OPERADORES LÓGICOS Operam sobre expressões, resultando valores lógicos de TRUE ou FALSE. Possuem a característica de “short circuit”, ou seja, sua execução é curta e só é executada até o ponto necessário. Operador Ação && || ! operação AND operação OR operador de negação NOT (operador unário) 13 Exemplos de “short circuit”: (a == b) && (b == c) /*Se a != b não avalia o resto da expressão*/ (a == b) || (b == c) /*Se a == b não avalia o resto da expressão*/ 2.5.5 MANIPULAÇÃO DE BITS A manipulação é feita em todos os bits da variável a qual não pode ser do tipo float ou double. Operador Ação & | ^ << >> ~ bit and bit or bit xor - exclusive or shift left shift right bit not (complemento) Observação: x << n irá rotacionar n vezes a variável x à esquerda. 2.5.6 OPERADORES DE ASSINALAMENTO É expresso da seguinte forma: (operadores combinados) var = var op expr à var op= expr Onde tempos op como um dos seguintes operadores: Operador Ação + - * / % >> << & ^ | soma subtração multiplicação divisão módulo (resto da divisão) shift right shift left and xor - exclusive or or Exemplo de aplicação: i += 2; /* É equivalente a: i = i + 2 */ j -= 3; /* É equivalente a: j = j – 3 */ k >>= 3; /* É equivalente a: k = k >> 3; z &= flag; /* É equivalente a: z = z & flag; 16 char ch; int i; float f; double d; result = (ch/i) + (f * d) – (f + i); 2.7.2 MODELADORES (CASTS) É possível forçar uma expressão a ser de um tipo específico usando-se uma construção chamada de modelador. A forma geral de um modelador é: (tipo) expressão onde tipo é um dos tipos dado-padrão da linguagem C. Por exemplo, se x é um inteiro e você quer certificar-se de que a expressão x/2 resulta em um tipo float, garantindo um componente fracionário, pode escrever (float) x / 2; Aqui, o modelador (float) é associado com o x, o que faz com que o 2 seja elevado ao tipo float e o resultado seja um float. Entretanto, tome cuidado: se você escrever a expressão acima como segue, o componente fracionário não será considerado: (float) (x/2); Neste caso, uma divisão de inteiros é levada a cabo e o resultado é transformado em float. Modeladores são freqüentemente considerados como operadores. Como um operador, um modelador é unário e tem a mesma precedência de qualquer outro operador unário. 2.7.3 ESPAÇAMENTO E PARÊNTESES Você pode colocar espaços numa expressão ao seu critério para torná-la mais legível. Por exemplo, as duas expressões seguintes são as mesmas: int int double double double double double double 17 x=645/(num_entry)-y*(3217/balance); x = 645 / (num_entry) – y * (3127 / balance); O uso de parênteses redundantes ou adicionais não causará erros ou diminuirá a velocidade de execução da expressão. Você é estimulado a usar parênteses para tornar clara e exata a ordem de avaliação, tanto para você como para outros que precisarem entender o seu programa mais tarde. Por exemplo, qual das duas expressões seguintes é mais fácil de ler? x=y/3-24*temp-127; x = (y/3) – (34*temp) – 127; 2.8 ESQUELETO DE UM PROGRAMA EM C Todo o programa em C deve conter a função main( ). Esta função é responsável pelo início da execução, de forma semelhante ao bloco BEGIN/END. do Pascal. No C só existeM funções e não existe o conceito de procedimento, ou seja, todas devem retornar algo a quem a chamou, mesmo que o retorno seja do tipo void (sem valor). Os comentários no C são feitos através do par “/*” e “*/”, sendo um “/*” usado para abrir um comentário e um “*/” para encerrá-lo. Um bloco de comandos é delimitado por chaves (“{“ e “}”). Exemplo: #include <stdio.h> /* No início do programa, declara-se as bibliotecas usadas */ int a_global; /* Declaração de variáveis globais */ /* Declaração de funções do programador, se for o caso */ int main(){ /* Declaração da função principal. Sempre necessária */ int conta; /* Variáveis locais a esta função */ /* comandos ... */ } 18 UNIDADE 3 – ESTRUTURAS BÁSICAS DE PROGRAMAÇÃO (FLUXO DE CONTROLE) Os comandos de fluxo de controle de uma linguagem especificam a ordem em que a computação é feita. 3.1 COMANDOS E BLOCOS Uma expressão tal como x = 0 ou i++ ou printf(...) torna-se um comando quando seguida por um ponto-e-vírgula, como em: x = 0; i++; printf (“Olá !”); Em C, o ponto-e-vírgula é um terminador de comandos, e não um separador como em linguagens do tipo Pascal. As chaves { e } são usadas para agruparem declarações e comandos num comando composto ou bloco de modo que são sintaticamente equivalentes a um único comando. Não há um ponto-e-vírgula após a chave direita que termina um bloco. 3.2 PRINTF( ) Quase todos os programas exemplo vistos até agora, que realizam saída para a tela, usaram a função printf( ). Vamos dar uma olhada mais formal nela agora. A forma geral da função printf( ) é: printf (“string de controle”, lista de argumentos); Na função printf( ), a string de controle contém tanto caracteres para serem impressos na tela como códigos de formato que especificam como apresentar o restante dos argumentos. Existem códigos de formato que você já deve ter aprendido até aqui: Código Significado %c %d %i %e %E %f %g %G %o Exibe um caractere Exibe um inteiro em formato decimal Exibe um inteiro Exibe um número em notação científica (com e minúsculo) Exibe um número em notação científica (com E maiúsculo) Exibe um ponto flutuante em formato decimal Usa %e ou %f, o que for menor O mesmo que %g, só que um E maiúsculo é usado se o formato %e for escolhido Exibe um número em notação octal 21 scanf(“%d,%d”, &a, &b); //entrada válida 10,15 Todas as variáveis usadas para receber valores por meio da função scanf( ) deverão ser passadas pelos seus endereços. Por exemplo, para ler um inteiro em uma variável count, você poderia usar a seguinte chamada à função scanf( ): scanf(“%d”, &count); As strings serão lidas em vetores (cadeias de caracteres) e o nome do vetor é o endereço do primeiro elemento do vetor. Então, para ler uma string no vetor de caracteres nome, você deve usar o seguinte comando: scanf(“%s”, nome); Nesse caso, nome já em um endereço e não precisa ser precedido pelo operador &. Os itens de dados de entrada devem ser separados por espaços, tabulações ou novas linhas. Pontuações como vírgula, ponto-e-vírgula e semelhantes não contam como operadores. Isso significa que scanf(“%d%d”, &r, &c); aceitará uma entrada dos números 10 20, mas falhará com 10,20. Como na função printf( ), os códigos de formato da função scanf( ) devem ser correspondidos na ordem com as variáveis que estão recebendo a entrada na lista de argumento. Um * colocado depois do % e antes do código de formato lerá um dado de um tipo especificado, mas suprimirá a sua atribuição. Assim, scanf(“%d%*c%d”, &x, &y); dando-se a entrada 10/20, colocará o valor 10 em x descartando o sinal de divisão, e dará a y o valor 20. Os comandos de formato podem especificar um campo modificador de comprimento máximo. Esse modificador é um número inteiro colocado entre o sinal % e o código de comando de formato, que limita o número de caracteres lidos para qualquer campo. Por exemplo, para ler não mais que 20 caracteres em str, você pode escrever: scanf(“%20s”, str); Se o apontador de entrada é maior do que 20 caracteres, uma chamada subseqüentes para entrada começará onde ela pára. Por exemplo, se você digitar ABCDEFGHIJKLMNOPQRSTUVWXYZ em resposta à chamada scanf( ), nesse exemplo, somente os 20 primeiros caracteres, até o “T”, serão colocados em str por causa do especificador de tamanho máximo. Isso significa que os caracteres restantes “UVWXYZ” não são usados. Se uma outra chamada à função scanf( ) é feita, tal como: 22 scanf(“%s”, str); então “UVWXYZ” é colocado em str. A entrada para o campo pode ser terminada, antes que o campo de comprimento máximo seja alcançado, se um caractere de espaço em branco é encontrado. Nesse caso, a função scanf( ) move-se para o próximo campo. Ainda que espaços, tabulações e novas linhas sejam usados como separadores de campos, quando da leitura de um único caractere, esses últimos são lidos como qualquer outro caractere. Por exemplo, com uma entrada de “x y”; scanf(“%c%c%c”, &a, &b, &c); retornará com o caractere “x” em a, um espaço em b e o caractere “y” em c. Você não pode usar a função scanf( ) para exibir uma mensagem ao usuário. Portanto, todas as mensagens devem ser feitas explicitamente antes da chamada à função scanf( ). A função scanf( ) inclui também uma característica muito poderosa chamada scanset. Um scanset define uma lista de caracteres que serão correspondidos por scanf( ). A função scanf( ) continuará a ler caracteres enquanto eles estiverem no scanset. Assim que um caractere entrado não corresponder a qualquer um do scanset, a função scanf( ) segue para o próximo especificador de formato (se existir). Um scanset é definido colocando-se uma lista de caracteres que você quer que seja examinada entre chaves. A chave inicial deve ser prefixada por um sinal de porcentagem. Por exemplo, este scanset diz à função scanf( ) para ler somente os dígitos de 0 a 9: %[1234567890] O argumento correspondente a scanset deve ser uma variável string. Após retornar de função scanf( ), a variável conterá uma string terminada com um nulo com os caracteres lidos. Para ver como isso funciona, considere este programa: #include <stdio.h> void main(){ char s1[80], s2[80]; scanf (“%[1234567890]%s”, s1, s2); printf (“\n%s| |%s”, s1, s2); } Experimente esse programa usando a entrada “123456789abcdefg987654” seguida por um retorno de carro. O programa exibirá, então: 123456789| |abcdefg987654 23 Uma vez que “a” não faz parte do scanset, a função scanf( ) pára de ler os caracteres em s1 quando ele é encontrado e os caracteres restantes são colocados em s2. Você pode especificar um intervalo dentro de um scanset usando um hífen. Por exemplo, isto diz à função scanf( ) para aceitar os caracteres de A a Z: %[A-Z] Você pode especificar mais de um intervalo dentro de um scanset. Por exemplo, este programa lê dígitos e letras. Ele também ilustra que você pode usar o especificador de campo máximo como um scanset. #include <stdio.h> void main(){ char str[80]; printf (“Informe dígitos e letras: ”); scanf (“%78[a-z0-9]”, str); printf (“\n%s, str); } Você pode especificar um conjunto invertido se o primeiro caractere é um ^. Quando está presente, o ^ instrui a função scanf( ) a aceitar quaisquer caracteres que não estão definidos no scanset. Um ponto importante a lembrar é que o scanset difere letras minúsculas de maiúsculas. Portanto, se você quiser examinar tanto letras maiúsculas como minúsculas, deve especificá-las individualmente. 3.4 A DECLARAÇÃO if A forma geral da declaração if é if (condição){ comandos; } else{ comandos; } A cláusula else é opcional. Se condição for verdadeira (qualquer coisa diferente de 0), o bloco que forma o destino de if será executado; caso contrário o bloco que forma o destino de else será executado (desde que exista else). Lembre-se que somente o código associado a if ou o código associado a else será executado, nunca os dois. Tenha em mente também que o destino dos dois, if e else, pode ser um comando simples ou um bloco de comandos. Para demonstrar o comando if vamos escrever um programa simples que converte bases numéricas. Este programa será capaz de apresentar as seguintes 26 void main(){ int opcao; int valor; printf (“Converter: \n”); printf (“1: decimal para hexadecimal\n”); printf (“2: hexadecimal para decimal\n”); printf (“\nInforme sua opção: ”); scanf (“%d”, &opcao); if (opcao == 1){ printf (“\nInforme o valor em decimal: ”); scanf (“%d”, &valor); printf (“%d em hexadecimal e: %x”, valor, valor); } else if (opcao == 2){ printf (“\nInforme o valor em hexadecimal: ”); scanf (“%x”, &valor); printf (“%x em decimal e: %d”, valor, valor); } else { printf (“\nA opção escolhida é inválida.”) } } 3.4.3 A EXPRESSÃO CONDICIONAL Algumas vezes, iniciantes na linguagem C confundem-se pelo fato de que qualquer expressão válida na linguagem C pode ser usada para controla a declaração if. Isto é, o tipo de expressão não precisa se restringir àquelas envolvendo operadores relacionais e lógicos. Só é requerido que a expressão resulte em um valor zero ou não zero. Por exemplo, este programa lê dois inteiros do teclado e mostra o quociente. Para evitar um erro de divisão por zero, uma declaração if é usada para controlar o segundo número. /* Divide o primeiro número pelo segundo*/ #include <stdio.h> void main(){ int a, b; printf (“Informe dois números: ”); scanf (“%d%d”, &a, &b); if (b) printf (“%d\n”, a/b); else printf (“Não posso dividir por zero\n”); } 27 Essa abordagem funciona porque, se b for zero, a condição controlando o if é falsa e a instrução else é executada. Caso contrário, a expressão é verdadeira (não zero) e a divisão é realizada. Não é necessário escrever uma declaração if como esta if (b != 0) printf (“%d\n”, a/b); porque é redundante. 3.4.4 ifs ANINHADOS Um dos muitos aspectos que causam confusão na declaração if, em qualquer linguagem de programação, são os ifs aninhados. Um if aninhado é uma declaração if que é objeto de um if ou um else. Os ifs aninhados são incômodos por poderem dificultar saber qual else está associado a qual if. Considere este exemplo: if (x) if (y) printf (“1”); else printf (“2”); A qual if o else se refere? Felizmente, a linguagem C fornece uma regra muito simples para resolver essa questão. Em C, o else é ligado ao if mais próximo dentro do mesmo bloco de código que já não tenha uma declaração else associada a ele. Neste caso o else é associado à declaração if(y). Para fazer com que else seja associado à declaração if(x), deve-se usar chaves para sobrepor a sua associação normal, como mostrado aqui: if (x){ if (y) printf (“1”); } else printf (“2”); O else agora está associado ao if(x), já que ele não é parte do bloco de código do if(y). Exercícios: 1) Escrever um trecho de código que receba duas variáveis inteiras e atribua a uma terceira variável o maior valor. 2) O mesmo problema, em forma de função, retornando o maior valor. 3) Fazer uma função que receba uma variável do tipo inteiro e retorne: 1, se o valor recebido for maior do que 0; 0, se o valor recebido for igual a zero; e -1, se o valor recebido for menor do que 0. Use o comando if. 4) Escreva um programa que lê um par de coordenadas (x,y) inteiras e imprime uma mensagem informando em qual quadrante está o ponto. O programa deve identificar se o ponto está sobre algum dos eixos. 28 5) Escrever uma função que recebe dois inteiros (a e b) e um código inteiro (cod) e retorne: a + b, se cod >= 0; e |a - b|, se cod < 0. 3.5 A DECLARAÇÃO switch Ainda que o encadeamento if-else-if possa realizar testes de múltipla escolha, ele quase nunca é elegante. O código pode ser muito difícil de acompanhar e pode confundir até mesmo o seu autor. Por esse motivo, a linguagem C tem internamente uma declaração de decisão de múltipla escolha chamada de switch. Na declaração switch, a variável é sucessivamente testada contra uma lista de inteiros ou constantes caractere. Quando uma associação é encontrada, o conjunto de comandos associado com a constante é executado. As constantes não precisam sequer estar em qualquer ordem especial. A forma geral da declaração switch é: switch (variável){ case constante1: commandos; break; case constante2: commandos; break; case constante3: commandos; break; M default commandos; } onde a declaração default é executada se nenhuma correspondência for encontrada. O default é opcional e, se ele não estiver presente, nenhuma ação será realizada se todas as correspondências falharem. Quando uma correspondência é encontrada, os comandos associados a case são executados até que o break seja encontrado ou até que se encontre o final do switch. Há três coisas importantes a saber sobre a declaração switch: 1) Ele difere do if, já que o switch pode testar somente igualdades, enquanto a expressão condicional if pode ser de qualquer tipo; 2) Nunca duas constantes case no mesmo switch podem ter valores iguais. Obviamente, uma declaração switch dentro de outra declaração switch pode ter as mesmas constantes case; 3) Uma declaração switch é mais eficiente que um encadeamento if-else-if. É possível especificar comandos no switch que serão executados caso nenhuma correspondência seja encontrada. Basta adicionar uma declaração default. A declaração default é uma boa maneira de direcionar qualquer final livre que possa ficar pendente na declaração switch. Por exemplo, no programa de conversão de base numérica, pode-se usar uma declaração default para informar ao usuário que uma resposta inválida foi dada e para tentar outra vez. 31 case 0: printf (“erro de divisão por zero”); break; case 1: process (x, y); } break; case 2: M Como outro exemplo, um programa de banco de dados bastante simples mostrado a seguir ilustra como se pode usar uma declaração switch aninhada. Este programa solicita ao usuário a região e a letra inicial do nome do vendedor e, então, mostra o demonstrativo de vendas do mesmo. Switchs aninhados são requeridos uma vez que muitos vendedores têm a mesma letra inicial. Note que uma nova função, toupper( ), é introduzida. Ela retorna a letra maiúscula correspondente do seu argumento caractere. Ela é usada neste programa para permitir que o usuário insira informações tanto em letra maiúscula como em letra minúscula. A função complementar de toupper( ) é tolower( ), que converte caracteres maiúsculos em minúsculos. Ambas as funções estão contidas na biblioteca ctype.h. /* Um banco de dados simples de vendedores por região */ #include <stdio.h> #include <ctype.h> void main(){ char regiao, vendedor; printf (“As regiões são: Leste, Oeste e Norte\n”); printf (“Informe a primeira letra da região: ”); regiao = getche(); regiao = toupper(regiao); //converte para maiúsculas printf (“\n”); switch (regiao){ case ‘L’: printf (“Vendedores são: Rafael, João e Maria \n”); printf (“Informe a primeira letra do vendedor: ”); vendedor = toupper(getche()); printf (“\n”); switch (vendedor){ case ‘R’: printf (“Vendas: R$%d\n”, 10000); break; case ‘J’: printf (“Vendas: R$%d\n”, 12000); break; 32 case ‘M’: printf (“Vendas: R$%d\n”, 14000); } break; case ‘O’: printf (“Vendedores são: Ronaldo, Lisa e Hilton\n”); printf (“Informe a primeira letra do vendedor: ”); vendedor = toupper(getche()); printf (“\n”); switch (vendedor){ case ‘R’: printf (“Vendas: R$%d\n”, 10000); break; case ‘L’: printf (“Vendas: R$%d\n”, 9500); break; case ‘H’: printf (“Vendas: R$%d\n”, 13000); } break; case ‘N’: printf (“Vendedores são: Tomás, João e Raquel\n”); printf (“Informe a primeira letra do vendedor: ”); vendedor = toupper(getche()); printf (“\n”); switch (vendedor){ case ‘R’: printf (“Vendas: R$%d\n”, 5000); break; case ‘J’: printf (“Vendas: R$%d\n”, 9000); break; case ‘T’: printf (“Vendas: R$%d\n”, 14000); } break; } } Para ver como o programa funciona , selecione a região Oeste, digitando O. Isso indica que case ‘O’ é selecionado pela declaração switch externa. Para ver o total de vendas de Hilton, digite H. Isso faz com que o valor 13000 seja apresentado. Note que a declaração break em um switch aninhado não tem efeito no 33 switch externo. Exercício: 1) Escreva um programa que pede para o usuário entrar um número correspondente a um dia da semana e que então apresente na tela o nome do dia. utilizando o comando switch. 3.6 LAÇOS DE REPETIÇÃO Os laços de repetição permite que um conjunto de instruções seja repetido até que uma condição seja encontrada. A linguagem C suporta os mesmos tipos de laços que outras linguagens estruturadas modernas. Os laços em C são o for, o while e o do-while. Cada um deles será examinado separadamente. 3.7 O LAÇO for A forma geral do laço for é for (inicialização; condição; incremento){ comandos; } Na sua forma simples, a inicialização é um comando de atribuição usado para inicializar a variável de controle do laço. A condição é usualmente uma expressão relacional que determina quando o laço terminará pelo teste da variável de controle do laço contra algum valor. O incremento usualmente define como a variável de controle do laço mudará cada vez que a repetição for realizada. Estas três maiores divisões devem ser separadas por ponto-e-vírgula. O laço for continuará a execução do programa no comando seguinte a for. Para um exemplo simples, o seguinte programa imprime os números de 1 a 100 na tela: #include <stdio.h> void main(){ int x; for (x = 1; x <= 100; x++){ printf (“%d “, x); } } Neste programa, x é inicializado em 1. Desde que x seja menor ou igual a 100, a função printf( ) é chamada. Depois que a função printf( ) retorna, x é incrementado em 1 e testado para ver se é menor ou igual a 100. Este processo 36 #include <stdio.h> #include <ctype.h> void main(){ int i, j, resposta; char fim = ‘ ‘; for (i = 0, i < 100 && fim != ‘N’; i++){ for (j = 1; j < 10; j++){ printf (“quanto é %d + %d? “, i, j); scanf (“%d”, &resposta); if (resposta != (i + j)){ printf (“errado\n”); } else{ printf (“certo\n”); } } printf (“Mais ?”); fim = toupper(getche()); printf (“\n”); } } Uma outra interessante variação do laço for é possível porque, atualmente, cada uma das três partes da declaração do for podem consistir de qualquer expressão válida da linguagem C. Elas não precisam ter nada que faça a seção ser usada de maneira padrão. Considerando isso, vejamos o seguinte exemplo: #include <stdio.h> void main(){ int t; for (prompt(); t = readnum(); prompt()) { sqrnum(t); } } void prompt(){ printf (“Informe um inteiro: ”); } 37 int readnum(){ int t; scanf (“%d”, &t); return t; } void sqrnum (int num){ printf (“%d\n”, num * num); } Esse programa primeiro apresenta uma solicitação e, então, aguarda pela resposta. Quando um número é informado, o seu quadrado é exibido e novamente é feita uma solicitação. Isso prossegue até que um 0 seja digitado. Se você olhar com atenção o laço for na função main( ), verá que cada parte do for é compreendida por chamadas a funções que fazem a solicitação ao usuário e lêem um número do teclado. Se o número informado é zero, o laço termina, já que a expressão condicional será falsa; caso contrário, o quadrado do número é calculado. Assim, nesse laço for as partes de inicialização e incremento são usadas de modo não tradicional, mas perfeitamente válido. Outra característica interessante do laço for é que pedaços da definição do laço não necessitam estar lá. Na verdade, não é necessário que uma extensão esteja presente em qualquer das partes – as expressões são opcionais. Por exemplo, este laço será executado até que o número 10 seja informado. for (x = 0; x!= 10; ) scanf (“%d”, &x); Note que a parte de incremento da definição do for está vazia. Isso significa que, cada vez que o laço é repetido, a variável x é testada para verificar se ela é igual a 10, mas x não é modificado de nenhuma forma. Entretanto, se você digital 10, a condição do laço torna-se falsa e o laço encerra-se. 3.7.2 O LAÇO INFINITO Um dos usos mais interessantes do laço for é na criação de laços infinitos. Nenhuma das três expressões que formam o laço for são requeridas, portanto, é possível fazer um laço sem fim, deixando-se a expressão condicional vazia, como mostra este exemplo. for ( ; ; ){ printf (“Este laço será executado para sempre.\n”); } 3.7.3 A INTERRUPÇÃO DE UM LAÇO for A construção for ( ; ; ) não cria necessariamente um laço infinito tendo em vista uma nova aplicação da declaração break da linguagem C. Quando encontrada 38 em algum lugar dentro do corpo de um laço, a declaração break faz com que o laço termine. O controle do programa segue no código posterior do laço, como mostrado aqui. for ( ; ; ){ ch = getche(); //lê um caractere if (ch = ‘A’) break; //sai do laço } printf (“Você digitou a letra A”); Este laço é executado até que um caractere A seja digitado no teclado. 3.7.4 USANDO LAÇOS for SEM CONTEÚDO Um bloco de comandos, como definido pela sintaxe da linguagem C, pode ser vazio. Isso significa que o conteúdo do for (ou qualquer outro laço) também pode ser vazio. Essa característica pode ser usada para aumentar a eficiência de certos algoritmos, bem como para criar laços de tempo e espera. É assim que se cria um tempo de espera usando-se o for. for (t = 0; t < ALGUM VALOR; t++); Exercícios: 1) Fazer uma função que receba um número e retorne o fatorial deste número, usando for. (Lembre que 0!=1 e 1!=1). 2) Fazer uma rotina para contar as ocorrências do caractere 'a' em uma string, usando for. 3) Fazer uma rotina para achar o maior valor de um vetor de 10 posições, usando for. 4) Fazer uma rotina para contar o número de ocorrências das letras de 'A' até 'Z' em um string. 5) Escrever um programa que gera e escreve os 5 primeiros números perfeitos. Um número perfeito é aquele que é igual a soma dos seus divisores. Por exemplo: 6 = 1 + 2 + 3 28 = 1 + 2 + 4 + 7 + 14 etc. 3.8 O LAÇO while O segundo laço disponível na linguagem C é o while. A sua forma geral é while (condição){ comandos; } 41 do{ scanf (“%d”, &num); }while(num > 100); } Talvez o uso mais comum do laço do-while seja em uma rotina de seleção em menu. Já que você sempre precisará de uma rotina de seleção em menu para ser executada no mínimo uma vez, o laço do-while é uma opção óbvia. O seguinte fragmento mostra como adicionar um laço do-while no menu do programa de conversão numérica. /* Assegura que o usuário especificou uma opção válida */ do{ printf (“Converte:\n”); printf (“ 1: decimal para hexadecimal\n”); printf (“ 2: hexadecimal para decimal\n”); printf (“informe sua opção: ”); scanf (“%d”, &opcao); }while(opcao < 1 || opcao > 2); Depois que a opção tiver sido apresentada, o programa se repetirá até que uma opção válida seja selecionada. 3.10 LAÇOS ANINHADOS Quando um laço está dentro de outro, diz-se que o laço mais interno é aninhado. Laços aninhados propiciam o meio de resolver alguns problemas interessantes de programação. Por exemplo, este pequeno programa exibe as quatro primeiras potências dos números de 1 a 9. /* Exibe uma tabela das 4 primeiras potencies de 1 a 9 */ #include <stdio.h> void main(){ int i, j, k, temp; printf(“ i i^2 i^3 i^4\n”); for (i = 1; i < 10; i++){ // laço externo for (j = 1; j < 5; j++) { // primeiro aninhamento temp = 1; for (k = 0; k < j; k++) // segundo aninhamento temp = temp * i; printf (“%9d”, temp); 42 } printf (“\n”); } } Algumas vezes, é importante determinar quantas interações o laço interno executa. Este número é conseguido multiplicando-se o número de vezes que o laço externo intera pelo número de vezes que o laço interno é repetido cada vez que é executado. No exemplo do programa de potência, o laço externo é repetido nove vezes e o segundo laço, quatro vezes; assim, o segundo laço interagirá 36 vezes. O laço interno é executado, em média, duas vezes; dessa forma, o número total de interações é 72. Como no último exemplo, um melhoramento final para o programa de conversão de base numérica usando-se laços aninhados é mostrado aqui. O laço externo faz com que o programa seja executado até que o usuário diga para parar. o laço interno assegura que o usuário informará uma seleção válida do menu. Agora, em vez de simplesmente converter um número toda vez que for executado, o programa repete até que o usuário queira parar. /* Programa de conversão de base numérica – versão final decimal ---> hexadecimal hexadecimal ---> decimal*/ #include <stdio.h> void main(){ int opcao; int valor; //repete até que o usuário diga para terminar do{ //assegura que o usuário especificou uma opção válida do{ printf (“Converter: \n”); printf (“1: decimal para hexadecimal\n”); printf (“2: hexadecimal para decimal\n”); printf (“3: fim\n”); printf (“\nInforme sua opção: ”); scanf (“%d”, &opcao); }while(opcao < 1 || opcao > 3); switch(opcao){ case 1: printf (“\nInforme o valor em decimal: ”) scanf (“%d”, &valor); printf (“%d em hexadecimal e: %x”, valor, valor); break; case 2: printf (“\nInforme o valor em hexadecimal: ”) 43 scanf (“%x”, &valor); printf (“%x em decimal e: %d”, valor, valor); break; case 3: default: printf (“\nOpção inválida. Tente outra vez.”) } printf (“\n”); }while(opcao != 5); } 3.11 QUEBRANDO UM LAÇO A declaração break tem dois usos. O primeiro é terminar um case na declaração switch. Esse uso é coberto na seção deste capítulo onde o switch foi inicialmente apresentado. O segundo uso é forçar a terminação imediata de um laço, passando sobre o teste condicional normal do laço. Este uso é examinado aqui. Quando uma declaração break é encontrada dentro de um laço, este é imediatamente encerrado e o controle do programa é retornado na declaração seguinte ao laço. Por exemplo: #include <stdio.h> void main(){ int t; for (t = 0; t < 100; t++){ printf (“%d”, t); if (t == 10) break; } } Esse programa imprimirá os números de 0 a 10 na tela e, então, terminará devido à declaração break, que fará com que haja uma saída imediata do laço, sobrepondo-se ao teste condicional t < 100 construído dentro do laço. É importante ressaltar que um break causará uma saída somente do laço mais interno. Por exemplo, considere este fragmento: for (t = 0; t < 100; ++t){ count = 1; for ( ; ; ){ printf (“%d”, count); count++; if (count == 10) break; } } Ele imprimirá os números de 1 a 10 na tela cem vezes. Toda vez que a 46 pronto = 0; for (...){ for (...){ while (...){ if(...){ pronto = 1; break; } M } if (pronto) break; } if (pronto) break; } Se você usar a declaração goto, deve fazê-lo restritamente. Mas, se o código ficar muito mais difícil de se entender sem ele ou se a velocidade de execução do código é crítica, então, certamente, use o goto. 47 UNIDADE 4 – VETORES, MATRIZES E STRINGS 4.1 INTRODUÇÃO Vetores são usados para tratamento de conjuntos de dados que possuem as mesmas características. Uma das vantagens de usar vetores é que o conjunto recebe um nome comum e elementos deste conjunto são referenciados através de índices. Pelo nome vetor estaremos referenciando estruturas que podem ter mais de uma dimensão, como por exemplo matrizes de duas dimensões. 4.2 DECLARAÇÃO DE VETORES UNIDIMENSIONAIS A forma geral da declaração de um vetor é: tipo nome [tamanho]; onde tipo é um tipo qualquer dados, nome é o nome pelo qual o vetor vai ser referenciado e tamanho é o número de elementos que o vetor vai conter. Observar que, em C, o primeiro elemento tem índice 0 e o último (tamanho –1). Exemplos de declarações de vetores são: int numeros[1000]; /* conjunto de 1000 numeros inteiros */ float notas[65]; /* conjunto de 65 numeros reais */ char nome[40]; /* conjunto de 40 caracteres */ O espaço de memória, em bytes, ocupado por um vetor é igual a: Espaço = tamanho * (número de bytes ocupado por tipo) É importante notar que em C não há verificação de limites em vetores. Isto significa que é possível ultrapassar o fim de um vetor e escrever em outras variáveis, ou mesmo em trechos de código. É tarefa do programador fazer com que os índices dos vetores estejam sempre dentro dos limites estabelecidos pela declaração do vetor. O exemplo, mostrado abaixo, ilustra como se declara um vetor, inicializa seus valores e imprime o conteúdo. Notar o uso da diretiva #define DIM 5 para definir uma constante, que posteriormente foi usada para estabelecer o tamanho do vetor. Esta constante passa a ser usada nas referências ao vetor, observar o comando de geração do conjunto. Caso seja necessário trocar o tamanho do vetor basta alterar o valor da constante. /*Este programa gera um vetor contendo números inteiros*/ #define DIM 5 #include <stdio.h> void main(){ 48 int vetor[DIM]; unsigned int i, num; printf (“Entre com o numero inicial do conjunto. ”); scanf (“%d”, &num); /* Geração do conjunto */ for (i = 0 ; i < DIM; i++) vetor[i] = num++; /* Impressão do conjunto */ for (i = 0; i < DIM; i++) printf (“Elemento %d = %d\n”, i, vetor[i]); } O exemplo, mostrado a seguir, calcula o produto escalar de dois vetores inteiros. Observar como na leitura dos elementos do vetor usa-se o operador de endereço & antes do nome de cada elemento. /*Definições*/ #define DIM 5 #include <stdio.h> void main(){ int vetor1[DIM], vetor2[DIM], i, prod = 0; printf (“Entre com um vetor de %d elementos\n”, DIM); for (i = 0; i < DIM; i++){ printf (“Elemento %d “, i); scanf (“%d”, &vetor1[i]); } printf(“Entre com um outro vetor de %d elementos\n”, DIM); for (i = 0; i < DIM; i++){ printf (“Elemento %d “, i); scanf (“%d”, &vetor2[i]); } for (i = 0; i < DIM; i++) prod += vetor1[i] * vetor2[i]; printf(“O produto vale %d”, prod); } O exemplo, mostrado a seguir ilustra o método da bolha para ordenação em ordem crescente de um vetor de inteiros. Neste método a cada etapa o maior elemento é movido para a sua posição.
Docsity logo



Copyright © 2024 Ladybird Srl - Via Leonardo da Vinci 16, 10126, Torino, Italy - VAT 10816460017 - All rights reserved