Ciclos

Instruções de ciclos

while

é usado para ciclos em que a expressão é testada antes de executar o corpo do ciclo

do...while

é usado para ciclos em que a expressão é testada depois de executar o corpo

for

é uma forma conveniente para ciclos com uma variável de controlo

Instrução while

while ( expressão ) instrução


Execução:

  1. Primeiro avalia a expressão:
  2. Se for zero, o ciclo termina imediatamente;
    se for diferente de zero, executa instrução e repete 1.

i = 1;
while (i < 10)   /* expressão de controlo */
   i = i * 2;   /* corpo do ciclo */
i = 1;
i < 10? 1 (verdade)
i = i * 2 = 2
i < 10? 1 (verdade)
i = i * 2 = 4
i < 10? 1 (verdade)
i = i * 2 = 8
i < 10? 1 (verdade)
i = i * 2 = 16
i < 10? 0 (falso)

No final: i = 16.

Instrução while

O corpo pode ser um bloco de instruções em vez de uma só:

i = 1;
while (i < 10) {
   printf("%d\n", i);
   i = i * 2;
}

Podemos colocar chavetas mesmo com uma só instrução:

i = 1;
while (i < 10) {
  i = i * 2;
}

Terminação

   while (1) {
      ...   /* ciclo infinito */
   }

Exemplo 1

Limite superior: 5
1        1
2        4
3        9
4       16
5       25

/*
  quadrados.c
  Imprimir uma tabela de quadrados
*/
#include <stdio.h>

int main(void) {
   int i, n;    

   printf("Limite superior: ");
   scanf("%d", &n);
   i = 1;
   while (i <= n) {
      printf("%d\t%d\n", i, i*i);
      i ++;
   }
   return 0;
}

Exemplo 2


/*
  somar.c
  Somar uma sequência de números
*/
#include <stdio.h>

int main(void) {
   int n, soma = 0;
   printf("Introduza valores; 0 termina.\n");
   scanf("%d", &n);      // primeiro valor
   while (n != 0) {  // enquanto não terminou
        soma += n;       // acumular
        scanf("%d", &n); // ler próximo valor
   }
   printf("A soma é: %d\n", soma);
   return 0;
}

Instrução do...while

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


Execução:

  1. Primeiro executa a instrução
  2. Depois avalia a expressão
  3. Se for zero, o ciclo termina;
    se for diferente de zero, repete o passo 1.

Exemplo

Vamos re-escrever o programa para somar números usando um ciclo do.


/*
  somar2.c
  Somar uma sequência de números (alternativa)
*/
#include <stdio.h>

int main(void) {
   int n, soma = 0;
   printf("Introduza valores; 0 termina.\n");
   do {
       scanf("%d", &n);  // próximo valor
       soma += n;        // acumular
   } while (n != 0);  // enquanto não terminou
   printf("A soma é: %d\n", soma);
   return 0;
}

Observações

Exemplo 3

Calcular o número de algarismos de um inteiro positivo:

Introduza um inteiro positivo: 5633
4 algarismo(s)

/* algarismos.c
   Contar algarismos de um inteiro positivo
*/
#include <stdio.h>

int main(void) {
  int digits = 0, n;
  printf("Inteiro positivo: ");
  scanf("%d", &n);
  do {
     n /= 10;    // quociente divisão por 10
     digits ++;  // mais um algarismo
  } while (n > 0);
  printf("%d algarismo(s)\n", digits);
  return 0;
}

Instrução for

for ( expr1; expr2; expr3 ) instrução

Exemplo:

for (i = 0; i < 10; i++)
  printf("%d\n", i);

Instrução for

Instrução for

Exemplo:

for (i = 0; i < 10; i++)
  printf("%d\n", i);

é equivalente a

i = 0;
while (i < 10) {
  printf("%d\n", i);
  i++;
}

Instrução for

A forma geral

for (expr1; expr2; expr3) instrução

é equivalente a:

expr1;
while ( expr2 ) {
   instrução
   expr3;
}

Esta tradução pode ajudar a compreender alguns detalhes.

Instrução for

Exemplo: qual o efeito de usar ++i em vez de i++ no ciclo seguinte?

for(i = 0; i < 10; ++i)
   printf("%d\n", i);

Traduzindo para while:

i = 0;
while (i < 10) {
   printf("%d\n", i);
   ++i;  // alternativa: i++;
}

Usar ++i ou i++ é equivalente — contamos de 0 a 9.

Formas comuns de for

Repetir n vezes:

// contagem ascendente de 0 até n-1 
for(i = 0; i < n; i++) ...

// contagem ascendente de 1 até n
for(i = 1; i <= n; i++) ...

// contagem descendente de n-1 até 0
for(i = n-1; i >= 0; i--) ...

// contagem descendente de n até 1
for(i = n; i > 0; i--) ...

Erros comuns no for

Omitir expressões no for

Podemos omitir uma ou mais expressões no ciclo for.

Omitir a inicialização:

int i = 10;
for (; i > 0; i--)
   printf("%d\n", i)

Omitir a atualização:

int i;
for (i = 10; i > 0;)
   printf("%d\n", i--)

Omitir expressões no for

Omitir ambas inicialização e atualização:

int i = 10;
for (; i > 0;)
   printf("%d\n", i--)

Isto é equivalente a um ciclo while:

int i = 10;
while (i > 0)
   printf("%d\n", i--)

Omitir condição do for

// usando ciclo while
while (1) {
   ...
}

// usando ciclo for
for (;;) {
   ... 
}

Ciclos for em C99

Ciclos for em C99

for(int i = 0; i < n; i++) {
   printf("%d\n", i); // OK: i é válido
}
printf("%d\n", i); // ERRO: i fora de âmbito
printf("%d\n", n); // OK: n é válido

Instrução break

Instrução break

Exemplo: procurar o primeiro divisor próprio de um número \(n\) (isto é, um divisor entre 2 e \(n-1\)):

int i, n;
... /* obter valor de `n' */
for (i = 2; i < n; i++) {
   if (n%i == 0) break;
}

Este ciclo pode terminar de duas formas:

Instrução break

No final do ciclo podemos determinar a causa de terminação com um teste simples:

int i, n;
... /* obter valor de `n' */
for (i = 2; i < n; i++) {
   if (n%i == 0) break;
}
if (i < n)
   printf("Encontrou divisor: %d\n", i);
else
   printf("Não tem divisores próprios\n");

Instrução break

for(;;) {
  scanf("%d", &n);
  if (n == 0)   // se for zero
     break;     // terminar o ciclo
  ... // se não: processar o valor 
}

Instrução continue

Exemplo

Ler e acumular 10 inteiros não-negativos.

int i = 0, n, soma = 0;
while (i < 10) {
  scanf("%d", &n);
  if (n < 0)
    continue;
  soma += n;
  i ++;
  /* continue salta para aqui */
}

Exemplo

int i = 0, n, soma = 0;
while (i < 10) {
  scanf("%d", &n);
  if (n >= 0) {
     soma += n;
     i ++;
  }
}

Instrução vazia

Uma instrução pode ser vazia, isto é, apenas um ponto-e-vírgula sem mais símbolos:

i = 0; ; j = 1;  // segunda instrução vazia

Uma instrução vazia não faz nada; é útil apenas para escrever um ciclo cujo corpo é vazio.

Instrução vazia

Considere o ciclo para procurar divisores:

for (i = 2; i < n; i++) {
   if (n%i == 0) break;
}

Podemos juntar as duas condições e retirar o break; o corpo fica vazio:

for (i = 2; i < n && n%i != 0; i++)
   ; /* instrução vazia */ 

Para evitar confusão, devemos escrever a instrução vazia numa linha separada.