Pular para o conteúdo principal

Capítulo Capítulo. 3 (VARIÁVEIS, CONSTANTES, OPERADORES E

As estruturas de controle de fluxo são fundamentais para qualquer linguagem de

programação. Sem elas só haveria uma maneira do programa ser executado: de cima para baixo comando por comando. Não haveria condições, repetições ou saltos. A linguagem C possui diversos comandos de controle de fluxo. É possível resolver todos os problemas sem utilizar todas elas, mas devemos nos lembrar que a elegância e facilidade de entendimento de um programa dependem do uso correto das estruturas no local certo.

O Comando if

Já introduzimos o comando if. Sua forma geral é:

if (condição) declaração;

A expressão, na condição, será avaliada. Se ela for zero, a declaração não será

executada. Se a condição for diferente de zero a declaração será executada. Aqui

reapresentamos o exemplo de um uso do comando if:

#include

int main ()

{

int num;

printf ("Digite um numero: ");

scanf ("%d",&num);

if (num>10)

printf ("\n\nO numero e maior que 10");

if (num==10)

{

printf ("\n\nVoce acertou!\n");

printf ("O numero e igual a 10.");

}

if (num<10)

printf ("\n\nO numero e menor que 10");

return(0);

23

}

O else

Podemos pensar no comando else como sendo um complemento do comando if. O

comando if completo tem a seguinte forma geral:

if (condição) declaração_1;

else declaração_2;

A expressão da condição será avaliada. Se ela for diferente de zero a declaração 1 será executada. Se for zero a declaração 2 será executada. É importante nunca esquecer que, quando usamos a estrutura if-else, estamos garantindo que uma das duas declarações será executada. Nunca serão executadas as duas ou nenhuma delas. Abaixo está um exemplo do uso do if-else que deve funcionar como o programa da seção anterior

#include

int main ()

{

int num;

printf ("Digite um numero: ");

scanf ("%d",&num);

if (num==10)

{

printf ("\n\nVoce acertou!\n");

printf ("O numero e igual a 10.\n");

}

else

{

printf ("\n\nVoce errou!\n");

printf ("O numero e diferente de 10.\n");

}

return(0);

}

O if-else-if

A estrutura if-else-if é apenas uma extensão da estrutura if-else. Sua forma geral pode ser escrita como sendo:

if (condição_1) declaração_1;

else if (condição_2) declaração_2;

else if (condição_3) declaração_3;

else if (condição_n) declaração_n;

else declaração_default;

A estrutura acima funciona da seguinte maneira: o programa começa a testar as

condições começando pela 1 e continua a testar até que ele ache uma expressão cujo resultado dê diferente de zero. Neste caso ele executa a declaração correspondente. Só uma declaração será executada, ou seja, só será executada a declaração equivalente à primeira condição que der diferente de zero. A última declaração (default) é a que será executada no caso de todas as condições darem zero e é opcional. Um exemplo da estrutura acima:

#include

int main ()

{

int num;

printf ("Digite um numero: ");

scanf ("%d",&num);

if (num>10)

printf ("\n\nO numero e maior que 10");

24

else if (num==10)

{

printf ("\n\nVoce acertou!\n");

printf ("O numero e igual a 10.");

}

else if (num<10)

printf ("\n\nO numero e menor que 10");

return(0);

}

A expressão condicional

Quando o compilador avalia uma condição, ele quer um valor de retorno para poder

tomar a decisão. Mas esta expressão não necessita ser uma expressão no sentido

convencional. Uma variável sozinha pode ser uma "expressão" e esta retorna o seu próprio valor. Isto quer dizer que teremos as seguintes expressões:

int num;

if (num!=0) ....

if (num==0) ....

for (i = 0; string[i] == ’\0’; i++)

equivalem a

int num;

if (num) ....

if (!num) ....

for (i = 0; string[i]; i++)

Isto quer dizer que podemos simplificar algumas expressões simples.

ifs aninhados

O if aninhado é simplesmente um if dentro da declaração de um outro if externo. O

único cuidado que devemos ter é o de saber exatamente a qual if um determinado else está ligado. Vejamos um exemplo:

#include

int main ()

{

int num;

printf ("Digite um numero: ");

scanf ("%d",&num);

if (num==10)

{

printf ("\n\nVoce acertou!\n");

printf ("O numero e igual a 10.\n");

}

else

{

if (num>10)

{

printf ("O numero e maior que 10.");

}

else

{

printf ("O numero e menor que 10.");

}

}

25

return(0);

}

O Operador ?

Uma expressão como:

if (a>0)

b=-150;

else

b=150;

pode ser simplificada usando-se o operador ? da seguinte maneira:

b=a>0?-150:150;

De uma maneira geral expressões do tipo:

if (condição)

expressão_1;

else

expressão_2;

podem ser substituídas por:

condição?expressão_1:expressão_2;

O operador ? é limitado (não atende a uma gama muito grande de casos) mas pode ser usado para simplificar expressões complicadas. Uma aplicação interessante é a do contador circular. Veja o exemplo:

#include

int main()

{

int index = 0, contador;

char letras[5] = "Joao";

for (contador=0; contador <>

{

printf("\n%c",letras[index]);

(index==3) ? index=0: ++index;

}

}

O nome Joao é escrito na tela verticalmente até a variável contador determinar o término do programa. Enquanto isto a variável index assume os valores 0, 1, 2, 3, , 0, 1, ... progressivamente.

AUTO-AVALIAÇÃO

Veja como você está:

Altere o último exemplo para que ele escreva cada letra 5 vezes seguidas. Para isto, use um ’if’ para testar se o contador é divisível por cinco (utilize o operador %) e só então realizar a atualização em index.

O Comando switch

O comando if-else e o comando switch são os dois comandos de tomada de decisão.

Sem dúvida alguma o mais importante dos dois é o if, mas o comando switch tem aplicações valiosas. Mais uma vez vale lembrar que devemos usar o comando certo no local certo. Isto assegura um código limpo e de fácil entendimento. O comando switch é próprio para se testar uma variável em relação a diversos valores pré-estabelecidos. Sua forma geral é:

switch (variável)

{

case constante_1:

declaração_1;

break;

case constante_2:

declaração_2;

break;

.

.

.

case constante_n:

declaração_n;

break;

default

declaração_default;

}

Podemos fazer uma analogia entre o switch e a estrutura if-else-if apresentada

anteriormente. A diferença fundamental é que a estrutura switch não aceita expressões. Aceita apenas constantes. O switch testa a variável e executa a declaração cujo case corresponda ao valor atual da variável. A declaração default é opcional e será executada apenas se a variável, que está sendo testada, não for igual a nenhuma das constantes. O comando break, faz com que o switch seja interrompido assim que uma das declarações seja executada. Mas ele não é essencial ao comando switch. Se após a execução da declaração não houver um break, o programa continuará executando. Isto pode ser útil em algumas situações, mas eu recomendo cuidado. Veremos agora um exemplo do comando switch:

#include

int main ()

{

int num;

printf ("Digite um numero: ");

scanf ("%d",&num);

switch (num)

{

case 9:

printf ("\n\nO numero e igual a 9.\n");

break;

case 10:

printf ("\n\nO numero e igual a 10.\n");

27

break;

case 11:

printf ("\n\nO numero e igual a 11.\n");

break;

default:

printf ("\n\nO numero nao e nem 9 nem 10 nem 11.\n");

}

return(0);

}

AUTO AVALIAÇÃO

Veja como você está. 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.

O Comando for

for é a primeira de uma série de três estruturas para se trabalhar com loops de

repetição. As outras são while e do. As três compõem a segunda família de comandos de controle de fluxo. Podemos pensar nesta família como sendo a das estruturas de repetição controlada. Como já foi dito, o loop for é usado para repetir um comando, ou bloco de comandos, diversas vezes, de maneira que se possa ter um bom controle sobre o loop. Sua forma geral é:for (inicialização;condição;incremento) declaração; O melhor modo de se entender o loop for é ver como ele funciona "por dentro". O loop for é equivalente a se fazer o seguinte:

inicialização;

if (condição)

{

declaração;

incremento;

"Volte para o comando if"

}

Podemos ver, então, que o for executa a inicialização incondicionalmente e testa a

condição. Se a condição for falsa ele não faz mais nada. Se a condição for verdadeira ele executa a declaração, faz o incremento e volta a testar a condição. Ele fica repetindo estas operações até que a condição seja falsa. Um ponto importante é que podemos omitir qualquer um dos elementos do for, isto é, se não quisermos uma inicialização poderemos omiti-la.

Abaixo vemos um programa que coloca os primeiros 100 números inteiros na tela:

#include

int main ()

{

int count;

for (count=1; count<=100; count++) printf ("%d ",count);

return(0);

}

28

Note que, no exemplo acima, há uma diferença em relação ao exemplo anterior. O

incremento da variável count é feito usando o operador de incremento que nós agora já conhecemos. Esta é a forma usual de se fazer o incremento (ou decremento) em um loop for.

O for na linguagem C é bastante flexível. Temos acesso à inicialização, à condição e ao incremento. Qualquer uma destas partes do for pode ser uma expressão qualquer do C, desde que ela seja válida. Isto nos permite fazer o que quisermos com o comando. As três formas do for abaixo são válidas:

for ( count = 1; count <>

for (count = 1; count <>

for (count = 1; count <>

etc ...

Preste atenção ao último exemplo: o incremento está sendo feito de dois em dois. Além disto, no teste está sendo utilizada uma função (BusqueNumeroDeElementos() ) que retorna um valor que está sendo comparado com count.

O loop infinito

O loop infinito tem a forma

for (inicialização; ;incremento) declaração;

Este loop chama-se loop infinito porque será executado para sempre (não existindo a condição, ela será sempre considerada verdadeira), a não ser que ele seja interrompido. Para interromper um loop como este usamos o comando break. O comando break vai quebrar o loop infinito e o programa continuará sua execução normalmente. Como exemplo vamos ver um programa que faz a leitura de uma tecla e sua impressão na tela, até que o usuario aperte uma tecla sinalizadora de final (um FLAG). O nosso FLAG será a letra ’X’.

#include

#include

int main ()

{

int Count;

char ch;

for (Count=1;;Count++)

{

ch = getch();

if (ch == ’X’) break;

printf("\nLetra: %c",ch);

}

return(0);

}

O loop sem conteúdo

Loop sem conteúdo é aquele no qual se omite a declaração. Sua forma geral é (atenção ao ponto e vírgula!): for (inicialização;condição;incremento); Uma das aplicações desta estrutura é gerar tempos de espera. O programa

#include

int main ()

{

long int i;

printf("\a"); /* Imprime o caracter de alerta (um beep) */

for (i=0; i<10000000;>

printf("\a"); /* Imprime outro caracter de alerta */

29

return(0);

}

faz isto.

AUTO AVALIAÇÃO

Veja como você está. Faça um programa que inverta uma string: leia a string com gets e armazene-a invertida em outra string. Use o comando for para varrer a string até o seu final.

O Comando while

O comando while tem a seguinte forma geral: while (condição) declaração; Assim como fizemos para o comando for, vamos tentar mostrar como o while funciona fazendo uma analogia. Então o while seria equivalente a:

if (condição)

{

declaração;

"Volte para o comando if"

}

Podemos ver que a estrutura while testa uma condição. Se esta for verdadeira a

declaração é executada e faz-se o teste novamente, e assim por diante. Assim como no caso do for, podemos fazer um loop infinito. Para tanto basta colocar uma expressão eternamente verdadeira na condição. Pode-se também omitir a declaração e fazer um loop sem conteúdo.

Vamos ver um exemplo do uso do while. O programa abaixo é executado enquanto i for menor que 100. Veja que ele seria implementado mais naturalmente com um for ...

#include

int main ()

{

int i = 0;

while ( i <>

{

printf(" %d", i);

i++;

}

return(0);

}

O programa abaixo espera o usuário digitar a tecla ’q’ e só depois finaliza:

#include

int main ()

{

char Ch;

Ch=’\0’;

while (Ch!=’q’)

{

Ch = getch();

}

return(0);

}

30

AUTO AVALIAÇÃO

Veja como você está:

Refaça o programa da página anterior. Use o comando while para fechar o loop.

O Comando do-while

A terceira estrutura de repetição que veremos é o do-while de forma geral:

do

{

declaração;

} while (condição);

Mesmo que a declaração seja apenas um comando é uma boa prática deixar as chaves. O ponto-e- vírgula final é obrigatório. Vamos, como anteriormente, ver o funcionamento da estrutura do-while "por dentro": declaração; if (condição) "Volta para a declaração" Vemos pela análise do bloco acima que a estrutura do-while executa a declaração, testa a condição e, se esta for verdadeira, volta para a declaração. A grande novidade no comando dowhile é que ele, ao contrário do for e do while, garante que a declaração será executada pelo menos uma vez.

Um dos usos da extrutura do-while é em menus, nos quais você quer garantir que o valor digitado pelo usuário seja válido, conforme apresentado abaixo:

#include

int main ()

{

int i;

do

{

printf ("\n\nEscolha a fruta pelo numero:\n\n");

printf ("\t(1)...Mamao\n");

printf ("\t(2)...Abacaxi\n");

printf ("\t(3)...Laranja\n\n");

scanf("%d", &i);

} while ((i<1)||(i>3));

switch (i)

{

case 1:

printf ("\t\tVoce escolheu Mamao.\n");

break;

case 2:

printf ("\t\tVoce escolheu Abacaxi.\n");

break;

case 3:

printf ("\t\tVoce escolheu Laranja.\n");

break;

}

return(0);

}

31

AUTO AVALIAÇÃO

Veja como você está.

Refaça o exercício da página 26 utilizando o laço do-while para controlar o fluxo.

O Comando break

Nós já vimos dois usos para o comando break: interrompendo os comandos switch e

for. Na verdade, estes são os dois usos do comando break: ele pode quebrar a execução de um comando (como no caso do switch) ou interromper a execução de qualquer loop (como no caso do for, do while ou do do while). O break faz com que a execução do programa continue na primeira linha seguinte ao loop ou bloco que está sendo interrompido. Observe que um break causará uma saída somente do laço mais interno. Por exemplo:

for(t=0; t<100;>

{

count=1;

for(;;)

{

printf("%d", count);

count++;

if(count==10) break;

}

}

O código acima imprimirá os números de 1 a 10 cem vezes na tela. Toda vez que o break é encontrado, o controle é devolvido para o laço for externo.

Outra observação é o fato que um break usado dentro de uma declaração switch afetará somente os dados relacionados com o switch e nao qualquer outro laço em que o switch estiver.

O Comando continue

O comando continue pode ser visto como sendo o oposto do break. Ele só funciona

dentro de um loop. Quando o comando continue é encontrado, o loop pula para a próxima iteração, sem o abandono do loop, ao contrário do que acontecia no comando break. O programa abaixo exemplifica o uso do continue:

#include

int main()

{

int opcao;

while (opcao != 5)

{

printf("\n\n Escolha uma opcao entre 1 e 5: ");

scanf("%d", &opcao);

if ((opcao > 5)||(opcao <1))>

inicio do loop */

switch (opcao)

{

case 1:

printf("\n --> Primeira opcao..");

break;

case 2:

printf("\n --> Segunda opcao..");

break;

case 3:

32

printf("\n --> Terceira opcao..");

break;

case 4:

printf("\n --> Quarta opcao..");

break;

case 5:

printf("\n --> Abandonando..");

break;

}

}

return(0);

}

O programa acima ilustra uma aplicação simples para o continue. Ele recebe uma opção do usuario. Se esta opção for inválida, o continue faz com que o fluxo seja desviado de volta ao início do loop. Caso a opção escolhida seja válida o programa segue normalmente.

O Comando goto

Vamos mencionar o goto apenas para que você saiba que ele existe. O goto é o último comando de controle de fluxo. Ele pertence a uma classe à parte: a dos comandos de salto incondicional. O goto realiza um salto para um local especificado. Este local é determinado por um rótulo. Um rótulo, na linguagem C, é uma marca no programa. Você dá o nome que quiser a esta marca. Podemos tentar escrever uma forma geral:

nome_do_rótulo:

...

goto nome_do_rótulo;

....

Devemos declarar o nome do rótulo na posição para a qual vamos dar o salto seguido de :. O goto pode saltar para um rótulo que esteja mais à frente ou para trás no programa. Uma observação importante é que o rótulo e o goto devem estar dentro da mesma função. Como exemplo do uso do goto vamos reescrever o equivalente ao comando for apresentado na seção equivalente ao mesmo:

inicialização;

início_do_loop:

if (condição)

{

declaração;

incremento;

goto início_do_loop;

}

O comando goto deve ser utilizado com parcimônia, pois o abuso no seu uso tende a tornar o código confuso. O goto não é um comando necessário, podendo sempre ser substituído por outras estruturas de controle. Recomendamos que o goto nunca seja usado. Existem algumas situações muito específicas onde o comando goto pode tornar um código mais fácil de se entender se ele for bem empregado. Um caso em que ele pode ser útil é quando temos vários loops e ifs aninhados e se queira, por algum motivo, sair destes loops e ifs todos de uma vez. Neste caso um goto resolve o problema mais elegantemente que vários breaks, sem contar que os breaks exigiriam muito mais testes. Ou seja, neste caso o goto é mais elegante e mais rápido.

O exemplo da página anterior pode ser reescrito usando-se o goto:

#include

int main()

{

int opcao;

while (opcao != 5)

{

REFAZ: printf("\n\n Escolha uma opcao entre 1 e 5: ");

scanf("%d", &opcao);

if ((opcao > 5)||(opcao <1))>

ao rotulo REFAZ */

switch (opcao)

{

case 1:

printf("\n --> Primeira opcao..");

break;

case 2:

printf("\n --> Segunda opcao..");

break;

case 3:

printf("\n --> Terceira opcao..");

break;

case 4:

printf("\n --> Quarta opção..");

break;

case 5:

printf("\n --> Abandonando..");

break;

}

}

return(0);

}

AUTO AVALIAÇÃO

Veja como você está.

Escreva um programa que peça três inteiros, correspondentes a dia , mês e ano. Peça os números até conseguir valores que estejam na faixa correta (dias entre 1 e 31, mês entre 1 e 12 e ano entre 1900 e 2100). Verifique se o mês e o número de dias batem (incluindo verificação de anos bissextos). Se estiver tudo certo imprima o número que aquele dia corresponde no ano. Comente seu programa.

PS: Um ano é bissexto se for divisível por 4 e não for divisível por 100, exceto para os anos divisíveis por 400, que também são bissextos.

34

Comentários