Sie sind auf Seite 1von 28

Estruturas de Repetio

Introduo
No captulo anterior verificamos que a execuo seqencial dos comandos da funo main
nos limita a programao de algoritmos muito simples. Passamos, ento, a dedicar nossa
ateno ao estudo de recursos de programao mais elaborados, tais como as estruturas
condicionais if...else e switch, as quais permitem executar parte do cdigo do
programa somente sob determinadas condies.
Agora, estudaremos as estruturas de repetio, que permitem executar mais de uma vez um
mesmo trecho de cdigo. Trata-se de uma forma de executar blocos de comandos somente
sob determinadas condies, mas com a opo de repetir o mesmo bloco quantas vezes for
necessrio. As estruturas de repetio so teis, por exemplo, para repetir uma srie de
operaes semelhantes que so executadas para todos os elementos de uma lista ou de uma
tabela de dados, ou simplesmente para repetir um mesmo processamento at que uma certa
condio seja satisfeita.

Estrutura de repetio while


O while a estrutura de repetio mais simples. Ele repete a execuo de um bloco de
sentenas enquanto uma condio permanecer verdadeira. Na primeira vez que a condio
se tornar falsa, o while no repetir a execuo do bloco, mas continuar a execuo com a
sentena ou comando que vem logo aps o bloco do while, na seqncia do programa.

incio

0
expresso
1 Sintaxe:

sentena(s) while (expresso) {


sentena;
sentena;
...
}
fim
Figura 1 Fluxo de controle da Figura 2 Sintaxe da estrutura de repetio
estrutura de repetio while while

A Figura 12 ilustra a sintaxe da estrutura condicional while em C. O fluxo de execuo


desta estrutura est ilustrado na Figura 21. A expresso uma condio que controla o
while. Primeiro, o programa avalia a expresso. Ela utiliza os mesmos operadores de
relacionais e lgicos estudados quando tratamos das as estruturas condicionais. Caso o
resultado da expresso seja no nulo (verdadeiro), ento todo o bloco de sentenas ser
executado. Em seguida, o programa volta a avaliar a expresso e o processo se repete at
que a expresso retiorne como zero (falso). A expresso sempre avaliada antes da
deciso de se executar o bloco de sentenas novamente.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 1


Observao: A expresso dever ser colocada, obrigatoriamente, entre parnteses.
A repetio do while controlada por uma condio que verifica alguma caracterstica do
programa (por exemplo, valores de variveis). Para o uso correto do while, o bloco de
sentenas precisa modificar o estado do sistema de forma a afetar justamente as
caractersticas testadas na expresso. Se isto no ocorrer, ento o while executar
eternamente.
Observao: O programa sempre executa o bloco de sentenas completo. Se neste tempo a
condio se tornar falsa, o programa s verificar este fato quando avaliar novamente a
expresso, preparando para uma nova repetio.
Exemplo
Para imprimir os nmeros de 1 at 10:
int numero = 1;
while (numero <= 10) {
printf("%d\n" , numero);
numero = numero + 1;
}
Consulte: EstruturasRepeticao\while01\while01.vcproj
Declaramos uma varivel numero que controlar o while. Ela armazena o valor a
ser impresso. A expresso do while verifica se o nmero est dentro do limite
desejado (menor ou igual a 10).
No incio, o valor da varivel numero 1 e portanto a expresso do while
satisfeita. O bloco de expresses executado, imprimindo o valor de numero e
aumentando seu valor em uma unidade. Note que isto afeta a condio que controla
o bloco.
Nas prximas repeties, a expresso ser verdadeira para os valores de numero 2,
3, 4, ... 9 e 10. Quando numero armazenar o valor 11, a expresso que controla o
while ser falsa. Nesse ponto, o while termina, encerrando as repeties.
No final da execuo, o valor da varivel numero ser 11, que foi justamente o valor
que tornou a expresso falsa, impedindo uma nova execuo do bloco while.
Estrutura de repetio while em uma linha
Quando o bloco da estrutura while contm
Sintaxe: apenas uma nica sentena, pode-se omitir as
while (expresso)
chaves que delimitam o bloco, como na Figura
sentena; 3. No entanto, essa forma no delimita
claramente o cdigo do while do restante do
Figura 3 Sintaxe abreviada da estrutura
programa. Por ser mais confusa, evite a forma
condicional while
abreviada!
Exemplo
O prximo exemplo um uso tpico do while para realizar uma operao para um
intervalo de nmeros. Este programa imprime todos os divisores de um nmero inteiro
positivo. Para o nmero n dado, o programa verifica se cada nmero de 1 at n ou no um
divisor de n.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 2


Cdigo Fonte
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int numero;
int divisor;
int resto;

printf("Digite o numero: ");


scanf("%d", &numero);

divisor = 1;
while (divisor <= numero) {
resto = numero % divisor;
if (resto == 0) {
printf("Divisor encontrado: %d \n", divisor);
}
divisor = divisor + 1;
}

return 0;
}
Consulte: EstruturasRepeticao\Divisores01\Divisores01.vcproj

Descrio passo a passo


int numero;
int divisor;
int resto;
Declara-se trs variveis inteiras. A varivel numero armazenar o valor digitado
pelo usurio, para o qual descobriremos os divisores. A varivel divisor um
contador que conter o prximo nmero que ser testado como divisor. E resto
uma varivel que armazenar temporariamente o resto da diviso de numero por
divisor.

printf("Digite o numero: ");


scanf("%d", &numero);
As duas linhas pedem ao usurio para digitar o nmero para o qual deseja descobrir
os divisores.

divisor = 1;
while (divisor <= numero) {
...
divisor = divisor + 1;
}
Este bloco corresponde estrutura de repetio. Por motivos de simplicidade, o
cdigo executado dentro do bloco foi omitido com objetivo de entender sua lgica
de funcionamento.
A repetio controlada pelo valor da varivel divisor. Isto quer dizer que o bloco
precisa modificar o valor da varivel divisor para, em algum momento, parar as
repeties.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 3


No incio, antes de executar a repetio, a varivel divisor iniciada com um
valor vlido (1), que o primeiro divisor possvel. Em cada execuo da repetio, a
varivel divisor modificada, somando-se a ela uma unidade. Aps certo nmero
de repeties, valor da varivel divisor ultrapassar o valor de numero e assim
terminar a repetio.

resto = numero % divisor;


if (resto == 0) {
printf("Divisor encontrado: %d \n", divisor);
}
O cdigo executado dentro da repetio calcula o resto da diviso. Caso ele seja
zero, significa que encontramos um divisor. Tal divisor impresso.
Primeiro exemplo de execuo:
Digite o numero: 100
Divisor encontrado: 1
Divisor encontrado: 2
Divisor encontrado: 4
Divisor encontrado: 5
Divisor encontrado: 10
Divisor encontrado: 20
Divisor encontrado: 25
Divisor encontrado: 50
Divisor encontrado: 100
Segundo exemplo de execuo:
Digite o numero: 19
Divisor encontrado: 1
Divisor encontrado: 19

O que ocorre se o nmero informado for zero? E se for negativo?

Exemplo:
O prximo exemplo um uso tpico do while para realizar uma operao at que uma
condio seja satisfeita. Esta condio no depende de uma varivel contadora, tal como no
exemplo anterior. Assim, no possvel prever facilmente o nmero de repeties. O
programa calcula o mximo divisor comum (MDC) entre dois nmeros positivos.

Cdigo Fonte
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int numeroA;
int numeroB;
int resto;

printf("Digite dois numeros (ordem crescente): ");


scanf("%d %d", &numeroA, &numeroB);

while (numeroA > 0) {


resto = numeroB % numeroA;

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 4


printf("numeroB = %d; numeroA = %d; ", numeroB, numeroA);
printf("resto = %d\n", resto);
numeroB = numeroA;
numeroA = resto;
}

printf("MDC: %d", numeroB);

return 0;
}
Consulte: EstruturasRepeticao\mdc01\mdc01.vcproj

Descrio passo a passo


O programa segue o mesmo algoritmo apresentado na introduo do curso,
realizando divises sucessivas at achegar no MDC.
int numeroA;
int numeroB;
int resto;
So declaradas trs variveis. As primeiras duas armazenam o valor digitado pelo
usurio e, no decorrer do algoritmo, esses valores convergem para o MDC. A
varivel resto apenas para armazenamento temporrio dentro da repetio.

while (numeroA > 0) {


resto = numeroB % numeroA;
...
numeroB = numeroA;
numeroA = resto;
}
A cada repetio, o algoritmo divide sucessivamente um valor pelo outro e guarda o
resto. No final do bloco de repetio, a varivel numeroA armazena o resto da
diviso, e a varivel numeroB armazena o ltimo valor da varivel numeroA.
A repetio finalizada quando o resto for nulo, ou seja, quando a varivel
numeroA armazenar zero.
Exemplo de execuo
Digite dois numeros (ordem crescente): 30 36
numeroB = 36; numeroA = 30; resto = 6
numeroB = 30; numeroA = 6; resto = 0
MDC: 6

Estrutura de repetio do...while


Esta estrutura tem um comportamento muito semelhante ao while, com uma diferena
crucial: a condio verificada aps executar o bloco de instrues correspondente.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 5


incio

sentena(s)
Sintaxe:
1 do {
expresso sentena;
sentena;
0 ...
} while (expresso);
fim
Figura 4 Fluxo de controle da Figura 5 Sintaxe da estrutura de repetio
estrutura de repetio do...while do...while

A Figura 45 ilustra a sintaxe da estrutura condicional do...while em C. O fluxo de


execuo desta estrutura est ilustrado na Figura 54. A expresso uma condio que
controla o do...while.
Executa-se o bloco de sentenas, independentemente da condio. Somente ento a
expresso avaliada. Caso ela seja no nula (verdadeira), ento todo o bloco de sentenas
ser executado novamente. Este processo se repete at que a expresso resulte em zero
(falso). A expresso sempre avaliada depois da execuo do bloco de sentenas.
Observao 1: A condio dever ser colocada, obrigatoriamente, entre parnteses!
Observao 2: No esquecer do ponto-e-vrgula aps a expresso!
A diferenas entre a estrutura while e do...while sutil. Ela est no momento quando a
condio de repetio verificada: antes ou depois de executar o bloco de sentenas. A
escolha depender do bom senso do programador, que optar pela estrutura que deixar o
algoritmo mais simples e legvel.
Exemplo
Para imprimir os nmeros de 1 at 10:
int numero = 1;
do {
printf("%d\n" , numero);
numero = numero + 1;
} while (numero <= 10);
Consulte: EstruturasRepeticao\dowhile01\dowhile01.vcproj

Declaramos uma varivel numero que controlar o do...while. Ela armazena o


prximo valor a ser impresso. A expresso do do...while verifica se o nmero
est dentro do limite desejado (menor ou igual a 10).
O bloco de sentenas executado, imprimindo o valor de numero e aumentado seu
valor em uma unidade. Aps executar o bloco, a expresso verifica se a varivel
numero continua dentro do limite permitido. Caso afirmativo, o bloco executado
novamente. Assim, o bloco executado quando numero armazenar 1, 2, 3, ..., 9 e
10.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 6


No final da execuo, o valor da varivel numero ser 11, que foi justamente o valor
que tornou a expresso falsa, impedindo uma nova execuo do bloco do...while.
Estrutura de repetio do...while em uma linha
Quando o bloco da estrutura
Sintaxe: do...while contm apenas uma
nica sentena, pode-se omitir as
do sentena while (expresso); chaves que delimitam o bloco como na
Figura 6. No entanto, essa forma no
Figura 6 Sintaxe abreviada da estrutura delimita claramente o cdigo do
condicional do...while restante do programa. Por ser mais
confusa, evite a forma abreviada!
Exemplo
O programa MDC apresentado para a estrutura de repetio while pode ser re-escrito com
um do...while. Este programa calcula o mximo divisor comum (MDC) entre dois
nmeros positivos.
Cdigo Fonte
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int numeroA;
int numeroB;
int resto;

printf("Digite dois numeros (ordem crescente): ");


scanf("%d %d", &numeroA, &numeroB);

do {
resto = numeroB % numeroA;
printf("numeroB = %d; numeroA = %d; ", numeroB, numeroA);
printf("resto = %d\n", resto);
numeroB = numeroA;
numeroA = resto;
} while (numeroA > 0);
// ou while (resto > 0);

printf("MDC: %d", numeroB);

return 0;
}
Consulte: EstruturasRepeticao\mdc02\mdc02.vcproj

Descrio passo a passo


O programa segue a mesma lgica do anterior. A descrio a seguir foca somente
nas diferenas entre as estruturas de repetio.
do {
resto = numeroB % numeroA;
...
numeroB = numeroA;
numeroA = resto;
} while (numeroA > 0);

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 7


Cada repetio divide um valor pelo outro e guarda o resto. Quando o resto for nulo,
o valor do MDC foi encontrado e a repetio terminada.
Exemplo de execuo
Digite dois numeros (ordem crescente): 30 36
numeroB = 36; numeroA = 30; resto = 6
numeroB = 30; numeroA = 6; resto = 0
MDC: 6

Operadores de incremento
Talvez voc tenha observado que, freqentemente, as estruturas de repetio utilizam
variveis para controlar o nmero de repeties. No exemplo de imprimir nmeros de 1 at
10, no final de cada iterao temos:
numero = numero + 1;
Em C, a sentena acima significa que a varivel numero recebe um novo valor por causa do
operador de atribuio. O novo valor calculado da seguinte forma: somando-se 1 ao valor
da varivel no lado direito da atribuio. Como este tipo de atribuio muito freqente, a
linguagem C oferece atalhos que podem ser prticos em estruturas de repetio:
Para: Use o atalho: Forma original:
Somar uma unidade ao valor ++numero; numero = numero + 1;
da varivel (retorne numero)
Subtrair uma unidade do --numero; numero = numero - 1;
valor da varivel (retorne numero)
Observao:
1. comum que programadores experientes utilizem estes operadores dentro de
expresses complexas, at mesmo dentro das prprias condies que controlam a
execuo de um while. No momento, utilizaremos estes operadores apenas em
expresses simples. prefervel criar um cdigo simples e de fcil entendimento do que
um cdigo compacto.
2. O novo valor atribudo varivel, cujo novo valor fica acrescido de uma unidade.
3. O novo valor retornado como o valor da expresso.

Exemplo
Para imprimir os nmeros de 1 at 10 com while:
int numero = 1;
while (numero <= 10) {
printf("%d\n" , numero);
++numero;
}
Consulte: EstruturasRepeticao\while02\while02.vcproj

O mesmo exemplo com do...while


int numero = 1;
do {
printf("%d\n" , numero);

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 8


++numero;
} while (numero <= 10);
Consulte: EstruturasRepeticao\dowhile02\dowhile02.vcproj

Existem comandos semelhantes aos antriores, mas que retornam os valores que estavam
armazenados nas variveis antes de se realizar as operaes de incremento ou de
decremento.

Para: Use o atalho: Forma original:


Somar um ao valor da numero++; (retorne numero)
varivel, retornando o valor numero = numero + 1;
original
Subtrair um do valor da numero--; (retorne numero)
varivel, retornando o valor numero = numero - 1;
original
Exemplo
int numero = 1, val = 10;

val = numero--;
printf("val = %d, numero = %1d\n" , val, numero);

Este trecho de cdigo imprimir:


val = 1, numero = 0
Observe que o novo valor da varivel val 1, ou seja, o valor original de numero. Esse o valor
retornado pela expresso. Porm, o novo valor que atribudo para numero 0, ou seja, o resultado
da operao de decrscimo.

Operaes aritmticas da forma


variavel = variavel op expressao
onde op um dos operadores aritmticos, tambm ocorrem com bastante freqncia.
Nesses caso, podemos escrever essas atribuies de forma simplificada como
variavel op= expressao
A tabela a seguir ilustra os casos possveis.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 9


Para: Use o atalho: Forma original:
Somar k unidades ao valor numero += k; numero = numero + k;
da varivel
Subtrair k unidades do valor numero -= k; numero = numero - k;
da varivel
Multiplicar o valor da numero *= k; numero = numero * k;
varivel por k
Dividir o valor da varivel numero /= k; numero = numero / k;
por k

Estrutura de repetio for


Na maioria do casos, algoritmos necessitam executar um bloco de sentenas por um
nmero especfico de vezes. Freqentemente, utiliza-se uma varivel para controlar o
nmero de repeties. J aprendemos como fazer isso usando o while e o do...while
(vide exemplos para imprimir nmeros de 1 at 10). Estas situaes sempre apresentam
uma varivel contadora e as quatro etapas seguintes:
Inicializao: Atribui um valor inicial varivel contadora.
Teste: Verifica uma condio antes de decidir se executar o bloco de sentenas.
Caso a condio seja falsa, interrompe as repeties.
Execuo: Executa o bloco de sentenas.
Atualizao: Atualiza a varivel contadora para o prximo valor.
Vamos ilustrar com nosso primeiro exemplo, imprimir nmeros de 1 at 10.
int numero = 1; // Inicializao
while (numero <= 10) { // Teste
printf("%d\n", numero); // Execuo
...
numero = numero + 1; // Atualizao
}

O grande nmero de situaes que requerem esta lgica justifica a prxima estrutura de
repetio. Ela apresenta, de forma compacta, as etapas de inicializao, do teste e da
atualizao.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 10


incio

inicializao

teste
0
1
Sintaxe:
sentena(s)
for (inicializao;
teste;
atualizao) {
atualizao sentena;
sentena;
...
fim }

Figura 7 Fluxo de controle da Figura 8 Sintaxe da estrutura de repetio


estrutura de repetio for for

Um for sempre est acompanhado de uma varivel contadora que armazena quantas vezes
o bloco de sentenas do for deve ser executado. Na Figura 7 obervamos que o programa
faz a inicializao, que atribui o valor inicial da varivel contadora. Em seguida avalia a
expresso, que verifica se o valor da varivel contadora est dentro do limite desejado.
Caso positivo, o bloco de sentenas executado e, em seguida, executada a atualizao,
que altera o valor da varivel contadora. O processo se repete avaliando novamente a
expresso. A sintaxe da estrutura for est na figura Figura 8.
Tipicamente, uma estrutura for ocorre como no modelo abaixo:

int contador;
for (contador = 1; contador <= 10; contador++) {
...
}

Exemplo
Para imprimir os nmeros de 1 at 10:
int numero;
for (numero = 1; numero <= 10; numero++) {
printf("%d ", numero);
}
Consulte: EstruturasRepeticao\for01\for01.vcproj
Declaramos uma varivel numero que servir como contador para o for. Ela
armazenar a contagem de repeties. O for executa o bloco contendo o comando
printf vrias vezes, variando o valor da varivel numero de 1 at 10. Observe a
forma simplificada da escrita da expresso de atualizao.
Resultado: 1 2 3 4 5 6 7 8 9 10

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 11


Para imprimir os nmeros de 1 at 20, de 2 em 2:
int numero;
for (numero = 1; numero <= 20; numero += 2) {
printf("%d ", numero);
}
Consulte: EstruturasRepeticao\for02\for02.vcproj

A diferena est na atualizao, que aumenta o valor de numero em duas unidades a


cada repetio do bloco. Observe a forma simplificada na expresso de atualizao.
Resultado: 1 3 5 7 9 11 13 15 17 19
Para imprimir os nmeros de 10 at 1:
int numero;
for (numero = 10; numero >= 1; numero--) {
printf("%d ", numero);
}
Consulte: EstruturasRepeticao\for03\for03.vcproj

Ao invs de inicializar a varivel numero com 1, ela agora inicializada com 10. A
cada repetio, a atualizao deve reduzir o valor da varivel correspodente em uma
unidade. Portanto, podemos escrever numero--. A condio deve verificar agora se
o valor de numero maior ou igual que 1.
Resultado: 10 9 8 7 6 5 4 3 2 1
Alm de condensar uma lgica recorrente de programao em poucas linhas, o for possui
outras duas vantagens importantes:
O seu cabealho agrupa todas as instrues mais importantes que controlam a
execuo do for: a inicializao, o teste e a atualizao. O programador obrigado
a declarar toda a lgica de execuo em uma nica linha e de uma s vez. Em uma
estrutura while, um erro muito comum o programador esquecer de inicializar
ou atualizar a varivel de controle.
O cabealho separa claramente as instrues de controle de repetio das instrues
de execuo. No exemplo para imprimir nmeros de 1 at 10 sem o uso do for a
varivel contadora atualizada logo aps a impresso. Em programas mais
elaborados, as instrues de atualizao tendem a ficarem escondidas ou diludas
dentro das demais instrues, tornando o programa obscuro e suscetvel a erros de
programao.
Toda a estrutura for equivalente a um while. A escolha entre uma estrutura ou outra
uma questo de gosto e estilo de programao. Use o bom senso para realizar sua escolha.
Observao: Note a ordem correta das declaraes no cabealho: inicializao, teste e
atualizao! No esquea do ponto-e-vrgula separando as declaraes. Todo o cabealho
dever estar obrigatoriamente entre parnteses!

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 12


Estrutura de repetio for em uma linha

Sintaxe:
for (inicializao; teste; atualizao)
sentena;

Figura 9 Sintaxe abreviada da estrutura condicional for

Quando o bloco da estrutura for contm apenas uma nica sentena, pode-se omitir as
chaves que delimitam o bloco, tal como na Figura 9. No entanto, essa forma no delimita
claramente o cdigo a ser executado repetidamente do restante do programa. Por ser mais
confusa, evite a forma abreviada!
Exemplo
Este programa imprime todos os divisores de um nmero. Para um dado nmero n, o
programa testa todos os nmeros de 1 at n.
Cdigo Fonte
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int numero;
int divisor;
int resto;

printf("Digite o numero: ");


scanf("%d", &numero);

for (divisor = 1; divisor <= numero; divisor++) {


resto = numero % divisor;
if (resto == 0) {
printf("Divisor encontrado: %d \n", divisor);
}
}

return 0;
}
Consulte: EstruturasRepeticao\Divisores02\Divisores02.vcproj

Descrio passo a passo


O programa utiliza a mesma lgica que o exemplo apresentado para a estrutura while. A
discusso atm-se somente s diferenas na estrutura de repetio.

for (divisor = 1; divisor <= numero; divisor++) {


resto = numero % divisor;
if (resto == 0) {
printf("Divisor encontrado: %d \n", divisor);
}
}
A repetio controlada pelo valor da varivel divisor. Ela inicializada em 1 e a
repetio ocorre enquanto ela contiver valores menores ou iguais ao valor de

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 13


numero. Dentro do bloco for, calcula-se o resto da diviso. Caso ele seja zero,
significa que encontramos um divisor.
Primeiro exemplo de execuo:
Digite o numero: 100
Divisor encontrado: 1
Divisor encontrado: 2
Divisor encontrado: 4
Divisor encontrado: 5
Divisor encontrado: 10
Divisor encontrado: 20
Divisor encontrado: 25
Divisor encontrado: 50
Divisor encontrado: 100
Segundo exemplo de execuo:
Digite o numero: 19
Divisor encontrado: 1
Divisor encontrado: 19

Casos de Uso
Um programa pode ser escrito corretamente tanto com while, como com do...while
como com for. A escolha da estrutura cabe ao programador, que deve preferir aquela que
produz cdigo mais simples e fcil de entender.
while (expresso) { ... }
Objetivo: Executar o bloco apenas enquanto uma condio for verdadeira. Se a condio
for falsa logo no incio, o bloco no executado nenhuma vez.
Sugerido quando:
No h necessidade de inicializar ou atualizar variveis contadoras.
As etapas de inicializao ou atualizao requerem muitas instrues e no
caberiam elegantemente numa nica linha do for.
As informaes necessrias para avaliar a condio no dependem de uma varivel
contadora ou so obtidas durante a execuo do bloco.
Nestes trs casos anteriores, prefira um while ao invs do for.
do { ... } while (expresso);
Objetivo: Executar o bloco pelo menos uma vez e repetir enquanto uma condio for
verdadeira.
Sugerido quando:
necessrio executar um bloco pelo menos uma vez para obter as informaes
necessrias para avaliar a condio.
muito comum utilizar o do...while para leitura de dados. Um uso tpico poderia ser
repetir a leitura enquanto o dado no for vlido.
for (inicializao; teste; reinicializao) { ... }
Objetivo: Executar o bloco um certo nmero de vezes, controlado por uma varivel
contadora.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 14


Sugerido quando:
O nmero de repeties controlado por uma varivel controladora.
H necessidade de inicializao e atualizao, mas que sejam simples o suficiente
para acomodar na linha do for. Para casos mais complexos, melhor usar o
comando while.
A avaliao da condio no depende de dados obtidos na execuo do bloco.
Considere o uso do for para separar claramente as instrues do controle de repetio
(inicializao e atualizao) das demais instrues do bloco.
Mas adiante, o for ser uma ferramenta til para percorrer elementos de vetores, listas e
matrizes. A varivel contadora do for ser justamente um ndice para o vetor ou para a
matriz.

Exemplos Tpicos
Para entender melhor quando utilizar cada uma das estruturas, analisaremos alguns
exemplos que exigem execuo repetida do mesmo bloco de cdigo.
Caso 1, usando for: Ler uma quantidade fixa de valores
Primeiro, o usurio informa a quantidade de valores disponveis e em seguida informa cada
um dos valores. O programa calcula a mdia dos nmeros lidos.
Neste caso, ser conveniente utilizar um for, pois veremos que:
Existe uma varivel contadora que controla o nmero de repeties para a leitura
dos valores.
H necessidade de inicializar e atualizar esta varivel contadora. A inicializao e a
atualizao so instrues simples que so acomodadas facilmente em uma linha do
for.
conveniente separar a inicializao e atualizao do bloco que calcula a mdia.
Cdigo fonte:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int quantidade;
int contador;
double valor;
double soma = 0;
double media;
// Solicita a quantidade de nmeros que devem ser lidos
printf("Quantidade de valores: ");
scanf("%d", &quantidade);

// Solicita cada um dos nmeros e soma-o


for (contador = 1; contador <= quantidade; contador++) {
printf("Valor: ");
scanf("%lf", &valor);
soma += valor;
}
media = soma / quantidade;
printf("Mdia: %f", media);
return 0;

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 15


}
Consulte: EstruturasRepeticao\Caso1\Caso1.vcproj

Descrio passo a passo:


int quantidade;
int contador;
double valor;
double soma = 0;
double media;
O programa comea declarando as variveis. A varivel quantidade armazenar o
nmero de valores lidos para calcular a mdia. A varivel contador conter
quantos valores j foram lidos. J a varivel valor armazenar o valor lido mais
recentemente. E soma guardar a soma de todos os valores que so lidos.
Finalmente, media armazenar o resultado calculado no final do programa.

printf("Quantidade de valores: ");


scanf("%d", &quantidade);
O programa solicita que o usurio digite o nmero de valores que devem ser lidos
para calcular a mdia.

for (contador = 1; contador <= quantidade; contador++) {


printf("Valor: ");
scanf("%lf", &valor);
soma += valor;
}
O for executa o bloco repetidamente, uma vez para cada valor de contador entre
1 e o nmero armazenado em quantidade. A cada repetio, solicita um nmero, o
qual somado ao valor anterior em soma, e que substitui o antigo valor nessa
varivel.

media = soma / quantidade;


printf("Mdia: %f", media);
No final, o programa calcula a mdia e apresenta o valor.
Exemplo de execuo:
Quantidade de valores: 5
Valor: 3
Valor: 5
Valor: 4
Valor: 6
Valor: 5
Mdia: 4.600000

O que ocorre quando o usurio entra um valor zero ou negativo para quantidade? Modifique
o programa para se precaver desses casos.
Caso 2, usando while: Ler uma quantidade fixa de valores
O mesmo programa pode ser escrito usando while, mas torna o cdigo um pouco menos
evidente.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 16


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int quantidade;
int contador;
double valor;
double soma = 0;
double media;

// Solicita a quantidade de nmeros que devem ser lidos


printf("Quantidade de valores: ");
scanf("%d", &quantidade);

// Solicita cada um dos nmeros e soma-o


contador = 1;
while (contador <= quantidade) {
printf("Valor: ");
scanf("%lf", &valor);
soma += valor;
contador++;
}

// Calcula e mostra a mdia


media = soma / quantidade;
printf("Media: %f", media);
return 0;
}
Consulte: EstruturasRepeticao\Caso2\Caso2.vcproj

Caso 3, usando while: Ler uma quantidade desconhecida de valores


Desejamos calcular a mdia de uma lista de nmeros no negativos, de comprimento
arbitrrio. O usurio escreve a lista de nmeros, indicando o fim da lista com um nmero
negativo.
Neste caso, ser conveniente utilizar um while, pois veremos que:
No existe uma varivel que controla o nmero de repeties da leitura do valor.
As informaes necessrias para avaliar a condio so obtidas durante a execuo
do bloco.

Cdigo fonte:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int quantidade = 0;
double valor;
double soma = 0;
double media;

// Solicita cada um dos nmeros e soma-o


scanf("%lf", &valor);
while (valor >= 0.0) {
soma += valor;
quantidade++;

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 17


scanf("%lf", &valor);
}

// Calcula e mostra a mdia


media = soma / quantidade;
printf("Media: %f", media);
return 0;
}
Consulte: EstruturasRepeticao\Caso3\Caso3.vcproj

Descrio passo a passo:


int quantidade = 0;
double valor;
double soma = 0;
double media;
O programa declara variveis de forma semelhante aos exemplos anteriores.

scanf("%lf", &valor);
while (valor >= 0.0) {
soma += valor;
quantidade++;
scanf("%lf", &valor);
}
A diferena est no uso da estrutura while para determinar o momento para
terminar a repetio da leitura.
O programa precisa ler o primeiro nmero antes de verificar a condio, o que
justifica o scanf antes do while. Se ele for no negativo, ento ele somado no
bloco do while. A varivel quantidade aumentada em uma unidade para saber
quanto nmeros foram somados at agora no clculo da mdia. Por fim, necessrio
ler o prximo nmero antes de avaliar novamente a condio do while. Por este
motivo, a ltima linha do bloco contm um scanf para ler tal nmero.

media = soma / quantidade;


printf("Media: %f", media);
A mdia calculada da mesma forma como nos dois exemplos anteriores. O que
ocorre se a lista de nmeros for vazia, isto , o usurio entra logo com um primeiro
valor que negativo? Melhore o programa de forma que evite esse caso de
contorno.
Exemplo de execuo:
Escreva os valores, terminando com um nmero negativo.
3 5 4 6 5 -1
Media: 4.600000
Caso 4, usando do...while: Ler uma quantidade desconhecida de valores
O programa anterior pode ser reescrito usando a estrutura do...while.
Cdigo Fonte:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 18


int quantidade = 0;
double valor;
double soma = 0;
double media;

// Solicita cada um dos nmeros e soma-o


printf("Escreva os valores, terminando com um nmero negativo.\n");
do {
scanf("%lf", &valor);
if (valor >= 0.0) {
soma += valor;
quantidade++;
}
} while (valor >= 0.0);

// Calcula e mostra a mdia


media = soma / quantidade;
printf("Media: %f", media);
return 0;
}
Consulte: EstruturasRepeticao\Caso4\Caso4.vcproj

Descrio passo a passo:


Este programa semelhante ao caso anterior, variando apenas no uso da estrutura
do...while ao invs do while.
O primeiro comando executado no bloco o comando scanf, que l o prximo
valor. Se este valor for maior ou igual a zero, ento ele somando para o clculo da
mdia. Repare como agora resolvemos o problema usando o scanf apenas uma vez.
Por outro lado, precisamos sempre testar o valor lido dentro do bloco do scanf.
Poderamos ter evitado o teste, sempre somando o valor lido dentro do bloco, mas
desde que tenhamos o cuidado de, aps terminada a execuo do do...while,
subtrairmos o ltimo valor somado, que ter sido somado indevidamente.
A condio se sada verifica se o ltimo valor lido maior ou igual a zero e repete o
bloco caso afirmativo.
Comparao com o programa anterior
Para este programa, difcil decidir qual estrutura de repetio mais vantajosa: o
while o do...while. Os dois programas so idnticos quanto ao resultado
produzido.
O do...while menos elegante pois necessrio verificar a condio duas vezes e
por exigir um if dentro do do...while. O while, tem o inconveniente de exigir
duas linhas com o comando scanf.
Caso 5, usando do...while : executar at que o usurio decida parar
Podemos mostrar um uso interessante do do...while com o seguinte programa. Ele
idntico ao caso 1, mas possui a opo de ser executado vrias vezes. Depois de calcular a
mdia, o programa pergunta ao usurio se ele deseja repetir tudo de novo, para calcular
uma nova mdia sobre novos nmeros.
Cdigo Fonte:
#include <stdio.h>

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 19


#include <stdlib.h>

int main(int argc, char *argv[]) {


int quantidade;
int contador;
double valor;
double soma;
double media;
char repetir;

do {
// Solicita a quantidade de nmeros que devem ser lidos
printf("Quantidade de valores: ");
scanf("%d", &quantidade);
soma = 0; // inicializa soma com 0, inclusive nas demais iteracoes
// Solicita cada um dos nmeros e soma-o
for (contador = 1; contador <= quantidade; contador++) {
printf("Valor: ");
scanf("%lf", &valor);
soma += valor;
}

// Calcula e mostra a mdia


media = soma / quantidade;
printf("Media: %f\n\n", media);

printf("Deseja executar o programa novamente? (s/n) ");


scanf(" %c", &repetir);
} while (repetir == 's');

return 0;
}
Consulte: EstruturasRepeticao\Caso5\Caso5.vcproj

Descrio passo a passo:


Note que o bloco do do...while idntico ao programa do caso 1. No fim da
execuo do bloco, aps mostrar a mdia, o programa solicita que o usurio digite
uma das letras s ou n, para informar se ele quer executar novamente.
A condio do do...while tal que, enquanto o usurio terminar o bloco com a
letra s, o programa executado novamente.
Exemplo de execuo:
Quantidade de valores: 5
Valor: 3
Valor: 4
Valor: 3
Valor: 6
Valor: 5
Media: 4.200000
Deseja executar o programa novamente? (s/n) s
Quantidade de valores: 3
Valor: 6
Valor: 8
Valor: 9
Media: 14.666667

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 20


Deseja executar o programa novamente? (s/n) n

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 21


Controle de Repetio
Forar interrupo de repetio: break
O comando break um modo conveniente de terminar imediatamente a execuo de um
bloco controlado por uma estrutura de repetio, sem necessidade de esperar a prxima
avaliao da condio. O comando break til para interromper a excuo de uma
estrutura de repetio quando fica evidente que as demais repeties no produziro novos
resultados. Assim, o programa pode economizar algum tempo de execuo. No prximo
exemplo, que verifica se um nmero primo, o comando break ser usado para
interromper as repeties assim que mais de dois divisores forem encontrados.
A Figura 10 ilustra o desvio no fluxo de execuo causado pelo comando break. O break
no espera o trmino da execuo do restante do bloco. As linhas tracejadas mostram o

for (inicializao;
while (expresso) { teste;
do { sentenas(s);
sentenas(s); atualizao) {
if (condio) {
if (condio) { sentenas(s);
break;
break; if (condio) {
}
} break;
sentenas(s);
sentenas(s); }
} while (expresso);
} sentenas(s);
}
incio

incio incio inicializao

0
expresso teste
sentena(s) 0
1
break 1

1
sentena(s)
sentena(s)
break
expresso break

0
atualizao
fim fim

fim
Figura 10 Fluxo de controle em estruturas de repetio com break
fluxo convencional. A linha contnua representa o fluxo caso o break seja executado.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 22


Observao: O uso do comando break costuma estar associado com uma estrutura
condicional if para que a interrupo seja realizada somente sob determinadas condies
excepcionais.

Exemplo
Um programa que verifica se um nmero primo ou no. O programa utiliza o mesmo
algoritmo utilizado para encontrar os divisores de um nmero.
Note que o nmero primo contm exatamente dois divisores (1 e o prprio nmero).
Portanto, assim que o terceiro divisor for encontrado, ficar evidente que o nmero no
primo. Nesta situao, o programa utiliza o break para terminar a execuo do while,
evitando continuar as iteraes seguintes, que no seriam teis.
Cdigo fonte
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


int numero;
int divisor;
int resto;
int numero_divisores;

printf("Digite o numero: ");


scanf("%d", &numero);

numero_divisores = 0;
for (divisor = 1; divisor <= numero; divisor++) {
resto = numero % divisor;
if (resto == 0) {
numero_divisores = numero_divisores + 1;
if (numero_divisores >= 3) {
break;
}
}
}
if (numero_divisores == 2) {
printf("O numero %d eh primo!\n", numero);
} else {
printf("O numero %d NAO eh primo!\n", numero);
}

return 0;
}
Consulte: ControleExecucao\Divisores03\Divisores03.vcproj

Descrio passo a passo


int numero;
int divisor;
int resto;
int numero_divisores;
A varivel numero armazena o valor digitado pelo usurio. A varivel divisor
um contador para armazenar o prximo divisor a ser verificado. A varivel resto
uma varivel usada para armazenamento temporrio dentro do bloco de repetio do
for. E numero_divisores conta quantos divisores foram encontrados at o
momento.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 23


numero_divisores = 0;
for (divisor = 1; divisor <= numero; divisor++) {
...
}
A repetio controlada pelo valor da varivel divisor. Ela inicializada em 1 e a
repetio ocorre enquanto ela contiver valores menores ou iguais ao prprio
nmero.

resto = numero % divisor;


if (resto == 0) {
numero_divisores++;
if (numero_divisores >= 3) {
break;
}
}
O cdigo executado dentro da repetio calcula o resto da diviso. Sendo ele zero,
significa que encontramos um divisor. Neste caso, o contador numero_divisores
atualizado. Verifica-se ento se numero_divisores ultrapassou o nmero mximo
de divisores para um nmero primo (2 divisores). Se verdadeiro, o break
interrompe imediatamente a execuo do for, independente de quantas repeties
ainda faltem.

if (numero_divisores == 2) {
printf("O numero %d eh primo!\n", numero);
} else {
printf("O numero %d NAO eh primo!\n", numero);
}
No fim, se o nmero de divisores for 2, ento temos um nmero primo. Em
qualquer caso, uma mensagem impressa informando este resultado. Note que o
nmero 1 no considerado primo. Nesse caso, o funcionamento do programa
tambm correto, pois apenas um divisor (ele mesmo) ser encontrado.
Primeiro exemplo de execuo
Digite o numero: 5
O numero 5 eh primo!
Primeiro exemplo de execuo
Digite o numero: 10
O numero 10 NAO eh primo!

Reiniciar repetio: continue


O comando continue reinicia imediatamente a execuo de um bloco de uma estrutura de
repetio. O continue no espera o trmino da execuo do restante do bloco. No caso do
while, a execuo retorna imediatamente para avaliar a expresso, antes de executar
novamente o bloco, se for o caso. Se a expresso avaliar em falso, ento o while
finalizado, caso contrrio ele realiza uma nova iterao.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 24


Para o for, o continue interronpe a execuo normal do bloco, realiza imediatamente a
atualizao das variveis de controle para, em seguida, realizar novamente o teste. Se o
teste resultar em falso, ento o for finalizado, caso contrrio ele realiza uma nova
iterao. No do...while, o continue simplesmente inicia uma nova iterao, no incio do
bloco.
O comando continue til para avanar para a prxima repetio quando fica evidente
que a execuo atual do bloco no se faz mais necessria. Veja o prximo exemplo para
imprimir a tangente de ngulos de 0 a 180. Quando a iterao chega no ngulo de 90,
acionado o comando continue para avanar para o prximo ngulo, j que no existe
tangente de 90.
Observao: O uso do comando continue costuma estar associado com uma estrutura
condicional if para que a repetio seja reiniciada somente sob determinadas condies.
A Figura 11 ilustra o desvio no fluxo de execuo causado pelo comando continue. As
linhas tracejadas mostram o fluxo convencional. A linha contnua representa o fluxo caso o
continue seja executado.

for (inicializao;
while (expresso) { do { teste;
comandos(s); comandos(s); atualizao) {
if (condio) { if (condio) { comandos(s);
continue; continue; if (condio) {
} } continue;
comandos(s); comandos(s); }
} } while (expresso); comandos(s);
}
incio

incio incio inicializao

0
expresso teste
0
1 sentena(s)
continue 1

1
sentena(s)
sentena(s)
continue
expresso continue

0
atualizao
fim fim

fim
Figura 11 Fluxo de controle em estruturas de repetio com continue

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 25


Exemplo:
Um programa que imprime uma tabela com a imagem da funo tangente, em intervalos de
10 em 10 graus.
Cdigo fonte
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char *argv[]) {


double angulo;
double pi = 3.14159265358979;

for (angulo = 0; angulo <= 180; angulo += 10.0) {


if (angulo == 90.0) {
continue;
}

printf("tan(%f) = %f\n", angulo, tan(angulo/180*pi));


}

return 0;
}
Consulte: ControleExecucao\Tangete01\Tangente01.vcproj

Descrio passo a passo


double angulo;
double pi = 3.14159265358979;
A varivel angulo percorre o intervalo de zero at 180 graus. J pi uma varivel
usada para realizar a converso de graus para radianos.

for (angulo = 0; angulo <= 180; angulo += 10.0) {


if (angulo == 90.0) {
continue;
}
...
}
O for executa o bloco para diferentes valores de ngulos, em passos de 10 em 10
graus. No entanto, ao chegar ao valor de 90.0, a funo tangente no est definida!
Por este motivo, este valor precisa ser ignorado. Para tal, utiliza-se o comando
continue para reiniciar o for com o prximo valor (ou seja, 100 graus).

printf("tan(%f) = %f\n", angulo, tan(angulo/180*pi));


O printf no tem muito mistrio. Ele imprime o ngulo e o valor da funo tangente.
No entanto, antes, necessrio realizar uma converso para radianos, que o
formato esperado pela funo tan.
Exemplo de execuo
tan(0.000000) = 0.000000
tan(10.000000) = 0.176327
tan(20.000000) = 0.363970
tan(30.000000) = 0.577350
tan(40.000000) = 0.839100
tan(50.000000) = 1.191754
tan(60.000000) = 1.732051

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 26


tan(70.000000) = 2.747477
tan(80.000000) = 5.671282
tan(100.000000) = -5.671282
tan(110.000000) = -2.747477
tan(120.000000) = -1.732051
tan(130.000000) = -1.191754
tan(140.000000) = -0.839100
tan(150.000000) = -0.577350
tan(160.000000) = -0.363970
tan(170.000000) = -0.176327
tan(180.000000) = -0.000000

Fluxo de execuo arbitrrio: goto


O comando goto tem por finalidade desviar a execuo do programa para qualquer outro
ponto do programa, desconsiderando qualquer estrutura de repetio ou estrutura
condicional. O goto pode desviar a execuo para um ponto anterior na sequncia
(retrocesso), como tambm pode saltar para qualquer ponto situado mais para frente na
sequncia (avano). Em qualquer um dos casos, necessrio declarar uma marca que ser o
destino do goto. A marca um identificador seguido por dois-pontos (:). O nome desse
identificador segue as mesmas regras de escolha de nome que as mencionadas para
variveis.
Sintaxe: Sintaxe:
sentena(s); sentena(s);
... ...
marca1: goto marca2;
... ...
sentena(s); sentena(s);
... ...
goto marca1; marca2:
... ...
sentena(s); sentena(s);

Figura 12 Sintaxe goto: retrocesso Figura 13 Sintaxe goto: avano

Exemplo:
Imprimir os nmeros de 1 at 10.
Cdigo fonte:
#include <stdio.h>
#include <stdlib.h>
/*
* Imprime nmeros de 1 at 10, usando apenas GOTO.
*/
int main() {
int numero = 1;

inicio_repeticao:
if (numero > 10) { goto fim_repeticao; }
printf("%d " , numero);
numero++;
goto inicio_repeticao;
fim_repeticao:
return 0;
}

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 27


Consulte: ControleRepeticao\Goto01\Goto01.vcproj

Descrio passo a passo:


int numero = 1;
O programa comea declarando a varivel numero, inicializada com o valor 1. Essa
varivel servir de contador de repeties.

inicio_repeticao:
Em seguida, declara-se uma marca, que identifica o inicio do cdigo que dever ser
repetido 10 vezes.
fim_repeticao:
No final do programa, declara-se outra marca, para definir o ponto para onde saltar
aps a execuo das 10 iteraes.

if (numero > 10) {


goto fim_repeticao;
}
Assim que o contador de iteraes ultrapassar o valor mximo permitido, o
programa instrudo a saltar para o ponto fim_repeticao, localizado no final do
cdigo.

printf(%d\n , numero);
numero++;
goto inicio_repeticao;
O programa imprime o nmero e atualiza a varivel contadora. O comando goto
fora um desvio para o incio do lao, de modo a realizar novamente todas as
operaes para o prximo nmero na seqncia.
Exemplo de execuo:
1 2 3 4 5 6 7 8 9 10
Casos de uso do goto
Todos as estruturas de repetio podem ser escritas utilizando-se apenas marcas e gotos.
Mesmo assim, o emprego de goto no recomendado por vrios motivos, entre eles:
Dificulta a visualizao do destino de cada goto.
Oculta a estrutura lgica e de execuo do programa. Com o uso de while e for,
fcil identificar as condies de repetio, a inicializao e a atualizao de
variveis, como tambm o bloco que deve ser repetido. Com gotos, os blocos no
estaro mais realados por delimitaes.
Cada programador pode adotar sua prpria lgica de fluxo de execuo. Os
programas tornar-se-o incompreensveis e muito difceis e entender e de manter!
Toda a lgica de goto pode ser re-escrita de forma muito mais elegante usando
while, do...while, for e, se necessrio, tambm break e continue.

Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber 28

Das könnte Ihnen auch gefallen