Você está na página 1de 25

MC102 Algoritmos e Programao

Turma IJ
Professor: Rafael Saracchini
Respostas da Lista de Exerccios II Assunto: Estruturas de Controle
1)
Observaes sobre o exerccio:
A resoluo dos exerccios ser dividida em duas etapas: Projeto do programa e
Implementao. Embora a resposta do exerccio seja apenas o cdigo- fonte do programa
estas etapas serviro para ilustrar como um programa deve ser elaborado passo- a- passo.
a) Dados trs nmeros inteiros digitados pelo usurio diga qual o maior e o menor
entre eles
Projeto do programa:
Este programa pode ser dividido nas seguintes etapas
Ler os trs nmeros
Comparar nmeros lidos e descobrir o maior
Idem para descobrir o menor
Imprimir o maior e o menor nmero
Implementao:
a)Ler os trs nmeros
Para ler os 3 nmeros , basta declar- los e utilizar a funo scanf para efetuar a leitura do
teclado
#include <stdio.h>
int main(void){
//declarao e leitura dos nmeros
int a,b,c;
scanf(%d %d %d ,&a,&b,&c);
return 0;
}
b)Comparar nmeros lidos e descobrir o maior
O valor do maior poderia ser obtido ordenando- se os trs nmeros , porm isto uma
tarefa difcil. Uma maneira mais simples inicialmente escolher um numero como maior
(digamos, a varivel a), armazen- lo em uma varivel e depois comparar com os outros dois
sucessivamente. Se em alguma dessas comparaes o suposto maior nmero for menor que
o comparado, atualizamos o valor da varivel maior.
Para implementar esta etapa precisamos ento declarar o varivel maior, efetuar as
comparaes necessrias. Caso alguma comparao seja verdadeira o valor da varivel
maior dever ser atualizado com o novo maior valor.
#include <stdio.h>
int main(void){
//declarao e leitura dos nmeros
int a,b,c;
//declarao da varivel maior
int maior;
scanf(%d %d %d ,&a,&b,&c);
//escolhemos um possvel maior valor
maior = a;
//comparamos maior com b
if( maior < b){
//suposto maior menor que b ento b o possvel maior
maior = b;
}
//o mesmo raciocnio vlido para c
if(maior < c){
maior = c;
}
return 0;
}
c)Descobrir o menor nmero
O mesmo raciocnio utilizado para descobrir o maior nmero pode ser utilizado para
descobrir o menor nmero, s que testamos se o suposto menor nmero maior que os
nmeros restantes... caso a comparao seja verdadeira atualizamos a varivel menor.
#include <stdio.h>
int main(void){
int a,b,c;
//declarao da varivel maior e menor
int maior,menor;
scanf(%d %d %d ,&a,&b,&c);
maior = a;
if( maior < b){
maior = b;
}
if(maior < c){
maior = c;
}
//supomos que o menor nmero a
menor = a;
//comparamos com b para verificar se a afirmao anterior vlida
if(menor > b){
//b menor que o suposto menor, logo b o menor
menor = b;
}
if(menor > c){
// c menor que o suposto menor, logo c o menor
menor = c;
}
return 0;
}
d)Imprimi r o menor e o maior nmero
Uma vez que descobrimos ambos os valores e atribumos os mesmos as suas respectivas
variveis , basta chamar o comando printf para imprimi r o valor das variveis.
#include <stdio.h>
int main(void){
int a,b,c;
int maior,menor;
scanf(%d %d %d ,&a,&b,&c);
maior = a;
if( maior < b){
maior = b;
}
if(maior < c){
maior = c;
}
menor = a;
if(menor > b){
menor = b;
}
if(menor > c){
menor = c;
}
//imprimimos o valor do maior e menor valor
printf(O maior valor e %d e o menor %d,maior,menor);
return 0;
}
b)Dados os nmero n e m (digitados pelo usurio), escreva a tabuada de n de 1 at m.
Restrinja a entrada de dados de maneira que caso seja digitado um valor menor que 2
e maior que 9 seja exibida uma mensagem de aviso e no calcule a tabuada.
Projeto de programa:
Calcular uma tabuada de uma operao (por exemplo: multiplicao) de um nmero n de 1
at m o equivalente calcular os seguintes valores:
n x 1
n x 2
n x 3
...
n x m
Ento as tarefas a serem implementadas no programa so:
Ler n e m
Calcular o valor de cada elemento da tabuada de 1 at m e imprim - lo
restringir a entrada de dados de maneira que a tabuada s seja calculada se n e m
estiverem entre 2 e 9 (incluindo 2 e 9).
Implementao:
a) Ler n e m
Para implementar esta etapa basta declarar as variveis e utilizar o scanf para obter os
dados do usurio.
#include <stdio.h>
int main(void){
//declarao e leitura de n e m
int n,m;
scanf(%d %d ,&n,&m);
return 0;
}
b) Calcular o valor de cada elemento da tabuada de 1 at m e imprim - lo
No podemos fazer no cdigo o clculo de cada expresso direto no cdigo pois no temos
um m determinado ! Dada esta situao devemos ento utilizar uma estrutura de controle
de repetio como while, do- while ou for.
A primeira coisa ser feita analisar qual das 3 estruturas de controle sero utilizadas.
while recomendado quando queremos repetir uma operao 0 ou mais vezes e no
podemos precisar exatamente quando a repetio termina. Ex: Calculo de logaritmo,
converso de bases
do- while segue o mesmo princpio do while, mas queremos que as operaes a serem
repetidas sejam executadas ao menos uma vez. Ex: leitura de seqncia de numeros at
usurio digitar 1, solicitao de senha.
for mais utilizado quando sabemos exatamente quantas vezes as operaes sero
repetidas. Ex: fatorial, tabuada
Como podemos precisar que repetiremos m vezes o clculo dos valores da tabuada,
utilizaremos o for.
Uma vez escolhida a estrutura de controle , teremos que ver como adapt- la ao nosso
programa... a cada repetio vemos que o valor do multiplicando vai sendo incrementado e
que a repetio para ao chegar ao valor de m. Como o valor do multiplicando varia a cada
iterao, ento devemos declar- lo com uma varivel e alterar seu valor a cada rodada.
Sabemos tambm que o multipl icando sempre inicia com valor 1. Com isto podemos
implementar o nosso for.
#include <stdio.h>
int main(void){
int n,m;
// declaracao do multiplicando e do valor da operao em cada
etapa
int mt,valor;
scanf(%d %d ,&n,&m);
/*
Na estrutura do for temos j a inicializao, teste e atualizao
da varivel de controle, no caso a varivel mt
*/
for(mt = 1; mt <= m; mt = mt+1){
//aqui o valor da operao a ser calculada
valor = n*mt;
// e claro ns imprimimos o mesmo
printf(%d x %d = %d\n,n,mt,valor);
}
return 0;
}
c) Restringir a entrada de dados de maneira que a tabuada s seja calculada se n e m
estiverem entre 2 e 9 (incluindo 2 e 9).
O programa como est no restringe a entrada de dados do usurio. Para tal, teremos que
fazer uso de uma estrutura de controle condicional e com ela tomarmos uma deciso de
acordo com o valor digitado.
As seguintes decises precisam ser tomadas pelo programa:
Se n e m estiverem entre 2 e 9 , ou seja 2 n 9 e 2 m 9, o programa deve
calcular a tabuada
Caso contrrio, o programa dever exibir uma mensagem de aviso
Temos ento que adaptar essas decises a uma ou mais estruturas de controle, no caso,
apenas um if bastar.
Para a construo do IF precisamos determinar a expresso que resulte o valor Verdadeiro
caso n e m atendam as condies especificadas acima e Falso caso contrrio. A expresso
que avalia isso :
( (n>=2)&&(n <=9) ) && ( (m >=2) && (m<= 9))
Esta umaexpresso composta, o primeiro grupamento ((n>=2)&&(n <=9) ) possui valor
Verdadeiro se n respeitar a definio pedida assim como o segundo possui valor Verdadeiro
se m respeita a definio dada. Caso n ou m tenham valor fora do conjunto [2,3,4..9] o &&
lgico entre os dois grupamentos garante que a expresso ter valor Falso e ter valor
verdadeiro apenas se as duas variveis estiverem dentro da faixa especificada.
Uma vez pronta a expresso podemos ajustar nosso programa para atender a ultima etapa.
#include <stdio.h>
int main(void){
int n,m;
int mt,valor;
scanf(%d %d ,&n,&m);
//testamos se n e m esto na faixa especificada
if( ((n>=2) && (n<=9)) && ((m >=2) && (m <=9)) ){
//n e m esto na faixa especificada !
for(mt = 1; mt <= m; mt = mt+1){
valor = n*mt;
printf(%d x %d = %d\n,n,mt,valor);
}
}else{
// n e m fora da faixa permitida
printf(Valores fora da faixa permitida !\n);
}
return 0;
}
c)Dados os nmeros n e m, escreva todos os nmeros entre 1 a 200 que sejam
divisveis por n mas no por m.
Projeto do de programa :
Este programa consiste em listar uma seqncia de nmeros de 1 a 200, s que antes de
impri mir um nmero em particular devemos verificar se o mesmo atende a restrio pedida.
Tarefas a serem implementadas
Obter o valor de n e m
Percorrer todos os nmeros de 1 a 200
Analisar para cada nmero percorrido se o mesmo pode ser impresso na tela
Implementao:
Ler nmeros algo bem simples , a partir de agora essa etapa no ser mais abordada.
a)Percorrer todos os nmeros de 1 a 200
Percorrer todos os nmeros dentro de um intervalo restrito e bem definido uma tarefa que
pode ser feita facilmente com for ou while. O que precisamos a mais um contador para
regular a quantidade de repeties.
#include <stdio.h>
int main(void){
int n,m;
//declarao de um contador
int cont;
//leitura de n e m;
scanf(%d %d ,&n,&m);
//nmeros so percorridos pelo contador
for(cont = 1; cont <= 200; cont = cont+1){
/*
aqui deve ser tomada a deciso de imprimir um nmero ou
no
*/
}
return 0;
}
b)Analisar para cada nmero percorrido se o mesmo pode ser impresso na tela
Uma tomada de deciso deve ser feita atravs de uma estrutura de controle condicional, no
caso a mais adequada o IF. Para poder utilizar o IF devemos ver quantos sero necessrio
e qual expresso avalia Verdadeiro ou Falso diante da anlise pedida.
Temos duas situaes:
Se o nmero dor divisvel por n e no por m o nmero impresso
Seno nenhuma atitude tomada
Sabendo disso fcil ver que apenas um IF necessrio, sem necessitar da construo de
um ELSEpois se a condio de teste falhar nenhum comando executado. Resta determinar
a expresso.
Sabemos que quando um nmero a divisvel por b ento a%b sempre 0, qualquer valor
distinto indica que a no divisvel por b. Dado isto construmos nossa expresso para
determinar de um dado nmero x divisvel por n mas no por m.
(x%n == 0) && (x%m != 0)
Note que esse nmero a ser avaliado no nosso programa o prprio contador (varivel
cont), logo substumos x por cont.
Nosso programa fica ento assim:
#include <stdio.h>
int main(void){
int n,m;
int cont;
scanf(%d %d ,&n,&m);
for(cont = 1; cont <= 200; cont = cont+1){
if( (cont%n == 0) && (cont%m != 0) ){
//o nmero divisvel por n mas no por m
printf(%d\n,cont);
}
}
return 0;
}
d)Calcule o logaritmo mais prximo de 10 de um dado nmero n.
Esta questo est um tanto mal formulada em relao ao que eu pretendia pedir. O
enunciado correto deveria ser:
Calcule x igual ao logaritmo mais prximo de 10 de um dado nmero n onde x > n.
Esclarecido isso vamos resolver a questo.
Projeto de programa:
A grosso modo um logaritmo de um nmero pode ser calculado contando- se quantas
divises inteiras podemos fazer at que o resultado da diviso seja 0.
Logo nosso programa se resume a:
Obter o nmero n
Dividir n por 10 at que o resultado da diviso inteira seja 0
Contar quantas divises foram feitas
Note que o que este programa faz no fundo contar quantos dgitos possui um nmero
positivo.
Implementao:
Vamos construir o bsico do programa:
#include <stdio.h>
int main(void){
int n,x;
scanf(%d ,&n);
printf(O logaritmo maior mais proximo e %d\n,x);
return 0;
}
a)Dividir n por 10 at que o resultado da diviso inteira seja 0
Primeiro passo definir que estrutura de controle utilizar... desta vez no sabemos at
quando iremos dividir n ento de cara FOR no o mais recomendado (embora seja
perfeitamente possvel utiliz- lo). Temos que decidir ento se WHILE ou DO- WHILE mais
adequado... Note que pelo menos uma diviso teremos que fazer , mesmo que o nmero
seja 0. Dado isso DO- WHILE facilitar mais a construo de nosso programa j que ele
executa uma operao a ser repetida pelo menos uma vez.
Logicamente a operao a ser repetida de dividir n por 10. A condio de parada que o
resultado da diviso seja 0, logo a operao de diviso deve ser repetida enquanto o
resultado da diviso seja diferente de 0 (note que while traduzido significa enquanto)
#include <stdio.h>
int main(void){
int n,x;
//declaramos uma variavel que armazena o resultado da diviso
int r;
scanf(%d ,&n);
//inicialmente r deve comear com o valor de n
r = n;
do{
/*
dividimos o resultado da ultima diviso por 10
e armazenamos o resultado
*/
r = r/10;
/*
enquanto r no atingir o valor 0 devemos continuar
dividindo-o
*/
}while(r != 0);
printf(O logaritmo maior mais proximo e %d\n,x);
return 0;
}
b)Contar quantas divises foram feitas
Esta etapa bem fcil. Precisamos de um contador, que na verdade o resultado desejado,
representado pela varivel x. A cada diviso aumentamos o valor do contador em 1.
#include <stdio.h>
int main(void){
int n,x;
int r;
scanf(%d ,&n);
//inicializamos o contador com 0 (no foi feita divis
x = 0;
r = n;
do{
r = r/10;
//a cada diviso incrementamos o contador
x = x + 1;
}while(r != 0);
//Agora sim h sentido em imprimir o valor de x
printf(O logaritmo maior mais proximo e %d\n,x);
return 0;
}
e)Dado um dgito, escrever o mesmo em cdigo Morse
Projeto do programa:
Este programa simples. Dado um dgito especfico impri mir o seu cdigo Morse associado.
A questo decidir mesmo qual estrutura de controle condicional se adequa mais a
situao.
Implementao:
O programa pode ser feito tanto com um grupo de IFs quanto um SWITCH s. Para fins
ilustrativos o programa ser feito com ambas estruturas.
Como neste programa temos uma grande quantidade de casos particulares em torno de um
mesmo valor, SWITCH o mais recomendado. Utilizando- o o programa adquire este
aspecto:
#include <stdio.h>
int main(void){
int n;
//declaramos uma variavel que armazena o dgito
scanf(%d ,&n);
switch(n){
case 0: printf(_ _ _ _ _);
break;
case 1: printf(. _ _ _ _);
break;
case 2: printf(. . _ _ _);
break;
case 3: printf(. . . _ _);
break;
case 4: printf(. . . . _);
break;
case 5: printf(. . . . .);
break;
case 6: printf(_ . . . .);
break;
case 7: printf(_ _ . . .);
break;
case 8: printf(_ _ _ . .);
break;
case 9: printf(_ _ _ _ .);
break;
default:
//caso em que n possui mais de um dgito!
printf(A entrada deve ser composta de 1 digito !\n);
break;
};
return 0;
}
Repare que o scanf de um nmero no impede que digitemos mais de um dgito nem
nmeros negativos... neste caso devemos informar o usurio da situao.
O programa tambm pode ser feito com IFs e ELSEsencadeados... mais trabalhoso fazer o
mesmo assim, mas a funcionalidade ser a mesma.Confira na resposta abaixo:
#include <stdio.h>
int main(void){
int n;
//declaramos uma variavel que armazena o dgito
scanf(%d ,&n);
if( n == 0){
printf(_ _ _ _ _);
}else if( n == 1){
printf(. _ _ _ _);
}else if( n == 2){
printf(. . _ _ _);
}else if( n == 3){
printf(. . . _ _);
}else if( n == 4){
printf(. . . . _);
}else if( n == 5){
printf(. . . . .);
}else if( n == 6){
printf(_ . . . .);
}else if( n == 7){
printf(_ _ . . .);
}else if( n == 8){
printf(_ _ _ . .);
}else if( n == 9){
printf(_ _ _ _ .);
}else{
//caso em que n possui mais de um dgito!
printf(A entrada deve ser composta de 1 digito !\n);
}
return 0;
}
f)Dado um nmero inteiro, escrever o mesmo em cdigo Morse. O cdigo deve ser
fornecido na mesma ordem que os caracteres digitados.
Projeto do programa:
Este realmente no um programa trivial. Temos que extrair dgito a dgito do nmero, do
mais significativo para o menos significativo, e para cada um deles impri mir o cdigo Morse
correspondente.
Tarefas do programa
Obter o nmero a ser impresso
Extrair dgito a dgito do nmero, do mais significativo ao menos significativo
Imprimir o cdigo correspondente para cada dgito extrado
Destas etapas, a mais difcil de longe a segunda.
Para facilitar o entendimento e fazer um cdigo mais limpo e fcil de entender utilizaremos
funes e procedimentos na construo do programa.
Implementao:
Vamos fazer a parte bsica do programa:
#include <stdio.h>
int main(void){
int n;
scanf(%d ,&n);
return 0;
}
a)Extrair dgito a dgito do nmero, do mais significativo ao menos significativo
Vamos analisar um nmero qualquer, digamos o nmero 145.
fcil ver que se queremos extrair o primeiro dgito por meio de uma conta basta fazer a
diviso inteira de 145 por 100.Logo:
145/100 = 1
Porm queremos tambm obter o que restou do nmero (no caso 45) , pois o prximo
dgito necessrio para que este seja impresso tambm. Para fazermos isso basta utilizar o
operador %. Observe:
145%100 = 45
Vamos repetir o mesmo tratamento para o nmero 45, mas trabalhando com 10 em vez de
100:
45/10 = 4 (dgito mais significativo)
45%10 = 5 ( dgitos restantes )
Repetindo o caso para 5 temos:
5/1 = 5
5%1 = 0
Ou seja dado um nmero n qualquer precisamos:
Descobrir qual a potncia p de 10 mais prxima de n tal que p <= n
Dividir n por p e assim obter o primeiro dgito
Calcular o resto da diviso de n por p para obter os dgitos restantes
repetir o procedimento para os dgitos restantes at que no reste mais nenhum
Note que a potncia p de 10 mais prxima de um nmero n tal que p <= n exatamente a
quantidade de dgitos de n menos 1 . E que no exerccio da letra d foi feito um programa
que faz esta conta. Em vez de copiarmos diretamente o cdigo- fonte e inserir no meio do
main, vamos fazer isto de maneira mais prtica... atravs de uma funo.
Uma funo um subprograma que dado um certo conjunto de parmetros de entrada, o
mesmo retorna um valor de acordo com o conjunto de parmetros. Voc pode imaginar isto
como se fosse uma funo matemtica.
Quando colocamos uma funo no meio de uma expresso o subprograma
Ex.:

A funo sqrt tem como parmetro de entrada um nmero real R e avaliada em uma
expresso como a raiz quadrada de R. Veja s a avaliao desta expresso:
(4 + sqrt(81.0))/2.0 ===> sqrt(81.0) avaliada como 9.0
(4 + 9.0)/2.0
13.0/2.0
7.5
Relembrando a declarao de uma funo:
tipo NomeDaFuno (Listagem de Parmetros de Entrada) {
comandos
return ValorDaFuno ;
}
Ex:
a funo abaixo calcula a mdia aritmtica de 3 nmeros reais passados como parmetro
de entrada (declarados como a,b e c), O valor retornado peloa funo do tipo float (real,
ou ponto flutuante).
float media3(float a, float b, float c){
return (a + b + c)/3.0 ;
}
Portanto, vamos criar uma funo que dado um nmero inteiro retorna a quantidade de
dgitos que ele possui reaproveitando o cdigo do exerccio anterior.
int QtdDigitos(int n){
int x;
//inicializamos o contador com 0
x = 0;
do{
n = n/10;
//a cada diviso incrementamos o contador
x = x + 1;
}while(n != 0);
return x;
}
Quando colocamos QtdDigitos(i) dentro de uma expresso , o subprograma ser executado
com a varivel n inicializada com o valor de i e aps seu trmino ser avaliado com o valor
de x do tipo inteiro.
Note que essas variveis n e x declaradas dentro dele s existem dentro do bloco da funo
(trecho de cdigo entre chaves) e so completamente independentes de quaisquer varaveis
declaradas dentro de outros blocos de funo ou do main. Inclusive podemos declarar a
varivel n e x dentro do bloco do main sem quaisquer restries , isto o n declarado
dentro de uma funo no o mesmo n declarado dentro do bloco do main.
Voltando ao programa...
J sabemos qual o expoente da potncia de 10, mas precisamos do valor de 10 elevado
a este expoente. Vamos ento construir uma funo que dado um nmero positivo e retorna
10
e
.
int potencia10(int e){
int r,cont;
r = 1;
for(cont = 1; cont <= e; cont++){
// enquanto contador no for igual a e multiplicamos r por 10
r = r*10;
}
return r;
}
Agora resta apenas decidir qual a estrutura de repetio que vamos utilizar. Sabemos que
se um nmero tem t dgitos ento vamos repetir a operao t vezes. Podemos utilizar o FOR
ou WHILE. Desta vez vamos utilizar o WHILE.
O programa ento ficar desta maneira
#include <stdio.h>
int QtdDigitos(int n){
int x;
x = 0;
do{
n = n/10;
x = x + 1;
}while(n != 0);
return x;
}
int potencia10(int e){
int r,cont;
r = 1;
for(cont = 1; cont <= e; cont++){
r = r*10;
}
return r;
}
int main(void){
int n,p,t,d;
scanf(%d ,&n);
//calculamos o total de dgitos do numero
t = QtdDigitos(n);
//enquanto houverem dgitos a serem extrados repetimos operao
while(t > 0){
//calculamos a potencia p
p = potencia10(t - 1);
//extramos o digito mais significativo
d = n/p;
//recuperamos o restante dos dgitos
n = n%p;
//diminumos um digito do total de dgitos
t = t - 1;
}
return 0;
}
b)Imprimi r o cdigo correspondente para cada dgito extrado
Esta a etapa final do programa. Note que j fizemos tambm um programa que dado um
dgito imprime o seu cdigo Morse. Podemos transformar este programa em um
subprograma tambm e adicionarmos ao nosso cdigo.
A questo que desta vez no faremos uma funo, e sim um procedimento. Um
procedimento um subprograma que dado seus parmetros de entrada, executa seu cdigo
sem avaliar nenhum valor, ou seja no possvel utiliz- lo no meio de uma expresso e sim
como um comando. Um bom exemplo disso o comando printf, o mesmo no retorna valor
algum e seu cdigo imprime na tela uma lista de parmetros dados.
A declarao de um procedimento similar a de uma funo, s que o tipo do mesmo
sempre void (que quer dizer vazio), o restante exatamente igual a uma funo.
Ex:
este procedimento imprime n asteriscos na tela dado um n qualquer;
void imprimeAsteriscos(int n){
int contador;
for(contador = 1; contador <= n; contador++){
printf(*);
}
}
Da mesma maneira vamos fazer isto com o programa que imprime o cdigo Morse de um
dgito.
void ImprimeMorse(int n){
switch(n){
case 0: printf(_ _ _ _ _);
break;
case 1: printf(. _ _ _ _);
break;
case 2: printf(. . _ _ _);
break;
case 3: printf(. . . _ _);
break;
case 4: printf(. . . . _);
break;
case 5: printf(. . . . .);
break;
case 6: printf(_ . . . .);
break;
case 7: printf(_ _ . . .);
break;
case 8: printf(_ _ _ . .);
break;
case 9: printf(_ _ _ _ .);
break;
default:
//caso em que n possui mais de um dgito!
printf(A entrada deve ser composta de 1 digito !\n);
break;
};
}
Se chamarmos ImprimeMorse(k) em qualquer trecho do nosso programa, ser impresso o
cdigo morse do dgito k. Uma vez com esse procedimento pronto basta chamar
ImprimeMorse dentro da repetio principal do programa para cada dgito obtido.
#include <stdio.h>
void ImprimeMorse(int n){
switch(n){
case 0: printf(_ _ _ _ _);
break;
case 1: printf(. _ _ _ _);
break;
case 2: printf(. . _ _ _);
break;
case 3: printf(. . . _ _);
break;
case 4: printf(. . . . _);
break;
case 5: printf(. . . . .);
break;
case 6: printf(_ . . . .);
break;
case 7: printf(_ _ . . .);
break;
case 8: printf(_ _ _ . .);
break;
case 9: printf(_ _ _ _ .);
break;
default:
//caso em que n possui mais de um dgito!
printf(A entrada deve ser composta de 1 digito !\n);
break;
};
}
int QtdDigitos(int n){
int x;
x = 0;
do{
n = n/10;
x = x + 1;
}while(n != 0);
return x;
}
int potencia10(int e){
int r,cont;
r = 1;
for(cont = 1; cont <= e; cont++){
r = r*10;
}
return r;
}
int main(void){
int n,p,t,d;
scanf(%d ,&n);
t = QtdDigitos(n);
while(t > 0){
p = potencia10(t - 1);
d = n/p;
n = n%p;
t = t - 1;
//imprimimos o dgito d extrado em Morse
ImprimeMorse(d);
/*
imprimimos um espao em branc
o para evitar que os cdigos
fiquem grudados
*/
printf( );
}
return 0;
}
Fazer este programa sem utilizar procedimentos e funes no mnimo , bem mais
trabalhoso.
g)Dado um nmero n, escreva um X formado por asteriscos. Permita que apenas
nmeros mpares sejam utilizados como entrada.
Projeto do Programa:
Em vez de pensarmos no X como uma figura s , podemos pensar que o programa traa
duas diagonais simultaneamente. Desenhar uma diagonal um problema bem mais
simples.
O programa pode ser dividido nas seguintes etapas:
ler o nmero
traar diagonal principal
traar diagonal secundria
restringir entrada de nmeros pares
Implementao:
Estrutura bsica do programa
int main(void){
int n;
scanf(%d ,&n);
return 0;
}
a)Traar a diagonal principal
Dado um nmero n, traar uma diagonal na tela com caracteres escrever n vezes uma
linha composta por n caracteres onde n- 1 caracteres brancos e um asterisco. Observe:
Para n = 3
*
*
*
Para n = 3 escrevemos 3 linhas de 3 caracteres onde o asterisco posicionado de acordo
com a posio da linha. Se for a primeira linha o asterisco entra na primeira posio, se for
a segunda, na segunda posio... a regra se repete para todas as linhas. Os caracteres
restantes so brancos.
Vendo isso vamos primeiro nos preocupar primeiro em desenhar uma linha. Dada a posio
l de uma linha desenh- la de acordo com a regra acima... isso pode ser feito com uma
estrutura de repetio. No caso a mais indicada o FOR.
for(cont = 1; cont <= n; cont ++){
if(cont == l){
printf(*);
}
else{
printf( );
}
}
printf(\n);
O que trecho de programa acima faz escrever uma linha de n caracteres, se a posio do
caracter escrito (representado pela varivel cont) for igual a posio l da linha escreve- se
um asterisco, se no for imprime- se um espao em branco. De qualquer maneira sempre se
escrevem n caracteres.
Resolvemos o problema de escrever uma linha, mas queremos escrever n linhas. Para isso
podemos fazer uso de mais uma repetio. Da mesma maneira utilizar FOR o mais
recomendado. Nesta repetio iremos variar o valor de l de 1 at n, colocando o for que
desenha a linha dentro dele.
Nosso programa fica assim
int main(void){
int n,l,cont;
scanf(%d ,&n);
for(l = 1; l <=n;l++){
//variamos l de 1 a n
for(cont = 1; cont <=n; cont ++){
//escrevemos n caracteres, se for o l-esimo caracter
//ento um asterisco
if(cont == l){
printf(*);
}
else{
//se for qualquer outro espao em branco
printf( );
}
}
//pulamos a linha aps escrever os n caracteres
printf(\n);
}
return 0;
}
b)Traar a diagonal secundria
O problema praticamente o mesmo de traar a diagonal principal, s a posio do
asterisco cai em uma posio diferente . Se a linha for a primeira o asterisco dever ser
desenhado na n- esima posio, na segunda linha na n- esima posio menos 1 at que na
n- esima linha o asterisco dever ser desenhado na 1 posio. Seguindo essa lgica , em
uma linha de posio l o asterisco dever ser desenhado na posio n- l +1 .
No iremos fazer outro grupo de FOR para imprimir a diagonal secundria pois em vez de
obtermos o X teramos duas diagonais uma embaixo da outra.
Colocar dois agrupamentos de for vai nos dar isso:
*
*
*
*
*
*
Queremos isso:
* *
*
* *
Podemos alterar a expresso do IF da repetio que desenha a linha de maneira que se a
posio a ser desenhada for do caracter da diagonal principal OU do caracter da diagonal
secundaria ento impri me- se um asterisco.
Alterando- se apenas a expresso do IF fazemos nosso programa desenhar um X.
int main(void){
int n,l,cont;
scanf(%d ,&n);
for(l = 1; l <=n;l++){
//variamos l de 1 a n
for(cont = 1; cont <=n; cont ++){
/*escrevemos n caracteres,
Se a posio for igual a l ento diagonal principal
se for igual a (n l + 1) d. secundaria
*/
if((cont == l ) || (cont == (n l +1 ))){
printf(*);
}
else{
//se for qualquer outro espao em branco
printf( );
}
}
//pulamos a linha aps escrever os n caracteres
printf(\n);
}
return 0;
}
c)Restringir a entrada de nmeros pares
Basta fazer um if com a expresso (n%2 == 0), pois j sabemos que o resto da diviso por 2
de nmeros pares sempre 0.
int main(void){
int n,l,cont;
scanf(%d ,&n);
if(n %2 == 0){
printf(Digite apenas numeros impares !);
}else{
for(l = 1; l <=n;l++){
//variamos l de 1 a n
for(cont = 1; cont <=n; cont ++){
/*escrevemos n caracteres,
Se a posio for igual a l ento diagonal principal
se for igual a (n l + 1) d. secundaria
*/
if((cont == l ) || (cont == (n l +1 ))){
printf(*);
}
else{
//se for qualquer outro espao em branco
printf( );
}
}
//pulamos a linha aps escrever os n caracteres
printf(\n);
}
}
return 0;
}
h)Escreva um programa um nmero imaginado pelo usurio entre 0 e n. Para cada
valor sugerido pelo programa como sendo o valor imaginado pelo usurio, o usurio
deve responder se o valor sugerido pelo programa igual, menor ou maior que o valor
imaginado. A execuo do programa deve terminar assim que o programa adivinhar
o valor imaginado pelo usurio.
Projeto do Programa:
O problema maior deste programa : como o programa vai chutar um valor ? E o que fazer
quando este valor no for igual ?
Este programa pode ser feito de vrias maneiras, uma delas a partir das respostas do
usurio definir qual um valor mximo e mnimo possvel e escolher sempre o valor que
est exatamente no meio deles. Se o valor chutado for maior que o nmero procurado ento
o novo valor mximo possvel o valor chutado, o mesmo princpio vale para o caso do
valor chutado ser menor.
Veja:
N = 1000;
(usurio pensou no nmero 128)
Pergunta do Sistema Valor mnimo Valor mximo Resposta do Usurio
O valor 500 ? 0 1000 500 maior
O valor 250 ? 0 500 250 maior
O valor 125 ? 0 250 125 menor
O valor 187 ? 125 250 187 maior
O valor 156 ? 125 187 156 maior
O valor 140 ? 125 156 140 maior
O valor 132 ? 125 140 132 maior
O valor 128 ? 125 132 128 igual
O valor do chute sempre (Valor Mnimo + Valor Mximo)/2 considerando a diviso inteira.
Caso utilizemos nmeros inteiros o programa sempre acerta o nmero em uma quantidade
limitada de tentativas... o mesmo no vale para nmeros reais, mesmo fazendo a diviso
real para alguns nmeros a quantidade mnima de chutes infinita ! Tente reproduzir este
mtodo para achar o nmero 18 com nmeros reais... Logo o programa ser obviamente
considerando que os nmeros envolvidos so sempre inteiros
Etapas do programa
Determinar valor mximo do chute inicial (n)
Determinar um chute inicial
Obter respostas do usurio at acertar
Determinar um novo chute baseado no que o usurio disse caso programa erre.
Implementao:
a)Determinar valor mximo do chute
Este passo simples, basta declarar n e ler a entrada do usurio.
#include <stdio.h>
int main(void){
int n;
scanf(%d,&n);
return 0;
}
b)Determinar um chute inicial
Como determinamos antes , o chute feito pelo programa sempre no meio dos valores
mnimo e mximo, logo:
#include <stdio.h>
int main(void){
int n,chute;
int maximo, minimo;
scanf(%d,&n);
maximo = n;
chute = (maximo + minimo)/2;
return 0;
}
c)Obter a respostas do usurio do usurio at acertar
Ler uma resposta do tipo 128 maior ou 200 menor desnecessariamente
complicado. Vamos definir que o usurio simplesmente digita >, < ou = para dar suas
respostas. Como estes so caracteres temos que utilizar uma varivel do tipo char para
efetuar sua leitura.
Outro detalhe que precisamos repetir esta obteno de respostas at que o usurio diga
que o valor chutado igual ao que ele pensou, logo precisamos de uma estrutura de
repetio. Como no mnimo uma pergunta feita ento escolheremos DO- WHILE.
#include <stdio.h>
int main(void){
int n,chute;
int maximo, minimo;
char resp;
char auxiliar;
scanf(%d,&n);
maximo = n;
minimo = 0;
//eliminamos o ENTER depois da leitura de N
scanf(%c,&auxiliar);
do{
chute = (maximo + minimo)/2;
printf(O valor e %d ?,chute);
scanf(%c,&resp);
scanf(%c,&auxiliar);
//enquanto resposta for diferente de = temos que continuar chutando
}while(resp != =);
return 0;
}
Se voc leu o cdigo deve estar se perguntando por que motivo obscuro tem um scanf de
uma varivel auxiliar que nem foi citada... o motivo disto que o usurio ao digitar sua
resposta vai escrever invariavelmente o caracter + ENTER. Acontece que ENTERtambm
um caracter ! Se deixarmos apenas um scanf o ENTERir ficar na memria do teclado e na
prxima rodada do DO- WHILE o scanf ir ler o ENTERprovocando o seguinte resultado:
Texto em verde: Sada do programa
Texto em vermelho: Entrada digitada pelo usurio
O valor 500?>ENTER
O valor 500?O valor 500?
OBS: O valor chutado no mudou pois no alteramos ainda os valores de mnimo e mximo
dentro da repetio !
Portanto este scanf extra permite que nos livremos do inconveniente do caracter ENTER.O
scanf aps a leitura de n tambm possui a mesma funo.
c)Determinar um novo chute baseado no que o usurio disse caso programa erre.
O programa errou seu chute quando o usurio digitou > ou <, neste caso o que
devemos fazer ajustar os valores do mximo ou do mnimo de acordo com a resposta
dada. A expresso que avalia o valor do chute no muda.
#include <stdio.h>
int main(void){
int n,chute;
int maximo, minimo;
char resp;
char auxiliar;
scanf(%d,&n);
maximo = n;
minimo = 0;
scanf(%c,&auxiliar);
do{
chute = (maximo + minimo)/2;
printf(O valor e %d ?,chute);
scanf(%c,&resp);
scanf(%c,&auxiliar);
if(resp == >){
maximo = chute;
} else if (resp == <){
minimo = chute;
}
}while(resp != =);
return 0;
}
2)
Observaes dobre o exerccio:
Nenhuma
a)
Erro:
O teste do for est incorreto. Num fatorial o loop deve rodar n vezes, afinal a
frmula de fatorial n! = 1*2*3.. n. Com a condio i != n sero feitas n- 1
repeties. Outro problema grave que se for inserido um nmero menor ou igual
a 0 programa entrar em loop infinito, j que i nunca chegara a um valor menor que
1.
a varivel i no foi declarada
o operao repetida r = r*1 sempre resulta 1, no importa quantas vezes seja
repetida, e este valor obviamente no fatorial de n.
Correo:
Basta trocar o teste i!=n para i <=n . Assim nosso loop estar executando
corretamente. Isso no resolve o problema do fatorial de nmeros negativos, mas
como esta funo s est definida para R
+
ento no o caso de se preocupar.
Declarar um i resolve o problema
trocar r = r*1 por r= r*i , desta maneira, como i varia de 1 a n a cada repetio,
teremos o fatorial calculado corretamente
b)
Erro:
Quando um nmero negativo lido o mesmo est entrando no clculo da mdia.
O clculo da mdia est sendo feito incorretamente. A expresso total = (total +
lido) /contador est incorreta em 2 pontos :
1) V1/1 + V2/2 + V3/3 + ... + Vn/n no a mdia aritmtica.
2) contador uma varivel inteira, logo a diviso efetuada ser inteira e portanto
incorreta para o clculo que desejamos.
Correo:
Antes de somar o valor lido ao total acumulado e incrementar o contador verificar
primeiro se ele um nmero negativo primeiro. Isto pode ser feito com um IF (lido >
0)
Substituir a expresso dentro da repetio por total = total +l i do e no final do
programa em vez de media = total fazer media = total /(float) contador;
do{
scanf(%lf,lido);
if(lido >= 0){
contador++;
total = total + lido;
}
}while (lido >= 0);
media = total/(float)contador;
Note que nossa resoluo criou outro problema que antes no ocorria ! Se o primeiro
nmero lido for negativo faremos uma diviso por 0 ao calcular a mdia. Isso pode ser
tratado com outro IF. Veja a soluo abaixo:
do{
scanf(%lf,lido);
if(lido >= 0){
contador++;
total = total + lido;
}
}while (lido >= 0);
if(contador > 0){
media = total/(float)contador;
}else{
media = 0;
}
c)
Erro:
R no foi inicializado
resto no foi declarado
O trecho de atualizao do FOR (no caso resto++) incorreto, provocando
alteraes indevidas no resultado final e um possvel loop infinito. Este erro muitas
vezes ocorre quando se escreve um FOR sem prestar ateno no programa... e foi
justamente isso o que ocorreu...
Correo:
Inicializar R com 0
declarar resto
Uma vez que resto a varivel de controle a atualizao dele que est dentro das
operas repetidas pode ser passado para a estrutura do FOR
R = 0;
for( resto = N; resto != 0; resto = resto/M){
R = R + ((resto%M)*pot);
pot = pot*10;
}

Você também pode gostar