Curso de C - 7. Estruturas de Repetição
(2743 total de palavras neste texto) (4230 vizualização(ões)) 
Curso de C - 7. Estruturas de Repetição
Suponhamos que você queira fazer um programa que lê 100 números do teclado e para cada número verifique se é múltiplo de 3, imprimindo a
resposta para cada um. Como você escreveria este programa?
Seria assim?
#include <stdio.h>
main()
{
int num;
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
etc .....................
}
Como você pode ver, não é uma técnica nada viável, pois temos que repetir a mesma sequência de comandos várias vezes. Mas não se
desespere... Nesta aula veremos que C, assim como outras linguagens, tem vários comandos que nos ajudam em tarefas repetitivas como esta.
Estes comandos são conhecidos como estruturas de repetição ou laços. Veremos também algumas técnicas básicas que nos ajudarão a criar
programas iterativos.
Para começar, vamos estudar o laço for.
7.1. O laço for
O laço for é uma estrutura de repetição controlada por variável, onde devemos saber de antemão a quantidade de iterações. O laço
for tem a seguinte forma geral:
for (inicialização; teste condicional; incremento ou decremento)
{
comandos;
}
OU
for (inicialização; teste condicional; incremento ou decremento)
comando único;
Veja este exemplo:
#include <stdio.h>
main()
{
int i, num;
for (i=0; i<100; i++)
{
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if ((num %3) == 0)
printf("é múltiplo de 3\n");
else
printf("não é múltiplo de 3\n");
}
return 0;
}
Veja só o nosso exemplo revisitado, com o uso de for.
Como você pode ver, o laço for contém 3 expressões entre parênteses, que controlarão o modo que o nosso laço trabalhará:
- Na expressão inicialização, atribuímos valor inicial à variável de controle. No exemplo acima, inicializamos i com 0.
- Em teste condicional, temos uma expressão relacional/lógica que definirá o critério de parada do nosso laço. No nosso //detector de
múltiplos de 3//, o laço for ficará repetindo o bloco de comandos enquanto a variável i for menor que 100. Quando i tiver o valor
100, o laço não executará mais os comandos do bloco de comandos, e o programa continuará sua execução (no nosso caso, executará return 0
e depois terminará.).
- A expressão incremento ou decremento deve dizer para o laço for como a variável vai "andar", se é de 1 em 1, de 2 em 2, de 10 em
10, etc. No nosso programa acima, a expressão i++ faz a variável i ser incrementada de 1 em 1.
Trocando em miúdos, no laço for do nosso programa, a variável i será inicializada com 1, andará de 1 em 1, e quando chegar a 100 sairá do
laço.
Viu como é fácil?
7.2. Flexibilidade do laço for
Mas não é só isso... As 3 espressões do laço podem conter várias instruções separadas por vírgula. Vamos ver um exemplo:
#include <stdio.h>
main()
{
int i, j, num;
for (i=0, j=0; i+j <100; i++, j++)
printf("%d\n", i+j);
return 0;
}
Veja que na inicialização, temos duas variáveis sendo atribuídas com 0: i e j, separadas por vírgula. Na parte de incremento, i e j
são incrementadas com 1, também separadas por vírgula. Isto torna o laço for bastante flexível, onde o limite é a sua criatividade...
Mas cuidado para não construir laços for monstros, com expressões enormes e de difícil compreensão...
Além disso, podemos omitir qualquer uma das expressões do laço for. Por exemplo:
for ( ; i<100; i++)
{
comandos;
}
Nesse caso, não haverá a inicialização.
Outro exemplo:
for (i=0; i<100; )
{
comandos;
}
Aqui, não há o incremento... Ele pode ser feito dentro do bloco de código do laço.
Em alguns casos, podemos usar o laço for como um laço infinito. Veja como:
for ( ; ; )
{
comandos;
}
Este é um laço for infinito. Sua execução nunca terminará, a menos que haja um return ou um break dentro dele.
Ou então, você pode usar o laço for sem o bloco de código. Por exemplo, em um compilador, que lê os caracteres do código fonte e deseja
ignorar os espaços, podemos fazer assim:
for ( ; *str == ' '; str++);
Elegante, não? Ou digamos que você queira ignorar as quebras de linha:
for ( ; *str == '\n'; str++);
Ou as tabulações:
for ( ; *str == '\t'; str++);
Ou então, chutando o balde e colocando tudo em um só for:
for ( ; ((*str == ' ') || (*str == '\n') || (*str == '\t')); str++);
Diferente de outras linguagens, C permite uma grande flexibilidade do laço for, o que o torna uma ferramenta bastante poderosa para o
programador.
7.3. O laço while
O laço while é uma estrutura de repetição que só repetirá o bloco de código se a condição, entre parênteses, for verdadeira. Esta
condição pode ser qualquer expressão, onde falso é 0 e verdadeiro é diferente de 0. Se a condição for falsa logo no início do while, o
laço não será executado.
Forma geral:
while (condição)
{
comandos;
}
OU
while (condição)
comando único;
Quando o programa chega no while, ele verifica a condição entre parênteses. Se for verdadeira, ele executa o bloco de códigos. Quando
termina de executar os comandos do bloco de código, ele volta para o while novamente, testa a condição de novo e, se for verdadeira,
executa o bloco de código novamente. Faz isso até a condição entre parênteses ser falsa, momento em que o programa continua a execução
normalmente, depois do while.
Vamos ver alguns exemplos:
#include <stdio.h>
#include <ctype.h>
main()
{
int cont=0, i= 0;
char ch;
while (i < 10)
{
printf("Digite um caractere: ");
scanf("%c", &ch);
getchar();
if (isdigit(ch))
cont++;
i++;
}
printf("Você digitou %d caracteres numéricos\n", cont);
return 0;
}
Aqui, o programa utiliza a função isdigit(), presente no arquivo de cabecalho ctype.h. O ctype.h contém funções para teste e
conversão de caracteres.
Neste programa, o while executará 10 vezes, só terminando quando i chegar ao valor 10. Aqui vemos uma técnica que usamos muito em várias
aplicações: um contador. A variável cont é inicializada com zero; quando, dentro do while, o cara digitar um caractere numérico,
esta variável é incrementada de 1. Ao final da execução, ela terá o número exato de caracteres numéricos que foram digitados.
Outro exemplo:
#include <stdio.h>
main()
{
int i=0, num, res= 0;
while (i < 5)
{
printf("Digite um número: ");
scanf("%d", &num);
res= res+num;
i++;
}
printf("Somatória: %d\n", res);
return 0;
}
Neste, outra técnica bastante utilizada: a somatória de um conjunto de números.
Funciona assim: ao entrar no while, o cara digita um número, que será armazenado na variável num. Esse número é somado com o valor da
variável res (que na primeira iteração é 0) e armazenado em res. Na próxima iteração, o valor da variável res (a soma da iteração passada) é
somada com num e armazenada em res novamente, assim sucessivamente até acabar o laço. Ao final do laço, o que temos em res é a somatória de
todos os números digitados.
Mais uma técnica: imagine que você queira somar os números digitados até que seja digitado um número maior que 100. Você pode criar uma
variável que muda de valor quando essa condição for satisfeita. É o que chamamos de flag. Exemplo:
int num;
int flag= 0;
while (flag == 0)
{
printf("Digite um número: ");
scanf("%d", &num);
getchar();
if (num > 100)
flag= 1; /* flag muda de valor (indica que loop deve parar) */
}
Lembrando que estas técnicas podem ser exploradas em qualquer tipo de laço, desde que sejam adaptadas para cada situação.
Assim como for, podemos fazer um laço infinito com o while também. Basta fazer o seguinte:
while(1) /* 1 é verdadeiro em C */
{
comandos;
}
É claro que em comandos deve haver alguma forma de sair do while, como um break, um return, um exit(), etc.
OBS: Evite usar comandos como break ou exit() dentro de laços, pois é uma prática pouco elegante. Só use quando não houver outro
jeito.
7.4. O laço do-while
Diferente do while, que testa a condição antes de executar o seu bloco de código, o do-while primeiro executa o seu bloco de código
para depois testar a condição. Ele é útil quando temos que executar no mínimo UMA VEZ o bloco de código do laço.
Forma geral:
do
{
comandos;
} while(condição);
No caso de haver um comando único, não é necessário delimitar com chaves, mas é recomendável, para não haver confusão e para deixar o código
mais legível.
Vamos para os exemplos:
#include <stdio.h>
main()
{
int num;
do
{
scanf("%d", &num);
getchar();
} while(num < 50);
return 0;
}
Neste programa, que não faz nada de útil, o bloco de código deve ser executado pelo menos uma vez, já que dependemos do valor da variável num
para processar a condição, no final do laço. Aqui, o programa só sai do laço quando for digitado algum número maior ou igual a 50.
Agora um exemplo mais prático:
#include <stdio.h>
main()
{
int opt;
do
{
do
{
printf("**** Menu ****\n");
printf("1) Cadastrar\n");
printf("2) Buscar\n");
printf("3) Exibir Relatório\n");
printf("4) Sair\n");
printf("Digite sua opção: ");
scanf("%d", &opt);
getchar();
} while ((opt < 1) || (opt > 4)); /* o cara fica preso até digitar um número válido */
switch(opt)
{
case 1:
cadastra();
break;
case 2:
busca();
break;
case 3:
relat();
break;
}
} while (opt != 4); /* laço principal, só sai quando opt for igual a 4 */
return 0;
}
Como você pode ver, temos dois do-while. O mais externo e principal fica vigiando se o cara digitou 4 (se quer sair). Caso contrário,
volta e executa tudo novamente.
O laço mais interno é uma técnica usada quando o usuário tem um menu, e tem que digitar uma opção para definir para que lado o programa vai.
No nosso caso, se o espertinho do usuário digitar algum número maior que 4 ou menor que 1 (inválidos), o laço volta e joga tudo de novo na
tela, esperando o "esperto" do usuário escolher a opção certa.
As funções cadastra(), busca() e relat() são fictícias e só serviram para ilustrar a situação.
Você viu que neste exemplo temos dois laços aninhados. Agora vamos falar um pouco sobre eles.
7.5. Laços aninhados
Laços aninhados não são laços dentro de ninhos... :) São laços dentro de laços (isso vai dar nó...).
Exemplo de laços for aninhados:
for (i=1; i<=10; i++)
{
for (j=1; j<=10; j++)
{
printf("%d X %d = %d\n", i, j, i*j);
}
printf("\n\n");
ch= getchar();
}
Vejam que poder: com apenas 9 linhas imprimimos as tabuadas de 1 a 10!!
Exemplo de laços while aninhados:
while(i <= 10)
{
while(j <= 10)
{
printf("%d x %d = %d\n", i, j, i*j);
j++;
}
printf("\n\n");
ch= getchar();
i++;
}
O mesmo exemplo das tabuadas usando while.
A lógica dos laços aninhados é a seguinte:
- O laço mais externo entra em execução;
- São executados os comandos do bloco até que o programa encontra o laço mais interno;
- O laço mais interno também entra em execução;
- Agora o laço mais interno fará todas as iterações possíveis, até acabar;
- Acabando a execução do laço mais interno, o laço mais externo continua executando seu bloco de código;
- Quando o último código do bloco de código é executado, o laço mais externo volta, testa e entra em execução novamente;
- Aí encontra o laço mais interno novamente, que entra em execução até terminar;
- E assim vai, até a condição de parada do laço mais externo ser satisfeita (the end).
Podemos ter vários laços aninhados, não somente 2. Podemos também ter laços for dentro de while ou do-while, e etc... Só tem uma
coisa: quanto mais laços aninhados, mais lento será seu programa.
7.6. Comandos de desvio
C possui 4 comandos de desvio incondicional: return, goto, brek e continue.
O comando return é um velho conhecido nosso. Ele retorna de uma função, voltando para o local de onde a função foi chamada. Na função
main(), ele faz encerrar o programa. Se estiver acompanhado de uma expressão, ele devolve o valor de uma expressão. Se estiver sozinho, é
retornado lixo (alguns compiladores retornam 0 quando return está sozinho, mas não espere isso). Veremos mais sua utilização na aula sobre
funções.
Forma geral:
return expressão;
O comando goto é um comando escomungado pelos programadores, que evitam a sua utilização. Na prática, não existe nenhum caso que precise
de goto, podendo ser usadas quaisquer estruturas para controle de fluxo (for, while, if, switch, etc...). Mas em algumas situações, se o
goto for bem empregado, há um ganho de performance. Podemos ver que os programadores do kernel do Linux usam o goto em algumas
construções, para obter melhor desempenho.
Forma geral:
rotulo:
comandos;
.
.
.
goto rotulo;
O goto salta de onde o programa está para o rótulo, executando os comandos daí em diante.
De qualquer forma, evite usar goto.
O comando break pode ser usado no comando switch (já vimos exemplos) ou em laços. Nos dois casos, ele causa a imediata interrupção na
execução, saltando para o próximo código após o switch ou o laço.
O comando continue é um pouco parecido com o break. Sua única diferença é que, ao invés de encerrar o laço e continuar do próximo
comando em diante, ele força o laço ir imediatamente para a próxima iteração.
Além destes comandos, existe a função exit() que provoca uma terminação imediata do programa. Ela possui apenas um argumento, que é o
código de retorno para o sistema operacional (como já sabemos, retornar 0 para o sistema operacional indica sucesso, e outros valores vários
tipos de erros). Geralmente a função exit() é usada se uma condição obrigatória para a execução do programa não acontecer.
Por esta semana é só... Na próxima aula falaremos sobre Matrizes e Strings, com exemplos e exercícios. Até lá!
Exercícios
1) Faça um programa que imprima o maior e o menor número de uma sequência de 10 números lidos do teclado.
2) Faça um programa que leia as seguintes informações de 50 vacas: seu nome, seu peso, sua idade e a quantidade de litros de leite que cada
uma dá por dia. Imprima o nome da vaca mais velha e da vaca que mais produz leite.
3) Faça um programa que leia um número e calcule o seu fatorial, lembrando que o fatorial de um número é: número * fatorial(número-1). Por
exemplo, fatorial de 5: 5*4*3*2*1= 120; fatorial de 1: 1; fatorial de 0: 1.
4) Faça um programa que dados leia 10 caracteres e conte quantos caracteres 'a' aparecem (somente minúsculo).
5) Faça um programa que imprima a sequência de Fibonacci: 0 1 1 2 3 5 8 13 21 31 ... Como você pode ver, cada número é a soma dos dois
números anteriores. O programa primeiro vai ler um número, que será a quantidade de iterações do laço.
Powered by txt2tags |