Programação 1 - Engenharia - Comandos de Repetição no C
Objetivos
- O aluno deverá ser capaz de colocar estruturas de repetição especificadas
em fluxogramas ou pseudo-código na forma de estruturas em linguagem C.
Estruturas de Repetição
Existem 4 estruturas/comandos que permitem implementar loops ou repetições de blocos de código:
- while()
- do while()
- for()
- goto label
NOTA: Observe que repetir o código siginifica voltar a executá-lo, normalmente sobre o controle de uma expressão lógica.
O comando 'while()': TESTE da REPETIÇÃO no começo
O comando while permite implementar loops com controle no início.
A semântica do while é a seguinte: ao entrar no comando a EXPRESSÃO entre parênteses é AVALIADA. Caso resulte em uma valor VERDADEIRO o LAÇO do loop é executado uma vez. O programa testa então novamente a expressão. LEMBRAR que:
- VERDADEIRO é qualquer valor diferente de ZERO;
- DENTRO do laço NORMALMENTE existe uma modificação de alguma parte da expressão de teste de forma que em algum momento o LOOP se encerra.
- Ao se encerrar o programa continua na próxima instrução APÓS o comando "while()";
- ANTES DE entrar no comando while SEMPRE tenha certeza que as variáveis estão com valores adequados de forma que a expressão SEJA AVALIADA sempre corretamente.
No exemplo que se segue existe UMA única instrução simples (terminada em ";").
#include <stdio.h>
main()
{
int contador;
contador=0;
while (contador<5)
contador=contador+1;
printf("valor do contador = %d\n", contador);
}
OBSERVE a seguir uma variação do exemplo anterior usando um bloco de instruções delimitado por "{" e "}"
#include <stdio.h>
main()
{
int contador;
contador=0;
while (contador<5) {
printf("valor da expressão = contador < 5 é %d\n", contador<5);
printf("valor do contador = %d\n", contador);
contador=contador+1;
}
printf("NO FINAL a expressão contador < 5 é %d\n", contador<5);
}
Notar que a expressão contador<5 assume valor 0 (falso) e 1 (verdadeiro).
A estrutura do comando, informalmente, é:
while (expressão) instrução_simples;
ou
while (expressão) { lista_de_instruções }
Vamos ver a correspondência do comando while com um fluxograma:
NOTE que no exemplo anterior o contador inicialmente DEVE conter um valor válido.
Exemplo 1
PROBLEMA: Elaborar um programa C para imprimir os números pares em ordem decrescente (até atingir 0 inclusive) a partir de um número N fornecido como entrada. Seguir o fluxograma mostrada abaixo.
DADOS DE ENTRADA: N (variável inteira)
DADOS DE SAÌDA: números pares impressos
SOLUÇÃO:
#include <stdio.h>
int main()
{
int N,i;
printf("Entre com o valode N\n");
scanf ("%d", &N);
i=N;
while(i>=0) {
if (i%2==0) { /* parênteses em (i%2) é opcional porque o operador de resto tem precedência */
printf("%d\n", i);
}
i=i-1;
}
return 0;
}
Exemplo 2
PROBLEMA: Elaborar um programa C para computação do fatorial de um número conforme definição abaixo:
DADOS DE ENTRADA:número N (numero inteiro)
DADOS DE SAÌDA: FATORIAL computado
O fatorial é definido por:
SOLUÇÃO:
#include <stdio.h>
int main()
{
int N,i,FAT;
printf("Entre com o valo de N\n");
scanf ("%d", &N);
i=N;
FAT=1;
while(i>1) {
FAT=FAT*i;
i=i-1;
}
printf("Valor de FAT de %d é %d\n", N, FAT);
return 0;
}
Exercício 1
Modificar o exercício do FATORIAL apresentado anteriormente para caso sejam lidos números negativos o programa pergunte novamente o número N. Usar um comando "while" adicional.
Antes de entrar com o valor de N, atribua um valor NEGATIVO, por exemplo -1 a N. A expressão de teste no comando "while" deve ser verdadeira enquanto N for negativo. Coloque o scanf dentro deste "while".
Exercício 2
Elaborar um programa C para computar a SOMA do fatorial de dois números inteiros fornecidos como entrada. O programa deve prever a entrada somente de números não negativos. Olhe as soluções acima e reproduza as estruturas propostas.
Exercício 3
Elabore uma versão otimizada do programa que computa a soma do fatorial de dois números. Observe que poderíamos "economizar" laços de repetição se calcularmos o fatorial do menor número e depois computar o fatorial do maior usando o menor número como ponto de parada na repetição.
Desenhando no terminal MODO texto
A saída de um programa em um terminal modo TEXTO possui algumas limitações. Além da questão da definição, o programa escreve sempre na posição de um CURSOR que avança automaticamente. Em condições normais não é possível retornar o cursor para linhas acima. Deve-se portanto planejar cuidadosamente o desenho de figuras levando em consideração estas restrições. As instruções de repetição ajudarão bastante neste processo.
Exemplo: imprimir uma linha com 10 caracteres 'A'
AAAAAAAAA
#include <stdio.h>
int main()
{
int i;
i=0;
while (i<10) {
printf("A");
i=i+1;
}
printf("\n");
}
Exercício 1
Elaborar um programa para imprimir uma linha CUSTOMIZADA em 3 partes. Cada parte imprime um número variável de caracteres. O número de caracteres e o caracter a ser impresso em cada parte deve ser informado.
Exercício 2
Modificar o exercício anterior para imprimir uma quantidade variável de LINHAS. As linhas são exatamente iguais.
Comando do while: controle do loop no final
O comando do while() permite a repetição de uma ou mais instruções, com controle do loop no final. Isto permite que o bloco seja executado pelo menos uma vez.
#include <stdio.h>
main()
{
int contador;
contador=0;
do {
printf("valor do contador = %d\n", contador);
contador=contador+1;
} while (contador<5);
}
A estrutura do comando, informalmente, é:
do instrução_simples; while (expressão);
ou
do { lista_de_instruções } while (expressão);
Comando for()
O comando for() permite uma forma mais elaborada de loop, com controle no início do bloco de repetição.
#include <stdio.h>
main()
{
int i;
for (i=0;i<10;i=i+1)
printf("i =%d\n",i);
}
A estrutura do comando é:
for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) instrução_simples;
ou
for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) { lista_de_instruções }
Aninhamento de loops
#include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
printf("valor de j = %d\n", j);
}
printf("valor de i = %d\n", i);
}
}
Comando goto
O comando goto é um dos mais antigos da programação. A ideia é comandar um salto para um determinado ponto específico do programa marcado por um rótulo (LABEL). Para utilizá-lo deve-se, portanto, marcar o ponto para onde será feito o salto usando um LABEL.
Exemplo:
#include <stdio.h>
main()
{
int i;
i=0;
PONTO1:
printf("Laço de número %d\n", i);
i++;
if (i<10)
goto PONTO1;
}
Devido a ser uma instrução "desestruturante", em geral NÂO se recomenda o uso deste comando.
Em alguns casos de tratamento de erro pode ser interessante o uso do goto.
Leia um pouco mais sobre o goto aqui.
Loop Infinito
É possível implementar loops infinitos com qualquer uma das instruções acima.
Exemplo com comando for:
main()
{
for(;;) {
/* Este bloco se executará infinitamente */
}
}
ou com o comando while:
main()
{
while(1) {
/* Este bloco se executará infinitamente */
}
}
Exercícios
1. Usando o comando for aninhado, construa um programa que implemente a figura abaixo. A margem esquerda (margem de espaços), o caracter do desenho, o número de linhas vazadas e o tamanho horizontal da figura devem ser lidos pelo teclado.
aaaaaaaaaa a a aaaaaaaaaa
SUGESTÃO: dividir em subproblemas.
solução |
---|
#include <stdio.h>
main()
{
int i, j, margem, largura, linhas_vazadas;
char caracter;
/** sub-problema 1 - ler margem , largura de desenho, caracter desenho e numero de linhas **/
printf("\n=====================\n");
printf("Entrar com margem => ");
scanf("%d", &margem);
printf("\n=====================\n");
printf("Entrar com largura => ");
scanf("%d", &largura);
printf("\n=====================\n");
printf("Entrar com caracter => ");
scanf(" %c", &caracter);
printf("\n=====================\n");
printf("Entrar com linhas_vazadas => ");
scanf(" %d", &linhas_vazadas);
/* sub-problema 2 - desenhar linha de topo */
/* desenhar margem */
for (i=0;i<margem;i++)
printf(" ");
/* desenhar restante da linha de topo */
for (i=0;i<largura;i++)
printf("%c", caracter);
printf ("\n"); /* avançar para a próxima linha */
/* sub-problema 3 - desenhar linhas vazadas */
for (j=0;j<linhas_vazadas;j++) {
/* desenhar margem */
for (i=0;i<margem;i++)
printf(" ");
if(largura>0)
printf("%c", caracter);
for (i=0;i<largura-2;i++)
printf(" ");
if(largura>1)
printf("%c", caracter);
printf("\n");
}
/* sub-problema 4 - desenhar linha de fundo */
/* desenhar margem */
for (i=0;i<margem;i++)
printf(" ");
/* desenhar restante da linha de topo */
for (i=0;i<largura;i++)
printf("%c", caracter);
printf ("\n"); /* avançar para a próxima linha */
}
|
2. Dado um número inteiro positivo, calcular a soma de todos os números inteiros compreendidos entre 0 e o número dado. Fazer uma versão com while e outra com for.
3. Construa um programa para desenhar a seguinte figura de forma parametrizável (dado caracter, margem, e número de linhas):
AAAAAAAAAAAAAAAA AAAAAAAAAAAAAA AAAAAAAAAAAA AAAAAAAAAA AAAAAAAA AAAAAA AAAA AA BB BBBBB BBBBBBBB BBBBBBBBBBB BBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBB
solução |
---|
#include <stdio.h>
main()
{
int i, j, margem, largura, linhas;
char caracter1,caracter2;
/** sub-problema 1 - ler margem , largura de desenho, caracter desenho e numero de linhas **/
printf("\n=====================\n");
printf("Entrar com margem => ");
scanf("%d", &margem);
printf("\n=====================\n");
printf("Entrar com caracter 1 => ");
scanf(" %c", &caracter1);
printf("\n=====================\n");
printf("Entrar com caracter 2 => ");
scanf(" %c", &caracter2);
printf("\n=====================\n");
printf("Entrar com linhas (tem que ser maior ou igual a 1) => ");
scanf(" %d", &linhas);
/* sub-problema 2 - desenhar parte superior */
for (i=linhas;i>0;i--) {
/* desenhar margem */
for (j=0;j<margem;j++)
printf(" ");
for (j=0;j<i*2;j++) {
printf("%c", caracter1);
}
printf("\n");
}
/* sub-problema 3 - desenhar parte inferior */
for (i=1;i<=linhas;i++) {
/* desenhar margem */
for (j=0;j<margem;j++)
printf(" ");
for (j=0;j<i*2;j++) {
printf("%c", caracter2);
}
printf("\n");
}
}
|
4.Estude o programa (referência) abaixo:
// rand example: guess the number
// extract from www.stackoverflow.com
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = 1 + (rand() % 10);
do {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
} while (iSecret!=iGuess);
printf ("Congratulations!\n");
return 0;
}
Estude também o significado das instruções:
srand ( time(NULL) ); iSecret = rand() % 10 + 1;
5. Elabore um programa que lê um número inteiro e imprime todos os números pares entre 1 e este número.
Uso de break para sair de loops
Em exercícios anteriores, a finalização de um loop normalmente se dá pela expressão de controle de loop associado a instrução usada. É possível sair de um loop na força bruta usando a instrução break:
#include <stdio.h>
main()
{
int i,j;
for (i=0;i<10;i++) {
if (i==5)
break;
}
printf("valor de i=%d\n", i);
}
Note que o break sempre sai do loop mais próximo a ele.
- O comando break encerra o laço no ponto em que for executado.
- O comando continue desvia o fluxo para o início do laço.
#include <stdio.h>
int main()
{
//break -> simplesmente interrompe o nosso ciclo
//continue -> interrompe o laço (desvia o fluxo para o início do laço)
for(int x = 0; x<=10; ++x){
//qndo x == 2, interrompa somente o laço atual
if(x == 2){
printf("-\n", x);
continue;
}
//Quando chegamos a 8 o looping será finalizado
if(x == 8){
printf("-\n", x);
break;
}
printf("%i\n", x);
}
}
Exercício
Elabore um programa em C que leia no máximo 5 números inteiros positivos. Caso um número negativo seja digitado no meio da seqüência uma mensagem deve ser impressa uma mensagem de aviso no terminal e o laço é encerrado de imediato.
Uso do continue para prosseguir no início do loop
#include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
if (i==1) {
continue;
}
printf("valor de i = %d\n", i);
for (j=0;j<4;j++) {
if (j==1) {
continue;
}
printf("valor de j = %d\n", j);
}
}
}
Usando funções da biblioteca matemática
Para usar as funções matemáticas da biblioteca padrão, fazer os seguintes passos:
- No arquivo-fonte incluir o header math.h da biblioteca matemática:
#include <stdio.h>
#include <math.h>
main()
{
float x,y; /* declaração de duas variáveis reais */
printf ("Entre com o valor de x ");
scanf("%f",&x);
y = sqrtf(x);
printf ("Raiz de x = %.2lf", y);
}
NOTA: a maior parte de parâmetros e valores de retorno das funções matemáticas são reais de dupla precisão (double).
- Compilar e linkar o arquivo da forma:
gcc ex1.c -o ex1 -lm
EXERCÍCIOS
1. Desenvolver um algoritmo que efetue a soma de todos os números ímpares que são múltiplos de três e que se encontram no conjunto dos números de 1 até 500.
2. Faça uma versão "politicamente incorreta" do programa de adivinhação da aula passada, Faça um loop infinito com o do while() e use uma instrução goto para sair do loop.
Solução - Exercício 2 |
---|
* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
do {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
if (iSecret==iGuess)
goto Final;// salta para o "Final"
} while(1);
//aqui está o "Final"
Final:printf ("Congratulations!\n");
return 0;
|
3. Ainda sobre o exercício 1, implemente uma versão usando o comando while().
Solução - Exercício 3 |
---|
/* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
iGuess = -71; //insere um valor que nunca vai ser inserido pelo usuario em iGuess
while (iSecret!=iGuess) {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
}
printf ("Congratulations!\n");
return 0;
}
|
/* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
/* coloca um valor em iGuess que nunca será inserido pelo usuário */
iGuess = -1;
while (iSecret!=iGuess) {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
}
printf ("Congratulations!\n");
return 0;
}
4. Ainda sobre o exercício 1, implemente uma versão usando loop infinito e o comando break;
Solução - Exercício 4 |
---|
/* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
do {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
if (iSecret==iGuess)
break; // break sai do loop logo após acertar o número
} while(1);
printf ("Congratulations!\n");
return 0;
}
|
/* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
do {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
if (iSecret==iGuess) /* se acertou sai do loop */
break;
} while(1);
printf ("Congratulations!\n");
return 0;
}
5. Implemente um programa C para ler N resistências. O programa deve ler inicialmente N, depois o valor das resistências (fazendo os cálculos cumulativos) e então calcular o valor da resistência série e paralelo equivalente do circuito. Não usar vetores. Usar um comando while.
Solução - Exercício 5 |
---|
#include < stdio.h >
main() {
int n, i = 1, tipo;
float R, req = 0;
printf("Quantas resistencias voce quer inserir ? \n");
scanf("%d", & n);
printf("Digite 1 para série e 0 para paralelo\n");
scanf("%d", & tipo);
if (n <= 0 || tipo < 0 || tipo > 2) {
printf("O numero de resistencias precisa ser maior que zero!!!\n");
printf("Ou o tipo precisa ser valido!!\n");
} else if (tipo == 1) {
while (i <= n) {
printf("Insira a %da Resistencia: \n", i);
scanf("%f", & R);
req = req + R;// acumulando(somando) a variavel R na variavel Req
i++;
}
} else if (tipo == 0) {
while (i <= n) {
printf("Insira a %da Resistencia: \n", i);
scanf("%f", & R);
printf("R: %f\n", R);
req = req + 1 / R;// acumulando(somando) "1/R" na variavel Req
req = 1 / req;
printf("req %f\n", req);
i++;
}
} else {
printf("Req = %f\n", req);
}
}
|
6. Tente descobrir por tentativas qual carga em um circuito com uma fonte de tensão de 500 V e resistência interna de 10 ohms produz a máxima dissipação de potẽncia (ver https://en.wikipedia.org/wiki/Maximum_power_transfer_theorem). Sugestão: gere/imprima uma tabela com valor de resistores de carga de 1 a 20 ohms com acréscimos de 0.5 ohms indicando a potência dissipada em cada um.
Solução - Exercício 6 |
---|
#include <stdio.h>
main() {
float V=500, rs =10, Is, Pl;
float rl=1, n;
int i=1;
while(i<40){//40 pois é esse o numero de loops somando 0.5 por loop para chegar ao valor 20 para rl
n = rl/(rl+rs);
printf("Com rl=%f a eficiencia fica em %f\n",rl,n);
Is=(V/rs);
Pl=(Is*Is)*rl;
printf("E a maxima potencia dissipada fica %f\n",Pl);
printf("--------------------------\n");//uma quebra de linha para a melhor visualizacao dos valores
rl = rl+0.5;
i++;
}
}
|
Exercícios Extras (resolver em sala)
- Escreva um algoritmo que mostre a tabuada de um número fornecido pelo teclado. Esse número deve estar entre 1 e 10.
- Faça um algoritmo que calcule a média para uma quantidade de números a serem lidos seja previamente, informada pelo teclado.
- Escreva um algoritmo que leia até 10 números do teclado, e informe ao final qual o maior e o menor deles.
- Escreva um algoritmo que teste se um número informado pelo teclado é primo.
Solução |
---|
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, num, k, primo;
printf("Informe o valor a ser validado: ");
scanf("%d",&num);
primo=0;
for(k=1; k<=num; k++)
if((num%k)==0)
primo++;
if(primo>2)
printf("%d nao e primo\n", num);
else
printf("%d e primo\n", num);
}
|