Mudanças entre as edições de "Programação 1 - Engenharia - Comandos de Repetição no C"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
(19 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 819: Linha 819:
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
main()
+
int main()
 
{
 
{
 
   int i,j;
 
   int i,j;
Linha 828: Linha 828:
 
   }
 
   }
 
   printf("valor de i=%d\n", i);
 
   printf("valor de i=%d\n", i);
 +
  return 0;
 
}
 
}
  
Linha 911: Linha 912:
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
main()
+
int main()
 
{
 
{
  int i,j;
+
    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);
 
    }
 
  }
 
  
 +
    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);
 +
        }
 +
    }
 +
    return 0;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Linha 1 170: Linha 1 171:
  
 
<math>
 
<math>
V=\frac{M!*2.5}{N!*7}
+
V=\frac{M!*2.5}{N! + 7}
 
</math>
 
</math>
 
</li>
 
</li>
Linha 1 450: Linha 1 451:
 
Escreva um programa C  que teste se um número informado pelo teclado é primo.
 
Escreva um programa C  que teste se um número informado pelo teclado é primo.
 
{{collapse top | Solução}}
 
{{collapse top | Solução}}
 +
A solução abaixo usa um contador para contar o número de divisores do número dado.
 +
Poderia ser usado um break para encerrar o loop assim que o número fosse divisível...
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
Linha 1 475: Linha 1 478:
  
 
<li>
 
<li>
Escreva um programa C  que calcule a série de Fibonacci até um número N informado pelo usuário (Ex. 1 1 2 3 5 8 13 21 ...)
+
Escreva um programa C  que calcule N termos da série de Fibonacci, onde é N informado pelo usuário (Ex. 0 1 1 2 3 5 8 13 21 ...). Não usar vetores.
{{collapse top | Solução 1}}
+
{{collapse top | Solução 1 - com while}}
 +
Nesta solução, os dois últimos termos da série sempre ficam armazenados em duas variáveis (ant2 e ant1). Inicialmente ant2 já possui 0 e ant1 possui 1. A partir do termo 3 o loop atua, computando o próximo termo e atualizando os valores de ant1 e ant2. 
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
Linha 1 483: Linha 1 487:
 
     int ant1, ant2, prox, i, n;
 
     int ant1, ant2, prox, i, n;
  
     printf("Informe o número de termos da série de Fibonacci\n");
+
     printf("Informe o número de termos\n");
 
     scanf("%d",&n);
 
     scanf("%d",&n);
  
     ant1 = ant2 = 1;
+
    ant2=0;
 
+
     ant1=1;
    printf("%d %d ", ant1 ,ant2);
+
    if (n==1)
 +
        printf("%d", ant2);
 +
    else
 +
        printf("%d %d ", ant2 ,ant1);
  
 
     i = 3;
 
     i = 3;
Linha 1 503: Linha 1 510:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
{{collapse bottom}}
 
{{collapse bottom}}
{{collapse top | Solução 2}}
+
{{collapse top | Solução 2 - uso de for com desempenho prejudicado por if no laço}}
 +
A solução abaixo é similar a anterior mas usa o comando for e podemos dizer que tem uma ineficiência pois sempre terá, no laço do loop, a execução de uma instrução de teste (if else) para ajustar a impressão dos 2 primeiros termos.
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
Linha 1 531: Linha 1 539:
 
{{collapse bottom}}
 
{{collapse bottom}}
  
{{collapse top | Solução 3}}
+
{{collapse top | Solução 3 - com  comando for e eficiente, porém não tão 'intuitiva'}}
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
Linha 1 565: Linha 1 573:
 
int main()
 
int main()
 
{
 
{
  int seq, n1=0,n2=1,i,n, cont_impar=0;
+
    int seq, n1=0,n2=1,i,n, cont_impar=0, soma=0;
  float soma=0,media;
+
    float media;
 +
 
 +
    printf("Entre com n\n");
 +
    scanf ("%d", &n);
 +
 
 +
    for(i=0;i<n;i=i+1) {
 +
        if (i<=1) {
 +
            seq = i;
 +
        } else {
 +
            seq = n1+n2;
 +
            n1=n2;
 +
            n2=seq;
 +
        }
 +
        if ((seq%2)==1) {
 +
            soma = soma + seq;
 +
            cont_impar = cont_impar + 1;
 +
        }
 +
        printf("%d ", seq);
 +
    }
 +
    if (cont_impar!=0)
 +
        media = (float)soma/cont_impar;
 +
    printf("\nA média dos números ímpares é %.2f\n", media);
 +
    return 0;
 +
}
 +
</syntaxhighlight>
 +
{{collapse bottom}}
 +
</li>
 +
 
 +
<li>
 +
Considere a função:<br>
 +
<math>f(x) = 2x^2+3 + 1 </math><br>
 +
Supondo x definido no domínio dos inteiros, faça um programa para calcular a média dos valores da função para x entre 1 e 1000.
 +
 
 +
<syntaxhighlight lang=c>
 +
#include <stdio.h>
 +
 
 +
int main()
 +
{
 +
    int x, y, soma_ac, limite;
 +
    float media;
  
  printf("Entre com n\n");
+
    /* calcular a soma acumulada aqui */
  scanf ("%d", &n);
+
    soma_ac = 0;
 +
    limite = 1000;
 +
    for ( x = 1; x <= limite; x++ ) {
 +
        y = 2 * x * x + 3 * x + 1;
 +
        printf("Valor de y é %d\n", y);
 +
        soma_ac = soma_ac + y;
 +
    }
 +
 
 +
    printf("Soma acumulada de f(x) para x entre 1 e %d: %d\n", limite, soma_ac);
 +
 
 +
    /* calcular a média aqui */
 +
    media = (float) soma_ac / limite;
 +
 
 +
    printf("media calculada é %f\n", media);
 +
 
 +
    return 0;
 +
}
 +
</syntaxhighlight>
 +
</li>
 +
 
 +
<li>
 +
Refazer o exercício anterior, criando uma função C que faz a computação da média. A função deve receber 5 parâmetros:
 +
*os coeficientes da equação;
 +
*os limites inferior e superior.
 +
Testar no programa principal (função main())
 +
<syntaxhighlight lang=c>
 +
#include <stdio.h>
  
  for(i=0;i<n;i=i+1) {
+
float media_func_quadratica(int a, int b, int c, int limite_inf, int limite_sup)
     if (i<=1) {
+
{
      seq = i;
+
    int x, y, soma_ac;
    } else {
+
    float media;
      seq = n1+n2;
+
   
      n1=n2;
+
    /* testar consistencia de limites e inverter se necessário */
      n2=seq;
+
     if (limite_inf > limite_sup) {
 +
        int aux;
 +
        aux = limite_sup;
 +
        limite_sup = limite_inf;
 +
        limite_inf = aux;
 
     }
 
     }
     if ((seq%2)==1) {
+
 
      soma = soma + seq; // soma poderia ser inteiro... mas teria
+
     /* calcular a soma acumulada aqui */
                          // que ter cast no final
+
 
      cont_impar = cont_impar + 1;
+
    for ( soma_ac = 0, x = limite_inf; x <= limite_sup; x++ ) {
 +
        y = a * x * x + b * x + c;
 +
        printf("Valor de y é %d\n", y); // tirar futuramente
 +
        soma_ac = soma_ac + y;
 
     }
 
     }
     printf("%d ", seq);
+
 
  }
+
    /* calcular a média aqui */
  media = soma/cont_impar;
+
    media = (float) soma_ac / (limite_sup - limite_inf + 1);
  printf("\nA média dos números ímpares é %.2f\n", media);
+
 
  return 0;
+
    return media;
 +
}
 +
 
 +
int main()
 +
{
 +
    float media;
 +
    int a,b,c,inf,sup;
 +
 
 +
    a = 2; b = 3; c = 1; inf = 1; sup = 3;
 +
    media = media_func_quadratica(a, b, c, inf, sup);
 +
 
 +
     printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
 +
 
 +
    a = 2; b = 3; c = 1; inf = 1; sup = 10;
 +
    media = media_func_quadratica(a, b, c, inf, sup);
 +
 
 +
    printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
 +
 
 +
    a = 2; b = 3; c = 1; inf = 1; sup = 3;
 +
    media = media_func_quadratica(a, b, c, sup, inf);
 +
 
 +
    printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
 +
 
 +
    return 0;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
{{collapse bottom}}
+
</li>
 +
<li>
 +
Fazer uma variação da função anterior mas agora a função deve retornar o MAIOR f(x) para uma determinada faixa colocada.
 
</li>
 
</li>
 
</ol>
 
</ol>

Edição das 09h22min de 5 de outubro de 2022

Objetivos

Após esta aula o aluno deverá:

  • conhecer a sintaxe e a semântica dos comandos de repetição do C: while, do while, for e goto.
  • utilizar comando break para sair de loops e o continue para interromper um laço específico;
  • identificar quando usar variáveis inteiras com maior ou menor capacidade de armazenamento (char, unsigned, long).
  • mapear estruturas simples de repetição especificadas em fluxogramas ou pseudo-código em 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 significa voltar a executá-lo (sem ter que escrevê-lo novamente) e 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>
int main() 
{
  int contador;
  
  contador=0;
  while (contador<5)     
     contador=contador+1;
  printf("valor do contador =  %d\n", contador);
  return 0;
}

OBSERVE a seguir uma variação do exemplo anterior usando um bloco de instruções delimitado por "{" e "}"

#include <stdio.h>
int 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);
  return 0;
}
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:

Fluxograma C Comentário
Fluxo5.jpg
while(contador<5) {
   printf("Entre com x\n");
   scanf("%f",&x);
   soma=soma+x;
   contador = contador + 1;
}
comando while() aplicado sobre um bloco de instruções. Note que se for uma instrução simples, as chaves podem ser omitidas.
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

FluxogramaRepeticaoImprimePar.jpg

SOLUÇÃO:

NOTE que existem outras soluções. Por exemplo, detectar se o número é par (ou ímpar) e depos fazer um loop decrementando de dois em dois (sugestão dos alunos). Esta última opção é mais eficiente em termos de tempo de execuçã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:

FluxogramaFatorialNum.jpg

SOLUÇÃO:

NOTE que a solução abaixo é simplificada pois não testa se a entrada é menor que ZERO.

#include <stdio.h>

int main()
{
  int N,i,FAT;

  printf("Entre com o valor 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.

OPÇÂO 1: Ler N com 'scanf()' e depois elaborar um 'loop' com 'while' com expressão de teste que resulte em verdadeiro caso N seja negativo. Dentro do loop é realizado uma nova leitura.
OPÇÂO 2: 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".

Solução Ex. 1

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. Será que poderia ser proposta uma solução mais otimizada? A pensar...

Solução Ex. 2
#include <stdio.h>
 
int main()
{
  int n1, n2,i,fat1, fat2;
 
  printf("Entre com o valor do fatorial 1\n");
  scanf ("%d", &n1);

   
  printf("Entre com o valor do fatorial 2\n");
  scanf ("%d", &n2);

  while (n1 < 0){
    printf("Entre com um novo valor de N1\n");
    scanf ("%d", &n1);
  } 
    while (n2 < 0){
    printf("Entre com um novo valor de N1\n");
    scanf ("%d", &n2);
  }   

  i=n1;
  fat1=1;

  while(i>1) {
      fat1=fat1*i;
      i=i-1;
  } 

  i=n2;
  fat2=1;
  while(i>1) {
      fat2=fat2*i;
      i=i-1;
  } 

  printf("A soma dos fatoriais de N1 e N2 é %d\n", (fat1+fat2));
  return 0;
}

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.

Solução Ex. 3
#include <stdio.h>
 
int main()
{
  int maior, menor, n1, n2,i,fat1, fat2;
 
  printf("Entre com o valor do fatorial 1\n");
  scanf ("%d", &n1);

  printf("Entre com o valor do fatorial 2\n");
  scanf ("%d", &n2);
 
  while (n1 < 0){
    printf("Entre com um novo valor de N1\n");
    scanf ("%d", &n1);
  } 
    while (n2 < 0){
    printf("Entre com um novo valor de N1\n");
    scanf ("%d", &n2);
  }   
 
  if (n2>n1) {
     maior = n2;
     menor = n1;
  } else {
     maior = n1;
     menor = n2;
  }
  
  i=menor;
  fat1=1;

  while(i>1) {
      fat1=fat1*i;
      i=i-1;
  } 
 
  i=maior;
  fat2=1;

  while(i>menor) {
      fat2=fat2*i;
      i=i-1;
  } 
  fat2=fat2*fat1;
 
  printf("A soma dos fatoriais de N1 (%d)e N2(%d) é %d\n", fat1, fat2, (fat1+fat2));
  return 0;
}

Exercício 4

Elaborar um programa C para computar a média de N números reais. Ver fluxograma da aula de lógica de programação para computaçlão de soma acumulada.

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.

ImpressaoSimplesTerminal.jpg

Solução Ex. 1
#include <stdio.h>
 
int main(){

int p1,p2,p3,i;
char c1, c2, c3;

printf("Carcater a ser desenhado na primeira parte da linha\n");
scanf("%c", &c1);
printf("Quantidade de caracteres a ser desenhado na primeira parte da linha\n");
scanf("%d", &p1);

printf("Carcater a ser desenhado na segunda parte da linha\n");
scanf(" %c", &c2);
printf("Quantidade de caracteres a ser desenhado na segunda parte da linha\n");
scanf("%d", &p2);

printf("Carcater a ser desenhado na terceira parte da linha\n");
scanf(" %c", &c3);
printf("Quantidade de caracteres a ser desenhado na terceira parte da linha\n");
scanf("%d", &p3);
 
i=0;
while (i < p1) {
   printf("%c", c1);
   i=i+1;
}

i=0;
while (i < p2) {
   printf("%c", c2);
   i=i+1;
}

i=0;
while (i < p3) {
   printf("%c", c3);
   i=i+1;
}

printf("\n");
return 0;
}

Exercício 2

Modificar o exercício anterior para imprimir uma quantidade variável de LINHAS. As linhas são exatamente iguais.

Solução Ex. 2
#include <stdio.h>
 
int main(){

int p1,p2,p3,i,j,linhas;
char c1, c2, c3;

printf("Carcater a ser desenhado na primeira parte da linha\n");
scanf("%c", &c1);
printf("Quantidade de caracteres a ser desenhado na primeira parte da linha\n");
scanf("%d", &p1);

printf("Carcater a ser desenhado na segunda parte da linha\n");
scanf(" %c", &c2);
printf("Quantidade de caracteres a ser desenhado na segunda parte da linha\n");
scanf("%d", &p2);

printf("Carcater a ser desenhado na terceira parte da linha\n");
scanf(" %c", &c3);
printf("Quantidade de caracteres a ser desenhado na terceira parte da linha\n");
scanf("%d", &p3);

printf("Informe a quantidade de linhas\n");
scanf("%d", &linhas);
 
j=0;
while (j < linhas){
    i=0;
    while (i < p1) {
        printf("%c", c1);
        i=i+1;
    }

    i=0;
    while (i < p2) {
        printf("%c", c2);
        i=i+1;
    }

    i=0;
    while (i < p3) {
        printf("%c", c3);
        i=i+1;
    }
    printf("\n");    
    j = j+1;    
}
printf("\n");
return 0;
}

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>
int main() 
{
  int contador;
  
  contador=0;
  do {  
     printf("valor do contador =  %d\n", contador);
     contador=contador+1;
  } while (contador<5);
  return 0;
}

A estrutura do comando, informalmente, é:

do 
  instrução_simples;
while (expressão);

ou

do {
  lista_de_instruções
} while (expressão); 
 
Fluxograma C Comentário
FluxoDoWhile-Eraldo.jpg
contador = 0;
do {
   scanf("%d",&x);
   soma=soma+x;
   if (soma>150) 
       y=z+x;
   contador++;
} while(contador<5);
Note que instruções while e if são tratadas como instruções normais que podem ser aninhadas normalmente em outros comandos.

Exemplo 1

Modificar o exemplo do cálculo do FATORIAL apresentado anteriormente para caso sejam lidos números negativos o programa pergunte novamente o número N. Usar um comando "do while" para construir o loop onde será realizado o scanf().


#include <stdio.h>

int main()
{
  int N,i,FAT;

  /* Leitura do número e 
     verificação se o número é negativo */

  do {
    printf("Entre com o valor de N\n");
    scanf ("%d", &N);
    if (N<0)
       printf("Número negativo...");
  } while (N<0);

  /* computação do fatorial */
  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;
}

Um problema na computação do fatorial é que rapidamente pode existir overflow', ou seja, ultrapassar a capacidade da da variável do tipo 'int'. VEJA a tabela abaixo com alternativas de inteiros com seus respectivos tamanhos.

TIPO bytes RANGE COMENTÁRIO
char 1 -128 até 127 um bit para o sinal
short int 2 32,768 to 32,767 um bit para o sinal
int 4 -2147483648 até 2147483647 um bit para o sinal. Dependendo da máquina poderia ser 8 bytes
long int 8 -9223372036854775808 até 9223372036854775807 um bit para o sinal
unsigned char 1 0 to 255
unsigned short 2 0 to 65,535
unsigned int 4 0 to 4294967295
unsigned long 8 0 até 18446744073709551615

Execute o programa abaixo para conferir.

#include <stdio.h>

int main()
{
  char num0;
  short num1;
  int num2;
  long int num3; 

  /* Leitura do número e 
     verificação se o número é negativo */

  printf ("tamanho de num0 = %ld\n", sizeof (num0));
  printf ("tamanho de num1 = %ld\n", sizeof (num1));
  printf ("tamanho de num2 = %ld\n", sizeof (num2));
  printf ("tamanho de num3 = %ld\n", sizeof (num3));
  
  return 0;
}

Exercício

Reimplementar o exemplo anterior usando o long int para computar o fatorial.

Exemplo 2

O programa abaixo foi extraído de (referência). Ele permite realizar a adivinhação de um número entre 1 e 10. Observe que as instruções permitem a geração do número randômico.

srand ( time(NULL) ); /* inicia o gerador com a semente baseada no relógio local */
iSecret = rand() % 10 + 1 /* gera o número */
// exemplo de geração randômica
// extracted and adapted from www.stackoverflow.com 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
      int segredo, sugestao;

      /* iniciar semente: */
      srand ( time(NULL) );

      /* gerar o número secreto: */
      segredo = rand() % 10 + 1;

      do {
          printf ("Adivinhe um número entre (1 a 10): ");
          scanf ("%d",&sugestao);
          if (segredo<sugestao) 
              printf ("O número secreto é menor\n");
          else {
              if (segredo>sugestao) 
                 printf ("O número secreto é maior\n");
          }
      } while (segredo!=sugestao);

      printf ("Parabéns!\n");
      return 0;
}

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
}


FluxogramaComandoFor-Eraldo.jpg
for(i=0; i<10; i++) {
  printf("Laço de número %d\n", i);
  if (i==5)
      printf("Este é o laço 5\n");
}
Observe que a expressão i=0 é executada SEMPRE e uma única VEZ, no início do comando.

A expressão i<10 é o controle do loop. Se FALSA o loop é encerrado. Ela é executada após a expressão de inicialização e, na sequência, no início de cada loop. A expressão i++ é executada no final de cada loop.

Exemplo

Elaborar um programa que lê um número inteiro e imprime todos os números pares entre 1 e este número INCLUSIVE.

#include <stdio.h>

int main()
{
  int i, N;

  printf("Entre com o número\n");
  scanf ("%d", &N);

  for (i=1;i<=N;i=i+1) {
     if (i%2==0)
       printf("número par ====> %d\n", i);
  }
  printf("FIM\n");

  return 0;
}

Aninhamento de loops

É muito comum que a solução de problemas exijam o aninhamento de loops. Neste caso, as instruções são aninhadas normalmente usando, se necessário, o recurso de bloco de instruções. Observe no código abaixo que para cada laço mais externo o comando for interno é executado integralmente.

#include <stdio.h>
int 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);
  }
  return 0;
}

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>

int main()
{
    int i;

    i=0;
    
    PONTO1:
    printf("Laço de número %d\n", i);
    i++;
    if (i<10)
        goto PONTO1;
    return 0;
}
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:

int main()
{
   for(;;) {
        /* Este bloco se executará infinitamente */
   }
   return 0;
}

ou com o comando while:

int main()
{
   while(1) {
        /* Este bloco se executará infinitamente */
   }
   return 0;
}

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>
int main()
{
  int i,j;

  for (i=0;i<10;i=i+1) {
     if (i==5)
       break;
  }
  printf("valor de i=%d\n", i);
  return 0;
}

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)
    int x;

    for(x = 0; x<=10; x++){

        //qndo x == 2, interrompa somente o laço atual
        if(x == 2){
            printf("Valor de x é 2 - fazendo continue...\n");
            continue;
        }

        //Quando chegamos a 8 o looping será finalizado
        if(x == 8){
            printf("Valor de x é 8 - fazendo continue...\n");
            break;
        }

        printf("%d\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>
int 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);
        }
    }
    return 0;
}

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 - nível INICIANTE

  1. Desenvolver em C um programa 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 inclusive. Usar comando for.
    Solução - Exercício 1
  2. Faça uma versão "controversa" do programa de adivinhação mostrado na aula usando uma instrução goto para sair de um loop infinito.
    Solução - Exercício 2
  3. Ainda sobre o exercício 2, implemente uma versão usando o comando while().
    Solução - Exercício 3
  4. Ainda sobre o exercício 2, implemente uma versão usando loop infinito e o comando break;
    Solução - Exercício 4
  5. Implemente uma variação do jogo de adivinhação para que ele conte o número de tentativas do jogador.
  6. Implemente uma variação do jogo de adivinhação para que dois dados (1 a 6) sejam jogados. O jogador deve adivinhar a soma dos dados.
  7. 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
  8. Dado um número inteiro positivo, calcular a soma de todos os números inteiros compreendidos entre 1 e o número dado. Fazer uma versão com while e outra com for. Caso o número apresentado for negativo ou zero, solicitar a entrada novamente. Use o comando do while para esta finalidade.
  9. Dado dois números inteiros positivos "M" e "N", computar o valor "V" conforme a equação:

EXERCÍCIOS - nível MÉDIO

  1. Tente descobrir por tentativas qual carga em um circuito com uma fonte de tensão contínua 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). Sabe-se que esta carga está entre 1 e 20 ohms. Sugestão: faça um "loop" com para testar cargas que vão de 1 a 20 ohms com acréscimos de 0.5 ohms. Crie uma variável para anotar a maior potência e a carga que produziu esta potência.
    Solução
    #include <stdio.h>
    
    int  main() {
    
      float V=500,  /* tensão da fonte */ 
            rf =10, /* resistência da fonte */
            Pl;     /* potência dissipada na carga */
      float il,     /* corrente na carga */
            rl=1;   /* carga tentativa */
            
      float maior_pot=0, /* maior potência */ 
            maior_rl;    /* maior carga */
    
      for (rl=1;rl<=20;rl=rl+0.5) {
          il=V/(rl+rf);
          Pl=rl*il*il;
          if (Pl>maior_pot) {
             maior_pot = Pl;
             maior_rl=rl;
          }
      }
      printf("Maior potência dissipada = %.2f W para carga de %.2f ohms\n", maior_pot,maior_rl);
    }
    
  2. Usando o comando for aninhado, construa um programa que implemente a figura abaixo. A margem esquerda (margem de espaços representada por ponto), 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 da forma:
    
    #include <stdio.h>
    
    int main()
    {
      int i, j, margem, largura, linhas_vazadas;
      char caracter;
      
      /** sub-problema 1 - ler margem , largura de desenho, caracter do desenho e numero de linhas **/
      
      /* sub-problema 2 - desenhar linha de topo */
    
      /* sub-problema 3 - desenhar linhas vazadas */
    
      for (j=0;j<linhas_vazadas;j++) {
          /* desenhar linha vazada*/
      }
    
      /* sub-problema 4 - desenhar linha de fundo  (igual ao sub-problema 1*/
    
      return 0;
    }
    
    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 */
    }
    
  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");
      }
    
    }
    

Exercícios Extras (resolver em sala)

  1. Escreva um programa em C que mostre a tabuada de um número fornecido pelo teclado. Esse número deve estar entre 1 e 10.
  2. Faça um programa em C que calcule a média de N números a serem lidos pelo teclado.
  3. Escreva um programa em C que para ler continuamente números inteiros pelo teclado, e informe ao final qual o maior e o menor deles. A condição de parada do programa ocorre quando o usuário informar um valor negativo ou zero.
    Solução 1
    #include <stdio.h>
    
    int main()
    {
      int maior = -1, numero;
    
      printf("Entre com um número\n");
      scanf("%d", &numero);
      while (numero > 0) {
          if(numero > maior) {
              maior = numero;
          }
          printf("Entre com um número\n");
          scanf("%d", &numero);
      }
      if (maior>0)
          printf("Maior é %d\n", maior);
      else
          printf("Não foi fornecido nenhum número\n");
      return 0;
    }
    
    Solução 2
    #include <stdio.h>
    
    int main()
    {
      int maior = -1, numero;
    
      do {
          printf("Entre com um número\n");
          scanf("%d", &numero);
          if(numero > maior) {
              maior = numero;
          }
      } while(numero>0);
      if (maior>0)
          printf("Maior é %d\n", maior);
      else
          printf("Não foi fornecido nenhum número\n");
      return 0;
    }
    
  4. Escreva um programa C que teste se um número informado pelo teclado é primo.
    Solução

    A solução abaixo usa um contador para contar o número de divisores do número dado. Poderia ser usado um break para encerrar o loop assim que o número fosse divisível...

    #include <stdio.h>
    
    int main(){
      int n, num, k, primo;
    
      printf("Informe o número a ser testado: ");
      scanf("%d",&num);
    
      primo=0;
    
      for(k=2; k<num; k++)
         if((num%k) == 0)
              primo++;
      if(primo > 0)
         printf("%d não é primo\n", num);
      else
         printf("%d é primo\n", num);
         
      return 0;
    }
    
  5. Escreva um programa C que calcule N termos da série de Fibonacci, onde é N informado pelo usuário (Ex. 0 1 1 2 3 5 8 13 21 ...). Não usar vetores.
    Solução 1 - com while

    Nesta solução, os dois últimos termos da série sempre ficam armazenados em duas variáveis (ant2 e ant1). Inicialmente ant2 já possui 0 e ant1 possui 1. A partir do termo 3 o loop atua, computando o próximo termo e atualizando os valores de ant1 e ant2.

    #include <stdio.h>
    
    int main (void){
        int ant1, ant2, prox, i, n;
    
        printf("Informe o número de termos\n");
        scanf("%d",&n);
    
        ant2=0;
        ant1=1;
        if (n==1)
            printf("%d", ant2);
        else
            printf("%d %d ", ant2 ,ant1);
    
        i = 3;
        while (i <= n){
            prox = ant1 + ant2;
            printf("%d ", prox);
            ant2 = ant1;
            ant1 = prox;
            i++;
        }
        printf("\n");
        return 0;
    }
    
    Solução 2 - uso de for com desempenho prejudicado por if no laço

    A solução abaixo é similar a anterior mas usa o comando for e podemos dizer que tem uma ineficiência pois sempre terá, no laço do loop, a execução de uma instrução de teste (if else) para ajustar a impressão dos 2 primeiros termos.

    #include <stdio.h>
    
    int main()
    {
      int seq, n1=0,n2=1,i,n;
    
      printf("Entre com n\n");
      scanf ("%d", &n);
    
      for(i=0;i<n;i=i+1) {
        if (i<=1) {
           seq = i;
        } else {
           seq = n1+n2;
           n1=n2;
           n2=seq;
        }
        printf("%d ", seq);
      }
    
      printf("\n");
      return 0;
    }
    
    Solução 3 - com comando for e eficiente, porém não tão 'intuitiva'
    #include <stdio.h>
    
    int main()
    {
      int seq, n1=-1,n2=1,i,n;
    
      printf("Entre com n\n");
      scanf ("%d", &n);
      printf("A série é\n");
      for(i=0;i<n;i=i+1) {
           seq = n1+n2;
           n1=n2;
           n2=seq;
           printf("%d ", seq);
      }
      printf("\n");
      return 0;
    }
    
  6. Escreva um programa C que calcule a média entre todos os números ÍMPARES da série de Fibonacci até o termo N sendo o primeiro termo 0. Exemplo: para N = 5 a série é 0 1 1 2 3 e a soma dos termos ímpares é 5. Assumir que N é sempre maior que 2.
    Solução 1
    #include <stdio.h>
    
    /* atenção: ajustar esta solução ao enunciado */
    int main()
    {
        int seq, n1=0,n2=1,i,n, cont_impar=0, soma=0;
        float media;
    
        printf("Entre com n\n");
        scanf ("%d", &n);
    
        for(i=0;i<n;i=i+1) {
            if (i<=1) {
                seq = i;
            } else {
                seq = n1+n2;
                n1=n2;
                n2=seq;
            }
            if ((seq%2)==1) {
                soma = soma + seq;
                cont_impar = cont_impar + 1;
            }
            printf("%d ", seq);
        }
        if (cont_impar!=0)
            media = (float)soma/cont_impar;
        printf("\nA média dos números ímpares é %.2f\n", media);
        return 0;
    }
    
  7. Considere a função:

    Supondo x definido no domínio dos inteiros, faça um programa para calcular a média dos valores da função para x entre 1 e 1000.
    #include <stdio.h>
    
    int main()
    {
        int x, y, soma_ac, limite;
        float media;
    
        /* calcular a soma acumulada aqui */
        soma_ac = 0;
        limite = 1000;
        for ( x = 1; x <= limite; x++ ) {
            y = 2 * x * x + 3 * x + 1;
            printf("Valor de y é %d\n", y);
            soma_ac = soma_ac + y;
        }
    
        printf("Soma acumulada de f(x) para x entre 1 e %d: %d\n", limite, soma_ac);
    
        /* calcular a média aqui */
        media = (float) soma_ac / limite;
    
        printf("media calculada é %f\n", media);
    
        return 0;
    }
    
  8. Refazer o exercício anterior, criando uma função C que faz a computação da média. A função deve receber 5 parâmetros:
    • os coeficientes da equação;
    • os limites inferior e superior.
    Testar no programa principal (função main())
    #include <stdio.h>
    
    float media_func_quadratica(int a, int b, int c, int limite_inf, int limite_sup)
    {
        int x, y, soma_ac;
        float media;
        
        /* testar consistencia de limites e inverter se necessário */
        if (limite_inf > limite_sup) {
            int aux;
            aux = limite_sup;
            limite_sup = limite_inf;
            limite_inf = aux;
        }
    
        /* calcular a soma acumulada aqui */
    
        for ( soma_ac = 0, x = limite_inf; x <= limite_sup; x++ ) {
            y = a * x * x + b * x + c;
            printf("Valor de y é %d\n", y); // tirar futuramente
            soma_ac = soma_ac + y;
        }
    
        /* calcular a média aqui */
        media = (float) soma_ac / (limite_sup - limite_inf + 1);
    
        return media;
    }
    
    int main()
    {
        float media;
        int a,b,c,inf,sup;
    
        a = 2; b = 3; c = 1; inf = 1; sup = 3;
        media = media_func_quadratica(a, b, c, inf, sup);
    
        printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
    
        a = 2; b = 3; c = 1; inf = 1; sup = 10;
        media = media_func_quadratica(a, b, c, inf, sup);
    
        printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
    
        a = 2; b = 3; c = 1; inf = 1; sup = 3;
        media = media_func_quadratica(a, b, c, sup, inf);
    
        printf("media calculada para a = %d b = %d c = %d limite inferior = %d e limite superior %d : %f\n", a, b, c, inf, sup, media);
    
        return 0;
    }
    
  9. Fazer uma variação da função anterior mas agora a função deve retornar o MAIOR f(x) para uma determinada faixa colocada.