Estruturas de repetição
Estruturas de repetição são estruturas que permitem que você repita comandos, e isso te permite automatizar algumas coisas como atribuir valor a arrays ou fazer contagem...
While
// exibindo uma contagem até 5
// sem estruturas de repetição
printf("%i\n", 1);
printf("%i\n", 2);
printf("%i\n", 3);
printf("%i\n", 4);
printf("%i\n", 5);
// com uma estrutura de repetição
int contador = 1;
while (contador <= 5){ // enquanto o contador for menor ou igual 5
printf("%i\n", contador); // escreva o contador
contador ++; // e incremente o contador
}
No caso acima temos duas formas de exibir uma contagem... “Mas deu a mesma quantidade de linhas, então não vale a pena aprender esse negócio difícil aí, a primeira opção é mais simples!!” ... E se ao invés de contar até 5 nós precisássemos contar até mil? Você ainda acha aceitável escrever isso sem usar uma estrutura de repetição ?
A estrutura usada é o while
, que significa “enquanto”, basicamente ele funciona assim:
condicao = (2 != 3);
while ( condicao ) { // enquanto a condição for verdade execute
// comandos
}
E se a condição for verdadeira o while
vai executar os comandos do bloco, mas se ela for falsa ele vai sair do loop (estrutura de repetição).
E assim como nos condicionais, se você precisar
No caso da contagem foi necessário adicionar 1
ao contador, pois se a condicao
sempre for verdadeira o programa vai entrar em um loop infinito, e foi isso que aconteceu com o nosso exemplo anterior, pois o 2
sempre será diferente do 3
.
Mas isso não quer dizer que loops infinitos sejam sempre ruins,Digamos que agente queira que um programa leia dados, mas não sabemos a quantidade exata de vezes ler, então criamos um loop infinito e damos um “flag”(uma forma de interrupção do loop) a ele, no nosso exemplo flag será a resposta para a pergunta “Deseja continuar?”, caso a pessoa digite “n” loop será interrompido.
Eu vou ilustrar a situação acima de duas maneiras usando o while
.
// usando o teste lógico do while
{
char flag = 's';
while (flag == 's'){
printf("Deseja continuar? [s/N] ");
scanf("%c", &flag);
}
}
// usando o break
{
char flag;
while (1) {
printf("Deseja continuar? [s/N] ");
scanf("%c", &flag);
if (flag != 's') break; // se a resposta for não interrompa
}
}
O break é um comando que interrompe loops
E assim como nos condicionais o while
também tem uma forma compacta:
int cont = 0;
while (cont <= 10) printf("%i\n", cont++);
Do..while
A estrutura popularmente conhecida como do
..while
é basicamente um while
de cabeça para baixo.
// exibindo uma contagem até 5
int i = 1;
// while
while ( i <= 5 ) // enquanto ( i menor ou igual a 5 )
printf ( "%i\n", i++ ); // escreva i
// do..while
do { // faça {
printf ( "%i\n", i ); // escreva i
} while ( i<=5 ); // } enquanto ( i menor ou igual a 5 )
O do
..while
funciona da mesma forma que o while
, com uma única diferença, ele faz o teste lógico no final, logo, ele executa o que está no bloco e só depois testa a condição:
int i = 90;
do {
printf("%i\n", i);
} while ( i <= 10 );
Saída:
90
“Ué? Por que ele imprimiu?” , Porque ele faz o teste lógico ( i <= 10
) no fim da execução do bloco, se este fosse um while
comum o teste seria feito antes, e só executaria o bloco se este teste fosse verdadeiro.
“Aah! Então é inútil usar este laço!!” ... Sinto discordar, mas este laço foi criado para agilizar algumas tarefas, lembra do código com flag? Que vimos no capítulo anterior?
char flag = 's';
while (flag == 's'){
printf("Deseja continuar? [s/N] ");
scanf("%c", &flag);
}
Para que o código acima funcione nós somos obrigados o valor 's'
à variável flag
, com o do
..while
isso não é necessário:
char flag;
do {
printf("Deseja continuar? [s/N] ");
scanf("%c", &flag);
} while (flag == 's');
E o código com while
e sem usar o teste lógico (o que usamos o break
para sair do loop) é um do
..while
escrito manualmente!
For
O for
é uma forma mais automatizada de loop, ele é mais usado para contagem, mas também é possível usá-lo com flag.
Em uma comparação direta com o while
:
// exibindo uma contagem até 5
// while
{
int i = 0;
while (i <= 5) printf("%i\n", i++);
}
// for
{
for ( int i = 0; i <= 5; i++) printf("%i\n", i);
}
“Caramba!! O que aconteceu aqui?” ... Se você não estiver entendido o código acima eu irei mostrar da forma tradicional:
// exibindo uma contagem até 5
// while
{
int i = 0; // dando o valor 0 a i
while (i <= 5) { // enquanto i menor ou igual a 5
printf("%i\n", i); // escreva i
i ++; // incremente i
}
}
// for
{
for ( int i = 0; i <= 5; i++ ) {
// para i entre 0 e 5 incremente i
printf("%i\n", i);
}
}
“Ainda não entendi o for
“ ... Note que temos três espaços entre os parenteses separados por ;
, no primeiro espaço você declara uma variável, no segundo você digita o teste lógico, e no terceiro você digita um incremento.
Basicamente o for
é uma gambiarra do while
, ainda utilizando o exemplo anterior observe um for escrito no estilo se um while
:
int i = 0;
for ( ; i <= 5 ; ){
printf("%i\n", i);
i++;
}
Os espaços entre
;
podem ficar em branco, mas convenhamos que é um tanto inútil usar umfor
desta maneira...
E as formas diversas de usar o for
são essas:
// usar variável já existente
int i;
for (i = 1; i <= 5; i++) printf("%i\n", i);
// criando variável local exclusiva para o uso do for
for ( int i = 1; i <= 5; i++) printf("%i\n", i);
// forma while
int i = 1;
for ( ; i <= 5; ) printf("%i\n", i++);
// forma de loop infinito com flag
int i = 1;
for (;;) {
printf ("%i\n", i++);
if ( i == 5 ) break;
}
Deu pra perceber que o for
é bem eclético não é mesmo? Mas definitivamente a forma em que ele é mais útil é a tradicional:
for ( int <nome da variável> = <valor inicial>; <teste lógico>; <incremento>) {
// comandos
}
// forma compacta
for ( int <nome da variável> = <valor inicial>; <teste lógico>; <incremento>) /* comando */;