Você está na página 1de 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 partes do cdigo 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, e a execuo continuar com a
sentena ou comando que vem logo aps o bloco do while, na seqncia do programa.
incio
0

expresso
1

Sintaxe:
while (expresso) {
sentena;
sentena;
...
}

sentena(s)
Figura 2 Sintaxe da estrutura de repetio
while

fim
Figura 1 Fluxo de controle da
estrutura de repetio 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
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 retorne um valor zero (falso). A expresso sempre avaliada antes da
deciso de se executar o bloco de sentenas novamente.
Observao: A expresso dever ser colocada, obrigatoriamente, entre parnteses.
Copyright@2005,2006,2007,2008: Arnaldo V. Moura, Daniel F. Ferber

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. Mesmo que
durante uma execuo do bloco a condio se torne 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, a varivel numero contm o valor 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 se tornar falsa. Nesse ponto, o while termina, encerrando as repeties.
No final da execuo, o valor da varivel numero estar em 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
chaves que delimitam o bloco, como na Figura
while (expresso)
3. No entanto, essa forma no delimita
sentena;
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

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;

Trs variveis inteiras so declaradas. 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, encerrar
as repeties.

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

No incio, antes de executar a repetio, a varivel divisor iniciada com um


valor vlido (1), que o primeiro divisor possvel. A 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 a
repetio ser encerrada.
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

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 obter o valor do 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 usada apenas para armazenamento temporrio durante a 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

Sintaxe:

incio
do {

sentena(s)

expresso

sentena;
sentena;
...
} while (expresso);

Figura 5 Sintaxe da estrutura de repetio


do...while

0
fim
Figura 4 Fluxo de controle da
estrutura de repetio 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 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

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
do...while contm apenas uma nica
Sintaxe:
sentena, pode-se omitir as chaves que
do sentena while (expresso);
delimitam o bloco como na Figura 6.
No entanto, essa forma no delimita
claramente o cdigo do restante do
Figura 6 Sintaxe abreviada da estrutura
condicional do...while
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 programa 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

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 a
10, no final de cada iterao tnhamos:
numero = numero + 1;

Em C, a sentena acima significa que a varivel numero recebe um novo valor devido ao
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 facilitam a sintaxe dessas operaes:
Para:

Use o atalho:

Forma original:

Somar uma unidade ao valor ++numero;


da varivel

numero = numero + 1;
(retorne numero)

Subtrair uma unidade do --numero;


valor da varivel

numero = numero - 1;
(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 e mais difcil de entender.
2. O novo valor atribudo varivel, cujo valor estar acrescido de uma unidade.
3. O novo valor, j acrescido da unidade, retornado como o valor do clculo da
expresso.

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

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);
++numero;
} while (numero <= 10);
Consulte: EstruturasRepeticao\dowhile02\dowhile02.vcproj

Existem comandos semelhantes aos anteriores, 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++;


varivel, retornando o valor
original

(retorne numero)
numero = numero + 1;

Subtrair um do valor da numero--;


varivel, retornando o valor
original

(retorne numero)
numero = numero - 1;

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 na forma geral
variavel = variavel op expressao

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

onde op um dos operadores aritmticos, tambm ocorrem com bastante freqncia.


Nesses casos, podemos escrever essas atribuies de forma simplificada como
variavel op= expressao

A tabela a seguir ilustra os casos possveis.


Para:

Use o atalho:

Forma original:

Somar k unidades ao valor numero += k;


da varivel

numero = numero + k;

Subtrair k unidades do valor numero -= k;


da varivel

numero = numero - k;

Multiplicar o
varivel por k

da numero *= k;

numero = numero * k;

Dividir o valor da varivel numero /= k;


por k

numero = numero / k;

valor

Estrutura de repetio for


Na maioria dos 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;
while (numero <= 10) {
printf("%d\n", numero);
...
numero = numero + 1;
}

// Inicializao
// Teste
// Execuo
// 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

Sintaxe:

incio
inicializao

teste
1
sentena(s)

for (inicializao;
teste;
atualizao) {
sentena;
sentena;
...
}

Figura 8 Sintaxe da estrutura de repetio


for

atualizao
fim
Figura 7 Fluxo de controle da
estrutura de repetio 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 observamos que o programa
faz a inicializao, que atribui o valor inicial varivel contadora. Em seguida avalia a
expresso, que determina 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 ilustrada na 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 da 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 iniciar a varivel numero com 1, ela agora iniciada com 10. A cada
repetio, a atualizao deve reduzir o valor da varivel correspondente em uma
unidade. Portanto, podemos escrever numero--. A condio deve verificar agora se
o valor de numero maior ou igual a 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 a 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 iniciada com 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 que sejam acomodadas 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 do vetor ou da 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 vemos que:

Podemos usar uma varivel contadora para controlar 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, e que podem ser 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 contra esses 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 vemos que:

No sabemos quantos dados sero digitados e, portanto, no podemos usar


diretamente 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 como nos 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. Esse valor ser necessrio para o 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 essa condio 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>

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

18

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


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 com 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.

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

19

Cdigo Fonte:
#include <stdio.h>
#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...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

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

20

Media: 14.666667
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 execuo 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

while (expresso) {
sentenas(s);
if (condio) {
break;
}
sentenas(s);
}

do { sentenas(s);
if (condio) {
break;
}
sentenas(s);
} while (expresso);

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

incio
0

incio

inicializao

expresso

sentena(s)
break

sentena(s)
break

teste
1

1
expresso

sentena(s)
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 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 que j vimos 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
int
int
int

numero;
divisor;
resto;
numero_divisores;

A varivel numero armazena o valor digitado pelo usurio. A varivel divisor


um contador para armazenar o prximo candidato a divisor a ser testado. A varivel
resto 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 inicializa 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 final, 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 como 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 interrompe 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 ao 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.

while (expresso) {
comandos(s);
if (condio) {
continue;
}
comandos(s);
}

do {
comandos(s);
if (condio) {
continue;
}
comandos(s);
} while (expresso);

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

incio
0

expresso

sentena(s)
continue

sentena(s)
continue

inicializao

incio

teste
1

1
expresso

sentena(s)
continue

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 graus, 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 comando printf simples. 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 seqncia
(retrocesso), como tambm pode saltar para qualquer ponto situado mais para frente na
seqncia (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 nomes para variveis.
Sintaxe:
sentena(s);
...
marca1:
...
sentena(s);
...
goto marca1;
...
sentena(s);

Figura 12 Sintaxe goto: retrocesso

Sintaxe:
sentena(s);
...
goto marca2;
...
sentena(s);
...
marca2:
...
sentena(s);

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;
}
Consulte: ControleRepeticao\Goto01\Goto01.vcproj

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

27

Descrio passo a passo:


int numero = 1;

O programa comea declarando a varivel numero, que recebe o valor inicial 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 embutida em um goto pode sempre ser re-escrita de forma muito
mais elegante usando os comandos while, do...while, for e, se necessrio,
tambm os comandos break e continue.

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

28

Você também pode gostar