Você está na página 1de 17

16/10/23, 12:48 Ciclos

Ciclos
Pedro Vasconcelos, DCC/FCUP

Outubro 2019

Ciclos
Um ciclo é uma instrução que executa várias vezes outras instruções (o corpo do ciclo)
Os ciclos em C são controlados por uma expressão
A expressão é avaliada a cada iteração
se o seu valor for zero o ciclo termina
se for diferente de zero, o ciclo continua

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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 1/17
16/10/23, 12:48 Ciclos

Instrução while
while ( expressão ) instrução

A expressão controla a terminação do ciclo


A instrução é o corpo do ciclo

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.

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 2/17
16/10/23, 12:48 Ciclos

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
O ciclo while termina quando o valor da expressão for 0 (falso)
e.g., se a expressão for i < 10 então o ciclo termina quando i ≥ 10

O corpo pode não chegar a executar (porque a expressão de controlo é testada


primeiro)
Se a expressão de controlo for sempre diferente de zero o ciclo não termina (exceto se
usarmos instruções especiais para sair do ciclo — mais tarde)

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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 3/17
16/10/23, 12:48 Ciclos

Exemplo 1
Um programa para imprimir uma tabela de quadrados
O utilizador introduz o limite superior

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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 4/17
16/10/23, 12:48 Ciclos

Um programa para somar uma sequência de números


O tamanho da sequência não é conhecido antecipadamente
Ideia:

ler cada valor dentro de um ciclo


acumular o total numa variável auxiliar
terminar quando lermos um valor especial (zero)

/*
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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 5/17
16/10/23, 12:48 Ciclos

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
Como a condição é testada depois da execução não necessitamos de ler o primeiro valor
fora do ciclo
Somar zero não altera o resultado: podemos sempre acumular o valor lido

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 6/17
16/10/23, 12:48 Ciclos

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

Introduza um inteiro positivo: 5633


4 algarismo(s)

Vamos usar um ciclo para fazer divisões inteiras por 10


Terminamos quando chegar a zero
O número iterações efetuadas dá-nos a contagem de algarismos
O ciclo do é mais conveniente do que while porque qualquer número positivo tem pelo
menos um algarismo

/* 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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 7/17
16/10/23, 12:48 Ciclos

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

expr1 é a inicialização
expr2 é a condição de repetição
expr3 é a atualização após cada iteração
instrução é o corpo do ciclo

Exemplo:

for (i = 0; i < 10; i++)


printf("%d\n", i);

Instrução for
O for é conveniente para ciclos que necessitam de contar de um valor inicial até um
valor final
Poderiamos usar o while em vez do for, mas o for é mais claro

Instrução for
Exemplo:

for (i = 0; i < 10; i++)


printf("%d\n", i);

é equivalente a

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 8/17
16/10/23, 12:48 Ciclos

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

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 9/17
16/10/23, 12:48 Ciclos

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


Trocar a ordem das comparações

contagens ascendentes devem usar < ou <=

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 10/17
16/10/23, 12:48 Ciclos

contagens descendentes devem usar > ou >=


Usar == em vez <, <=, >, >=
podemos "saltar" a terminação
"Errar por um" a condição de terminação

e.g. usar i<n em vez de i<=n

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--)

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 11/17
16/10/23, 12:48 Ciclos

Isto é equivalente a um ciclo while:

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

Omitir condição do for


Se omitirmos a condição, o ciclo for só termina se usarmos instruções de saida no
corpo (mais à frente)
Alguns programadores preferem usar um for sem condição em vez de while para esses
ciclos

// usando ciclo while


while (1) {
...
}

// usando ciclo for


for (;;) {
...
}

Ciclos for em C99


Em C99, a expressão de inicialização do for pode ser substituida por uma declaração
Isto permite declarar uma varíavel para usar dentro do ciclo:

for(int i = 0; i < n; i++) ...

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 12/17
16/10/23, 12:48 Ciclos

A variável não tem de ser declarada antes e tem âmbito limitado ao ciclo

Ciclos for em C99


Declarar a variável de controlo dentro do ciclo é conveniente e pode ajudar a tornar o
programa mais simples
Contudo, se quiseremos de usar o valor final da variável após o fim do ciclo, é
necessária a forma anterior

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
Usualmente um ciclo termina apenas quando a condição é testada

antes de uma iteração de while ou for


depois de uma iteração de do...while

Também podemos usar a instrução break para terminar um ciclo em qualquer


momento

Instrução break
Exemplo: procurar o primeiro divisor próprio de um número n (isto é, um divisor entre 2 e
n − 1 ):

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 13/17
16/10/23, 12:48 Ciclos

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:

se esgotou os possíveis divisores (i >= n)


se encontrou um divisor (i < n)

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
A instrução break é útil para escrever um ciclo com um teste de terminação a meio
Exemplo: ler uma sequência de valores e terminar com um valor especial

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 14/17
16/10/23, 12:48 Ciclos

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

Instrução continue
A instrução continue transfere a execução para o ponto imediatamente antes do fim
do corpo
Enquanto que break termina o ciclo, continue continua no ciclo

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 */
}

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 15/17
16/10/23, 12:48 Ciclos

Exemplo
Por vezes é mais simples evitar o continue colocando instruções dentro de um if
A condição é invertida: n >= 0 em vez de n < 0

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;
}

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 16/17
16/10/23, 12:48 Ciclos

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.

https://www.dcc.fc.up.pt/~pbv/aulas/progimp/teoricas/teorica06.html 17/17

Você também pode gostar