Você está na página 1de 16

4.

Estruturas de repetio
4.1 Para que servem as estruturas de repetio
Um locutor brasileiro ao narrar um jogo de futebol americano nos Estados Unidos recebe a informao
do placar eletrnico sobre a temperatura do estdio medida em graus Fahrenheit. Naturalmente, ele deve
fornecer aos telespectadores brasileiros a temperatura em graus Celsius. Para isto, o locutor, de posse de um
computador, poderia utilizar o programa abaixo, que foi solicitado no primeiro item do segundo exerccio da
seo 2.12.
/*Programa que converte uma temperatura dada em graus Fahrenheit para graus Celsius*/
#include <stdio.h>
main()
{
float Fahrenheit, Celsius;
printf("Digite a temperatura em Fahrenheit");
scanf("%f", &Fahrenheit);
Celsius = 5 * (Fahrenheit - 32)/9;
printf("A temperatura de %.2f Fahrenheit corresponde a %.2f Celsius ", Fahrenheit, Celsius);
}
Se o placar eletrnico indicasse uma temperatura de 60
o
F, o narrador executaria o programa com a
entrada 60 e receberia a sada
A temperatura de 60 graus Fahrenheit corresponde a 15.55 graus Celsius
Certamente, seria mais prtico a produo da transmisso do evento disponibilizar para o locutor uma
tabela contendo as temperaturas possveis em graus Fahrenheit e as correspondentes em graus Celsius. A
confeco desta tabela poderia ser feita atravs de um programa que contivesse vrios comandos que
calculassem para cada temperatura em graus Fahrenheit pretendida a correspondente temperatura em graus
Celsius e exibissem estas temperaturas. Neste caso, no haveria necessidade de comando de entrada; porm,
para cada temperatura em graus Fahrenheit pretendida, haveria, pelo menos, um comando de atribuio e a
chamada da funo printf(). Se a faixa de temperatura em graus Fahrenheit a ser coberta pela tabela fosse de
vinte a oitenta graus, teramos um programa como o programa abaixo.
/*Programa (muito ruim) que gera uma tabela de converso de temperaturas em graus Fahrenheit para
graus Celsius */
#include <stdio.h>
main()
{
int Fahrenheit;
printf("Tabela de conversao graus Fahrenheit/graus Celsius \n");
printf("-------------------------------------------------\n");
printf("\t Fahrenheit \t | \t Celsius\n");
printf("-------------------------------------------------\n");
Fahrenheit = 10;
printf("\t %f \t | \t %f \n", Fahrenheit, 5.0*(Fahrenheit - 32)/9);
Fahrenheit = 11;
printf("\t %f \t | \t %f \n", Fahrenheit, 5.0*(Fahrenheit - 32)/9);
. . .
/*Mais "uma poro" de comandos! */
Fahrenheit = 80;
printf("\t %f \t | \t %f \n", Fahrenheit, 5.0*(Fahrenheit - 32)/9);
}
Isto seria contornado se pudssemos repetir a execuo dos comandos que gerariam as temperaturas
em graus Fahrenheit e as correspondentes em graus Celsius. A linguagem C possui os comandos for; while e
do while, chamados estruturas de repetio ou laos, cujas execues redundam em repeties da execuo
de uma determinada sequncia de comandos.
4.2 O comando for
O comando for uma estrutura de repetio que repete a execuo de uma dada sequncia de
comandos um nmero de vezes que pode ser determinado pelo prprio programa, devendo ser escrito com a
seguinte sintaxe:
for (inicializaes; condies de manuteno da repetio; incrementos)
{
sequncia de comandos
}
Como os nomes indicam, em inicializaes, so atribudos valores iniciais a variveis; em condies
de manuteno da repetio, estabelecem-se, atravs de uma expresso, as condies nas quais a execuo
da sequncia de comandos ser repetida; em incrementos, incrementam-se variveis. Quando um comando
for executado, a sequncia de comandos da rea das inicializaes executada. Em seguida, a expresso
que fixa as condies de manuteno da repetio avaliada. Se o valor desta expresso no for nulo, a
sequncia de comandos executada, sendo em seguida executada a sequncia de comandos da rea dos
incrementos. Novamente a expresso das condies de manuteno da repetio avaliada e tudo se repete
at que o seu valor seja igual a zero.
Por exemplo, o programa
#include <stdio.h>
main()
{
int i;
for (i = 1; i <= 10; i = i + 1)
printf("%d ", i);
}
exibe na tela os nmeros 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Por seu turno, o programa
#include <stdio.h>
main()
{
int i;
for (i = 10; i >= 0; i = i - 2)
printf("%d ", i);
}
exibe na tela os nmeros 10, 8, 6, 4, 2, 0. J o programa
#include <stdio.h>
main()
{
int i;
for (i = 1; i <= 10; i = i + 20)
printf("%d ", i);
}
exibe, apenas, o nmero 1.
A semntica do comando for implica que a sequncia de comandos pode no ser executada nem uma
nica vez. Basta que na "primeira" execuo do comando for a expresso que controla a repetio assuma o
valor zero. Por exemplo, o programa abaixo no exibe nenhum valor na tela.
#include <stdio.h>
main()
{
int i;
for (i = 11; i <= 10; i = i + 20)
printf("%d ", i);
}
Com o comando for, a questo da gerao de uma tabela de converso de temperaturas em graus
Fahrenheit para graus Celsius seria simples.
#include <stdio.h>
#include <conio.h>
main()
{
int Fahrenheit;
float Celsius;
clrscr();
printf("Tabela de converso graus Fahrenheit/graus Celsius \n");
printf("-------------------------------------------------\n");
printf("\t Fahrenheit \t | \t Celsius\n");
printf("-------------------------------------------------\n");
for (Fahrenheit = 20; Fahrenheit <= 80; Fahrenheit = Fahrenheit + 1)
{
Celsius = 5.0*(Fahrenheit - 32)/9;
printf("\t %.2f \t | \t %.2f \n", Fahrenheit, Celsius);
}
}
Na execuo do comando for, a varivel Fahrenheit inicializada com o valor 20, este valor
comparado com 80, a correspondente temperatura em graus Celsius calculada e os dois valores so
exibidos. Em seguida, o contedo de Fahrenheit incrementado de uma unidade e tudo se repete at que
Fahrenheit atinja o valor 81. Desta forma, a execuo deste programa gera a seguinte tabela
Tabela de converso graus Fahrenheit/graus Celsius
Fahrenheit Celsius
20 -6.67
21 -5.11
22 -5.56
23 -5.00
. . . . . .
79 26,11
80 26,67
Observe que toda a repetio controlada pela varivel Fahrenheit. Num caso como este, a varivel
em foco chamada varivel de controle da estrutura de repetio. Vale observar tambm que, ao contrrio
de outras linguagens (Pascal, por exemplo), a varivel de controle no tem que ser necessariamente do tipo
int. Por exemplo, se quisssemos que a tabela tambm fornecesse temperaturas em graus Fahrenheit
fracionrias (meio em meio grau, por exemplo), poderamos executar o seguinte programa.
#include <stdio.h>
#include <conio.h>
main()
{
float Celsius, Fahrenheit;
clrscr();
printf("Tabela de converso graus Fahrenheit/graus Celsius \n");
printf("-------------------------------------------------\n");
printf("\t Fahrenheit \t | \t Celsius\n");
printf("-------------------------------------------------\n");
for (Fahrenheit = 20; Fahrenheit <= 80; Fahrenheit = Fahrenheit + 0.5)
{
Celsius = 5.0*(Fahrenheit - 32)/9;
printf("\t %.2f \t | \t %.2f \n", Fahrenheit, Celsius);
}
}
Cabe observar que a sequncia de comandos cuja execuo se pretende repetir pode ser colocada na
rea dos incrementos. O programa acima ficaria ento com a seguinte forma:
#include <stdio.h>
#include <conio.h>
main()
{
float Celsius, Fahrenheit;
clrscr();
printf("Tabela de converso graus Fahrenheit/graus Celsius \n");
printf("-------------------------------------------------\n");
printf("\t Fahrenheit \t | \t Celsius\n");
printf("-------------------------------------------------\n");
for (Fahrenheit = 20; Fahrenheit <= 80; Celsius = 5.0*(Fahrenheit 32)/9, printf("\t %.2f \t | \t %.2f
\n", Fahrenheit, Celsius), Fahrenheit = Fahrenheit + 0.5);
}
Observe que, neste caso, o comando for concludo com um ponto-e-vrgula e que a leitura do
programa fica bastante dificultada. Este fato faz com que esta prtica no seja incentivada ao longo do livro.
Observe tambm que aproveitamos a oportunidade para apresentar mais uma funo de biblioteca do
sistema; trata-se de clrscr() cuja execuo resulta na limpeza da janela do usurio, o que evita que resultados
da execuo de um programa sejam confundidos com resultados de execues anteriores (clrscr vem de
clear screen que significa "limpa tela"). Como indicado na segunda instruo do programa, o cabealho da
funo clrscr() encontra-se no arquivo conio.h.
4.3 O comando while
Para introduzir uma nova estrutura de repetio e cotej-la com o comando for, considere um
programa para encontrar um divisor prprio de um inteiro dado (um divisor prprio de um inteiro n um
divisor de n diferente dele e de 1). Esta questo importante na verificao da primalidade de um inteiro:
um nmero que no tem divisores prprios dito primo. Com a utilizao do comando for teramos a
seguinte soluo para esta questo.
/*Programa que determina um divisor prprio de um inteiro */
#include <stdio.h>
main()
{
int Num, i, Divisor;
printf("Digite um numero: ");
scanf("%d", &Num);
Divisor = 0;
for (i = 2; i < Num; i = i + 1)
if (Num % i == 0)
Divisor = i;
if (Divisor != 0)
printf("%d divisor prprio de %d \n", Divisor, Num);
else
printf("%d no tem divisores prprios \n", Num);
}
Um problema com este programa que ele retorna sempre, se existir, o maior divisor prprio. Isto
significa que se a entrada for um nmero par a estrutura de repetio no interrompida quando o divisor 2
encontrado, o que, evidentemente, vai prejudicar a performance do programa. Isto pode ser contornado pois
os compiladores C permitem que uma varivel de controle de um comando for tenha o seu contedo alterado
dentro do prprio comando. Com isto, o programa acima ficaria da seguinte forma.
#include <stdio.h>
main()
{
int Num, i, Divisor;
printf("Digite um nmero inteiro: ");
scanf("%d", &Num);
Divisor = 0;
for (i = 2; i < Num; i = i + 1)
if (Num % i == 0)
{
Divisor = i;
i = Num;
}
if (Divisor != 0)
printf("%d e' divisor prprio de %d \n", Divisor, Num);
else
printf("%d no tem divisores prprios \n", Num);
}
Nesta verso, quando o primeiro divisor prprio encontrado, o comando i = Num; faz com que a
execuo do comando for seja interrompida. A prtica de encerrar um comando for atravs da alterao do
contedo da varivel de controle no ser aqui incentivada pelo fato de que isto desestrutura o programa,
dificultando sua legibilidade. Alm disso, h situaes em que no se pode conhecer o nmero mximo de
repeties de uma estrutura de repetio. Na verdade, a questo central que o comando for deve ser
utilizado quando o nmero de repeties de execuo de uma sequncia de comandos conhecido a priori.
Quando isto no acontece (que o caso do exemplo anterior: no se sabe a priori se e quando um divisor
prprio vai ser encontrado), deve-se usar o comando while, que possui a seguinte sintaxe:
while (Expresso)
{
Sequncia de comandos
}
sendo os delimitadores opcionais se a sequncia possui um s comando (como acontece nas outras
estruturas de repetio).
A semntica deste comando bvia: a sequncia de comandos executada enquanto o valor da
Expresso for diferente de zero. Naturalmente, pode ocorrer que a sequncia de comandos no seja
executada nenhuma vez, isto ocorrendo se o valor da Expresso for igual a zero quando da "primeira"
execuo do comando (o teste feito antes da execuo da sequncia de comandos). Por outro lado,
necessrio que um dos comandos da sequncia de comandos altere contedos de variveis que aparecem na
Expresso de modo que em algum instante ela se torne igual a zero. Do contrrio, a sequncia de comandos
ter sua execuo repetida indefinidamente, o programa nunca termina e, evidentemente, no executa a tarefa
para a qual foi desenvolvido. Quando isto acontece comum se dizer que o programa est em looping.
Com o comando while as questes levantadas acima sobre o programa para determinar um divisor
prprio de um inteiro dado so resolvidas e temos o seguinte programa:
/*Programa que determina o menor divisor prprio de um inteiro */
#include <stdio.h>
#include <conio.h>
main()
{
int Num, d, Met;
printf("Digite o numero: ");
scanf("%d", &Num);
Met = Num/2;
d = 2;
while (Num % d != 0 && d < Met)
d++;
if (d <= Met)
printf("%d divisor de %d \n", d, Num);
else
printf("%d no tem divisores prprios", Num);
getch();
}
Observe que, ao contrrio dos exemplos anteriores, a estrutura tambm seria interrompida quando a
varivel com a qual se procura um divisor atingisse a "metade" do inteiro; isto se explica pelo fato de que se
um inteiro no possui um divisor prprio menor do que sua "metade", ento ele primo. Esta verso ainda
pode ser melhorada utilizando-se o fato discutido em [Evaristo, J 2002] de que se um inteiro no possui um
divisor prprio menor do que ou igual a sua raiz quadrada, ele no tem divisores prprios. Levando isso em
conta, teramos o seguinte programa.
/*Programa que determina o menor divisor prprio de um inteiro*/
#include <stdio.h>
#include <conio.h>
#include <math.h>
main()
{
int Num, d;
float r;
printf("Digite o numero: ");
scanf("%d", &Num);
r = sqrt(Num);
d = 2;
while (Num % d != 0 && d <= r)
d++;
if (d <= r)
printf("%d divisor de %d \n", d, Num);
else
printf("%d no tem divisores prprios", Num);
getch();
}
Como j foi dito, um nmero inteiro que no tem divisores prprios chamado nmero primo. Assim,
o comando de sada vinculado opo else poderia ser
printf("%d primo", Num);
Vale observar que o comando d = 2; dos programas acima atribuiu um valor inicial varivel d. Este
valor incrementado de uma unidade enquanto um divisor no foi encontrado. Um comando de atribuio
de um valor inicial a uma varivel chamado inicializao da varivel e os compiladores da linguagem C
permitem que inicializaes de variveis sejam feitas no instante em que elas so declaradas. Assim, as
declaraes de variveis dos programas acima poderiam ter sido feitas da seguinte forma:
int Num, i, d = 2;
Neste livro, na maioria das vezes vamos optar por inicializar as variveis imediatamente antes da
necessidade. A razo desta opo que h situaes, como mostraremos no prximo exemplo, em que no se
pode simplesmente inicializar uma varivel quando da sua declarao.
Observe que o ltimo comando dos ltimos dois programas foi uma chamada da funo getch(). Como
j foi dito, a execuo desta funo requer a digitao de alguma tecla. Isto faz com a janela do usurio (que
exibe o resultado do processamento) permanea ativa at que uma tecla seja acionada.
Repetindo a execuo de um programa
Uma outra aplicao importante do comando while diz respeito a aplicaes sucessivas de um
programa. O leitor deve ter observado que os programas anteriores so executados apenas para uma entrada.
Se quisermos a sua execuo para outra entrada precisamos executar o programa de novo.
Pode-se repetir a execuo de um programa quantas vezes se queira, colocando-o numa estrutura
definida por um comando while, controlada pelo valor de algum dado de entrada. Neste caso, o valor que
encerra a execuo pode ser informado dentro da mensagem que indica a necessidade da digitao da
entrada. O programa anterior poderia ser ento escrito da seguinte forma.
/*Programa que determina o menor divisor prprio de um inteiro */
#include <stdio.h>
#include <conio.h>
#include <math.h>
main()
{
int Num, d;
float r;
printf("Digite o numero (zero para encerrar): ");
Num = 1;
while (Num != 0)
{
scanf("%d", &Num);
r = sqrt(Num);
d = 2;
while (Num % d != 0 && d <= r)
d++;
if (d <= r)
printf("%d divisor de %d \n", d, Num);
else
printf("%d primo", Num);
}
}
Observe que, neste caso, a varivel d no pode ser inicializada quando da sua declarao. Observe
tambm que no h necessidade da funo getch(), pois a prpria repetio da execuo deixa a janela do
usurio aberta.
Alguns programadores preferem que a repetio da execuo de um programa seja determinada por
uma pergunta ao usurio do tipo Deseja continuar (S/N)?. Neste caso, h necessidade de uma varivel do
tipo char para receber a resposta e controlar a repetio da execuo do programa.
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <math.h>
main()
{
int Num, d;
float r;
char c;
c = 'S';
while (toupper(c) == 'S')
{
printf("Digite o numero: ");
scanf("%d", &Num);
r = sqrt(Num);
d = 2;
while (Num % d != 0 && d <= r)
d++;
if (d <= r)
printf("%d divisor de %d \n", d, Num);
else
printf("%d primo", Num);
puts("Deseja continuar (S/N)?");
c = getch();
}
}
Vale lembrar que a funo toupper() retorna o argumento no formato maiusculo. Esta funo foi
ativada aqui para que o usurio no se preocupe em digitar como resposta letras maiusculas. Qualquer letra
que for digitada, a funo a torna maiuscula e o sistema a compara com S (maiusculo).
4.4 O comando do while
Como dissemos na seo anterior, o nmero de execues da sequncia de comandos associada a um
comando while pode ser zero. H situaes onde importante se garantir a execuo de uma sequncia de
comandos pelo menos uma vez. Uma situao onde isto importante a verificao da consistncia dos
dados de entrada. Esta ao consiste em se dotar o programa de recursos para recusar dados incompatveis
com a entrada do programa, s "recebendo" dados que satisfaam s especificaes (lgicas ou
estabelecidas) dos dados de entrada. Por exemplo, se a entrada um nmero correspondente a um ms do
ano, o programa no deve aceitar uma entrada que seja menor do que 1 nem maior do que 12. Uma soluo
para esta questo utilizando o comando while poderia ser a seguinte:
int Mes;
printf("Digite o ms: ");
scanf("%d", &Mes);
while ((Mes < 1) || (Mes > 12))
{
printf("\a Digitacao errada! Digite de novo \n");
printf("Digite o ms: ");
scanf("%d", &Mes);
}
Observe que, como a verificao da condio de repetio feita no "incio" do comando, h a
necessidade de uma leitura antes da estrutura e outra dentro dela (s para lembrar, \a emite um beep).
O comando do while define uma estrutura de repetio que garante que uma sequncia de comandos
seja executada pelo menos uma vez. Sua sintaxe :
do
{
Sequncia de comandos;
}
while (Expressao);
e sua semntica a seguinte: a sequncia de comandos executada e a Expresso avaliada; se o valor da
Expresso for diferente de zero, a sequncia de comandos novamente executada e tudo se repete; do
contrrio, o comando que segue a estrutura executado. importante observar a necessidade do ponto-e-
vrgula encerrando o do while.
A consistncia da entrada de um dado relativo a um ms utilizando um comando do while poderia ser
a seguinte.
int Mes;
do
{
printf("Digite mes: ");
scanf("%d", &Mes);
if ((Mes < 1) || (Mes > 12))
printf("\a Digitacao errada! Digite de novo \n");
}
while ((Mes < 1) || (Mes > 12));
A utilizao do comando do while para execues sucessivas de um programa mais natural, quando
a repetio da execuo feita atravs da resposta pergunta Deseja continuar (S/N)? . Teramos algo como:
#include <stdio.h>
main()
{
char Resp;
do
{
Sequncia de comandos do programa propriamente dito;
printf("Deseja continuar (S/N)?");
scanf("%c", &Resp);
}
while (toupper(Resp) == 'S');
}
4.5 O comando break em estruturas de repetio
Da mesma forma que sua ativao num case interrompe a execuo de uma estrutura switch, a
execuo de um comando break dentro de uma estrutura de repetio interrompe as execues da sequncia
de comandos da estrutura, mesmo que a condio de manuteno da repetio no tenha sido negada. Com o
uso do break, o programa acima que determinava o menor divisor prprio de um inteiro poderia ter a
seguinte forma:
#include <stdio.h>
#include <math.h>
main()
{
float r;
int Num, d;
printf("Digite um numero : ");
scanf("%d", &Num);
d = 2;
r = sqrt(Num);
while (d <= r)
if (Num % d == 0)
break;
else
d = d + 1;
if (d <= r)
printf("%d e' divisor proprio de %d \n", d, Num);
else
printf("%d e' primo \n", Num);
}
Neste livro, o uso do break em estruturas de repetio no ser estimulado visto que sua utilizao
pode trazer problemas de legibilidade aos programas.
4.6 Exemplos Parte IV
1. Consideremos um programa para determinar a soma dos n primeiros nmeros mpares, n dado. Por
exemplo, se for fornecido para n o valor 6, o programa deve retornar 36, pois 1 + 3 + 5 + 7 + 9 + 11 = 36.
Naturalmente, o sistema pode gerar os nmeros impares que se pretende somar, atravs do comando
Impar = 1 e da repetio do comando Impar = Impar + 2. Naturalmente, tambm, para que o sistema gere o
prximo mpar, o anterior j deve ter sido somado. Isto pode ser feito atravs do comando Soma = 0 e da
repetio do comando Soma = Soma + Impar. Temos ento o seguinte programa.
/*Programa que soma os n primeiros nmeros mpar, n dado*/
#include <stdio.h>
main()
{
int Soma, Impar, n, i;
printf("Digite o valor de n: ");
scanf("%d", &n);
Impar = 1;
Soma = 0;
for (i = 1; i <= n; i = i + 1)
{
Soma = Soma + Impar;
Impar = Impar + 2;
}
printf("Soma dos %d primeiros nmeros impares: %d \n", n, Soma);
}
Observe que os comandos Impar = 1 e Soma = 0 atribuem um valor inicial s variveis para que estes
valores iniciais possam ser utilizados nas primeiras execues dos comandos Soma = Soma + Impar e
Impar = Impar + 2. Como j dissemos, nos referimos a comandos que atribuem valores iniciais a variveis
para que estes valores possam ser utilizados na primeira execuo de um comando que ter sua execuo
repetida como inicializao da varivel.
Uma outra observao interessante que, como existe uma frmula que d o i-simo nmero mpar
(a
i
= 2i - 1), o programa acima poderia ser escrito de uma forma mais elegante, prescindindo, inclusive, da
varivel Impar.
/*Programa que soma os n primeiros nmeros impar, n dado*/
#include <stdio.h>
main()
{
int Soma, n, i;
printf("Digite o valor de n: ");
scanf("%d", &n);
Soma = 0;
for (i = 1; i <= n; i = i + 1)
Soma = Soma + 2*i - 1;
printf("Soma dos %d primeiros nmeros impares: %d \n", n, Soma);
}
Optamos por apresentar a primeira verso pelo fato de que nem sempre a frmula para gerar os termos
da sequncia que se pretende somar to simples ou muito conhecida. Por exemplo, o exerccio nmero 2
da seo 4.7 pede para somar os quadrados dos n primeiros nmeros naturais e, neste caso, embora a frmula
exista, ela no to conhecida.
2. Um dos exemplos da seo anterior apresentava um programa que determinava, se existisse, um
divisor prprio de um inteiro dado. Imaginemos agora que queiramos um programa que apresente a lista de
todos os divisores de um inteiro n dado. Neste caso, o programa pode percorrer todos os inteiros desde um
at a metade de n verificando se cada um deles um seu divisor. Temos ento o seguinte programa.
#include <stdio.h>
main()
{
int Num, i;
printf("Digite o numero: ");
scanf("%d", &Num);
printf("Divisores prprios de %d: \n", Num);
for (i = 2; i <= Num/2; i = i + 1)
if (Num % i == 0)
printf("%d \n", i);
}
Vale observar que, ao contrrio do que foi dito na seo 2.9, os valores de sada deste programa no
esto sendo armazenados. O que acontece que ainda no temos condies de armazenar uma quantidade
indefinida de elementos. Este problema ser resolvido no captulo 6.
3. Na seo 1.5 discutimos um algoritmo que determinava o quociente e o resto da diviso entre dois
inteiros positivos dados. Embora os compiladores de C possuam o operador % que calcula o resto de uma
diviso inteira entre dois inteiros positivos, vamos apresentar, por ser interessante, a implementao do
algoritmo referido.
/*Programa que determina o quociente e o resto da diviso entre dois inteiros positivos*/
#include <stdio.h>
main()
{
int Dividendo, Divisor, Quoc, Resto;
printf("Digite o dividendo e o divisor (diferente de zero!): ");
scanf("%d %d", &Dividendo, &Divisor);
Quoc = 1;
while (Quoc * Divisor <= Dividendo)
Quoc = Quoc + 1;
Quoc = Quoc - 1;
Resto = Dividendo - Quoc * Divisor;
printf("Quociente e resto da diviso de %d por %d: %d e %d\n", Dividendo, Divisor, Quoc, Resto);
}
4. Em muitos casos h necessidade de que um dos comandos da sequncia que ter sua execuo
repetida atravs de uma estrutura de repetio seja uma outra estrutura de repetio (num caso deste dizemos
que as estruturas esto aninhadas). Para um exemplo, sejam A = {1, 2, 3, ..., n} e um programa que pretenda
exibir o produto cartesiano AxA. Observe que para cada valor da primeira componente o programa deve
gerar todas as segundas componentes. Devemos ter, portanto, uma estrutura de repetio para gerar as
primeiras componentes e uma outra, vinculada a cada valor da primeira componente, para gerar as segundas
componentes.
/*Programa para gerar um produto cartesiano*/
#include <stdio.h>
main()
{
int n, i, j;
printf("Digite o numero de elementos do conjunto: ");
scanf("%d", &n);
printf("{");
for (i = 1; i <= n; i = i + 1)
for (j = 1; j <= n; j = j + 1)
printf("(%d, %d), ", i, j);
printf("}");
}
5. interessante observar que a varivel de controle da estrutura interna pode depender da varivel de
controle da estrutura externa. Por exemplo, se ao invs dos pares ordenados, quisssemos os subconjuntos do
conjunto A com dois elementos, o programa no deveria exibir o subconjunto {1, 1}, que possui um s
elemento, e deveria exibir apenas um dos subconjuntos {1, 2} e {2, 1} j que eles so iguais. Isto pode ser
obtido inicializando j com uma unidade maior do que o valor de i.
/*Programa para gerar um conjunto de subconjuntos de um conjunto*/
#include <stdio.h>
main()
{
int n, i, j;
printf("Digite o numero de elementos do conjunto: ");
scanf("%d", &n);
printf("{");
for (i = 1; i <= n; i = i + 1)
for (j = i + 1; j <= n; j = j + 1)
printf("{%d, %d}, ", i, j);
printf("}");
}
6. Seja um programa para o clculo da mdia de uma dada quantidade de nmeros. Na seo 1.5
discutimos um algoritmo para determinar a mdia de 10.000 nmeros dados. Na ocasio discutimos que
utilizaramos uma nica varivel para receber os nmeros sendo que um valor subsequente s seria solicitado
depois que o anterior fosse "processado". A diferena agora que a quantidade de nmeros ser um dado de
entrada, o que torna o programa de aplicao mais variada. Como a quantidade de nmeros ser dada, pode-
se utilizar uma estrutura for para receber e somar os nmeros.
/*Programa para calcular a media de n numeros, n dado*/
#include <stdio.h>
main()
{
int n, i;
float Num, Soma, Media;
Soma = 0;
printf("Digite o numero de elementos: ");
scanf("%d", &n);
printf("\n Digite os elementos:");
for (i = 1; i <= n; i = i + 1)
{
scanf("%f", &Num);
Soma = Soma + Num;
}
Media = Soma/n;
printf("Media = %f", Media);
}
7. O exemplo acima tem o inconveniente de que sua execuo exige que se saiba anteriormente a
quantidade de nmeros e isto no ocorre na maioria dos casos. Vejamos ento um programa para determinar
a mdia de uma relao de nmeros dados, sem que se conhea previamente a quantidade deles. Neste caso,
no devemos utilizar o comando for, pois no sabemos o nmero de repeties! Assim, o comando while
deve ser utilizado; porm, uma pergunta deve ser formulada: qual a expresso lgica que controlar a
estrutura? A soluo "acrescentar" relao um valor sabidamente diferente dos valores da relao e
utilizar este valor para controlar a repetio. Este valor conhecido como flag. Como dito logo acima, deve-
se ter certeza que o flag no consta da relao. Isto no complicado, pois ao se escrever um programa se
tem conhecimento de que valores o programa vai manipular e a escolha do flag fica facilitada. Por exemplo,
se o programa vai manipular nmeros positivos pode-se usar -1 para o flag. Alm do flag, o programa
necessita de uma varivel (no caso Cont de contador) que determine a quantidade de nmeros da relao,
pois este valor ser utilizado no clculo da mdia.
/*Programa para calcular a media de uma relacao de numeros*/
#include <stdio.h>
main()
{
int Cont;
float Num, Soma, Media;
Soma = 0;
printf("\n Digite os elementos(-1 para encerrar):");
scanf("%d", &Num);
Cont = 0;
while (Num != -1)
{
Soma = Soma + Num;
Cont = Cont + 1;
scanf("%f", &Num);
}
Media = Soma/Cont;
printf("Media = %f", Media);
}
8. Na seo 1.6 apresentamos o algoritmo de Euclides para a determinao do mximo divisor comum
de dois nmeros dados. Para relembrar, vejamos como calcular o mximo divisor comum de 204 e 84.
2 2 3
204 84 36 12
O algoritmo o seguinte: divide-se 204 por 84 obtendo-se resto 36; a partir da repete-se divises at
que o resto seja zero, sendo o dividendo da diviso atual o divisor da diviso anterior e o divisor da diviso
atual o resto da diviso anterior. O ltimo divisor o mximo divisor procurado.
Escrever este algoritmo numa linguagem de programao muito simples, pois uma estrutura de
repetio e comandos de atribuio permitem que se obtenha facilmente a sequncia de divises desejadas,
atualizando o dividendo, o divisor e o resto.
/*Programa para determinar o mximo divisor comum de dois nmeros positivos*/
#include <stdio.h>
main()
{
int x, y, Dividendo, Divisor, Mdc, Resto;
printf("Digite os dois numeros \n");
scanf("%d %d", &x, &y);
Dividendo = x;
Divisor = y;
Resto = Dividendo % Divisor;
while (Resto != 0)
{
Dividendo = Divisor;
Divisor = Resto;
Resto = Dividendo % Divisor;
}
Mdc = Dividendo;
printf("mdc(%d, %d) = %d \n", x, y, Mdc);
}
Note a necessidade da utilizao das variveis Dividendo e Divisor. Alm de facilitarem a
compreenso do algoritmo, elas so utilizadas no processamento e tero seus contedos alterados durante a
execuo do programa. Se usssemos as variveis x e y, os valores dos dados de entrada seriam perdidos o
que, evidentemente, no deve ocorrer. No captulo 5, quando estudarmos funes, estas variveis tero outra
conotao.
primeira vista, o programa deveria inicialmente determinar o maior dos nmeros x e y,
armazenando-o em a. O quadro seguinte mostra que isto no necessrio, apresentando a simulao da
execuo do programa para x = 68 e y = 148.
x y a b Resto Mdc
68 148 68 148 68
148 68 12
68 12 8
12 8 4
8 4 0
4
9. Um outro algoritmo matemtico cuja implementao numa linguagem de programao apresenta
um bom exemplo do uso de estruturas de repetio o algoritmo para a determinao do mnimo mltiplo
comum (mmc) de dois nmeros dados. Como indica a prpria denominao, o mnimo mltiplo comum de
dois nmeros o menor nmero que divisvel pelos dois nmeros. A matemtica prova que o mmc de dois
nmeros o produto dos divisores primos dos dois nmeros, comuns ou no, ambos com as suas
multiplicidades. Para se obter os divisores primos, realiza-se divises sucessivas pelos primos que so
divisores de pelo menos um dos nmeros.
A tabela seguinte mostra o clculo do mnimo mltiplo comum dos nmeros 360 e 420, como nos
ensinado no ensino fundamental.
360, 4202
180, 2102
90, 1052
45, 1053
15, 353
5, 355
1, 77
1, 1MMC = 2*2*2*3*3*5*7 = 2 520
Observe que, quando um divisor primo encontrado, repete-se a diviso, com o quociente no lugar do
dividendo at se obter um nmero que no mltiplo daquele divisor. A, incrementa-se o tal divisor. Isto
feito at que ambos os quocientes sejam iguais a 1. Temos o seguinte programa.
/*Programa para determinar o minimo multiplo comum de dois numeros positivos*/
#include <stdio.h>
main()
{
int x, y, d, a, b, i, Mmc;
printf("Digite os dois numeros \n");
scanf("%d %d", &x, &y);
a = x;
b = y;
Mmc = 1;
i = 2;
while ((a != 1) || (b != 1))
{
while ((a % i == 0) || (b % i == 0))
{
if (a % i == 0)
a = a/i;
if (b % i == 0)
b = b/i;
Mmc = Mmc * i;
}
i = i + 1;
}
printf("mmc(%d, %d) = %d \n", x, y, Mmc);
}
10. A questo do mnimo mltiplo comum muito interessante como exemplo para a aprendizagem de
programao pelo fato de que podemos apresentar um outro algoritmo de compreenso bem mais simples
que o anterior. A ideia a seguinte: x, 2x, 3x, etc. so mltiplos de x. Para se obter o mnimo mltiplo
comum basta que se tome o primeiro destes nmeros que seja mltiplo tambm de y.
/*Programa para determinar o mnimo mltiplo comum de dois nmeros positivos*/
#include <stdio.h>
main()
{
int x, y, i, Mmc;
printf("Digite os dois numeros \n");
scanf("%d %d", &x, &y);
Mmc = x;
while (Mmc % y != 0)
Mmc = Mmc + x;
printf("mmc(%d, %d) = %d \n", x, y, Mmc);
}
4.7 Exerccios propostos
1. Mostre a configurao da tela aps a execuo do programa
#include <stdio.h>
main()
{
int i, a, q, Termo;
for (i = 5; i > 0; i = i - 1)
{
a = i;
q = 3;
Termo = a;
while (Termo <= 9 * a)
{
printf("%d \n", Termo);
Termo = Termo * q;
}
}
}
2. Escreva um programa que determine a soma dos quadrados dos n primeiros nmeros naturais, n
dado.
3. Escreva um programa para calcular a soma dos n primeiros termos das sequncias abaixo, n dado.
a)
1
2
3
5
5
8
, , , ...

_
,

b) 1
1
2
1
3
1
4
, , , , ...

_
,

4. O exemplo 10 da seo anterior apresentava uma soluo para a questo do mnimo mltiplo comum
de simples compreenso. Um problema que esta soluo possui que se o primeiro valor digitado fosse
muito menor do que o segundo, o nmero de repeties necessrias para se chegar ao mmc seria muito
grande. Refaa o exemplo, tomando o maior dos nmeros dados como base do raciocnio ali utilizado.
5. Um nmero inteiro dito perfeito se o dobro dele igual soma de todos os seus divisores. Por
exemplo, como os divisores de 6 so 1, 2, 3 e 6 e 1 + 2 + 3 + 6 = 12, 6 perfeito. A matemtica ainda no
sabe se a quantidade de nmeros perfeitos ou no finita. Escreva um programa que liste todos os nmeros
perfeitos menores que um inteiro n dado.
6. O nmero 3.025 possui a seguinte caracterstica: 30 + 25 = 55 e 55
2
= 3 025. Escreva um programa
que escreva todos os nmeros com quatro algarismos que possuem a citada caracterstica.
7. Escreva um programa que escreva todos os pares de nmeros de dois algarismos que apresentam a
seguinte propriedade: o produto dos nmeros no se altera se os dgitos so invertidos. Por exemplo, 93x13 =
39x31 = 1.209.
8. Escreva um programa para determinar o nmero de algarismos de um nmero inteiro positivo dado.
9. Um nmero inteiro positivo dito semiprimo se ele igual ao produto de dois nmeros primos. Por
exemplo, 15 semiprimo pois 15 = 3 x 5; 9 semiprimo pois 9 = 3 x 3; 20 no semiprimo pois 20 = 2 x 10
e 10 no primo. Os nmeros semiprimos so fundamentais para o sistema de criptografia RSA {Evaristo, J,
2002]. Escreva um programa que verifique se um inteiro dado semiprimo.
10. Quando um nmero no semiprimo, a Matemtica prova que ele pode ser escrito de maneira
nica como um produto de potncias de nmeros primos distintos. Este produto chamado de decomposio
em fatores primos do nmero e os expoentes so chamados de multiplicidade do primo respectivo. Por
exemplo, 360 = 2
3
x3
2
x5. Escreva um programa que obtenha a decomposio em fatores primos de um inteiro
dado.
11. Escreva um programa que transforme o computador numa urna eletrnica para eleio, em
segundo turno, para presidente de um certo pas, s quais concorrem os candidatos 83-Alibab e 93-
Alcapone. Cada voto deve ser dado pelo nmero do candidato, permitindo-se ainda o voto 00 para voto em
branco. Qualquer voto diferente dos j citados considerado nulo; em qualquer situao, o eleitor deve ser
consultado quanto confirmao do seu voto. No final da eleio o programa deve emitir um relatrio
contendo a votao de cada candidato, a quantidade votos em branco, a quantidade de votos nulos e o
candidato eleito.
12. A sequncia de Fibbonaci a sequncia (1, 1, 2, 3, 5, 8, 13, ...) definida por
a
se n ou n
a a se n
n
n n


+ >

'

1 1 2
2
1 2
,
,

Escreva um programa que determine o n-simo termo desta sequncia, n dado.
13. A srie harmnica S
n
+ + + + + 1
1
2
1
3
1
... ... divergente. Isto significa que dado qualquer real k
existe n
0
tal que 1
1
2
1
3
1
0
+ + + + > ...
n
k . Escreva um programa que dado um real k determine o menor
inteiro n
0
tal que S > k. Por exemplo se k = 2, o programa deve fornecer n
0
= 4, pois
1
1
2
1
3
1
4
2 083 + + + , .... e 1
1
2
1
3
18333 + + , ....
14. Dois nmeros inteiros so ditos amigos se a soma dos divisores de cada um deles (menores que
eles) igual ao outro. Por exemplo, os divisores de 220 so 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 e 110 e 1 + 2 + 4
+ 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284 e os divisores de 284 so 1, 2, 4, 71 e 142 e 1 + 2 + 4 + 71 +
142 = 220. Escreva um programa que determine todos os pares de inteiros amigos menores que um inteiro
dado.
15. Escreva um programa que escreva todos os subconjuntos com trs elementos do conjunto {1, 2, 3,
..., n}, n dado.
16. Um inteiro positivo x dito uma potncia prima se existem dois inteiros positivos p e k, com p
primo, tais que x = p
k
. Escreva uma funo que receba um inteiro e verifique se ele uma potncia prima.
17. Um inteiro positivo x dito uma potncia perfeita de base z e expoente y se existem dois inteiros
positivos z e y tais que x = z
y
. Escreva uma funo que receba um inteiro e verifique se ele uma potncia
perfeita.
Observao
Propostas de solues dos exerccios propostos podem ser solicitadas atravs de mensagem
eletrnica para jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio
abaixo devidamente preenchido.
Nome Categoria
1
Instituio
2
Curso
2
Cidade/Estado
1
Categoria: docente, estudante, autodidata
2
Se docente ou estudante

Você também pode gostar