Menu

Laço while em C: sintaxe, exemplos e erros comuns

Como o laço while do C repete até uma condição mudar - a regra da condição primeiro, laços com sentinela, ler entrada até o EOF, while(1) e como converter entre for e while.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Repetir sem uma contagem

Um laço for é a ferramenta certa quando você sabe - ou consegue calcular - quantas passagens precisa. Muito trabalho não vem com uma contagem. Ler cada linha de um arquivo até ele acabar. Continuar pedindo uma senha até ela estar certa. Dividir um número pela metade até chegar a 1. Nesses casos a pergunta não é "quantas vezes", e sim "até quando" - que é exatamente o que o while expressa.

Ninguém calculou "sete" de antemão. O laço simplesmente continua enquanto a condição vale.

Sintaxe e a regra da condição primeiro

while (condicao) {
    /* corpo - executa enquanto a condição for diferente de zero */
}

A condição é testada antes de cada passagem, inclusive a primeira. Três consequências:

  • Um laço cuja condição já começa falsa executa zero vezes. while (0) { ... } nunca executa o corpo.
  • O que a condição testa precisa estar inicializado antes do laço, ou você está testando um valor de lixo.
  • Algo no corpo precisa eventualmente tornar a condição falsa, ou o laço nunca termina.

Como no if, os parênteses são obrigatórios e não há ponto e vírgula depois deles. Esse ponto e vírgula perdido é a versão do mesmo bug para laços:

/* BUG: a instrucao vazia e o corpo - isto gira para sempre */
while (i < 10);
{
    printf("%d\n", i);
    i++;
}

i nunca é incrementado, então a condição nunca muda. O gcc -Wall sinaliza o corpo vazio.

A regra de veracidade do C vale aqui exatamente como no if/else: o laço continua enquanto a expressão for diferente de zero e para quando ela for zero.

O formato padrão: inicializar, testar, atualizar

Quase todo laço while correto tem três peças espalhadas por três lugares:

São as mesmas três partes que um cabeçalho for guarda, só que não reunidas em uma linha. Que é a resposta honesta para "for ou while?": se as três peças falam de um mesmo contador, um for as coloca onde quem lê pode conferi-las juntas. Se a atualização está espalhada por um corpo longo, ou a condição é sobre outra coisa que não uma contagem, o while é a forma mais clara.

Esquecer a peça 3 é o bug dos laços while. Se um laço trava, a primeira coisa a verificar é se o corpo realmente muda o que a condição lê.

Laços com sentinela

Uma sentinela é um valor especial que significa "pare". Some números até o usuário digitar 0:

O 99 depois do 0 nunca é alcançado - a sentinela encerrou o laço. Note que a quantidade de números nunca é conhecida de antemão, que é precisamente por que isto é um while.

As strings de C funcionam do mesmo jeito: elas terminam com uma sentinela '\0', então percorrer uma é um while de livro-texto:

Ler entrada até o EOF

O while mais comum do mundo real lê entrada até não haver mais. A regra é testar o valor de retorno da função de entrada, não o valor que ela guardou.

getchar devolve o próximo caractere, ou a constante EOF quando a entrada acaba:

Dois detalhes que importam. c é um int porque EOF é um valor negativo que não cabe em um char em muitos sistemas - declará-lo como char pode fazer a comparação nunca dar certo. E a atribuição fica dentro da condição: (c = getchar()) != EOF lê um caractere, guarda e compara em um passo só. Os parênteses internos são obrigatórios, porque != tem precedência maior que =; sem eles você guardaria em c o resultado da comparação. Este é um dos poucos lugares em que uma atribuição dentro de uma condição é idiomática em vez de um bug.

O mesmo formato funciona com scanf, cujo valor de retorno é a quantidade de itens convertidos com sucesso:

int n;
while (scanf("%d", &n) == 1) {
    /* n guarda um numero valido */
}

O laço termina no fim do arquivo e na primeira entrada que não for um número, que geralmente é o que você quer.

O que você não deve escrever é while (!feof(f)). feof informa se uma leitura falhou, então ele ainda é falso quando você está sobre o último item, o corpo do laço executa mais uma vez e a leitura falha - processando dados velhos. Teste a própria leitura.

while (1) e break

Às vezes a condição de saída só é conhecida no meio do corpo - depois de ler, mas antes de processar. A resposta idiomática é um laço intencionalmente infinito com uma saída explícita:

while (1) é sempre verdadeiro, então a única saída é break (ou return, ou exit). Você vai ver for (;;) usado com o mesmo propósito; os dois compilam para a mesma coisa, e qual deles um código prefere é questão de estilo.

Use esse formato quando o teste de saída realmente pertence ao meio do corpo. Quando o teste cabe naturalmente no topo, coloque-o na condição, onde quem lê consegue vê-lo - um while (1) cujo único break é a primeira instrução é apenas uma condição disfarçada.

Converter entre for e while

Qualquer laço for pode ser escrito como um while e vice-versa. O mapeamento é mecânico:

/* for */                          /* while equivalente */
for (init; cond; update) {         init;
    corpo;                         while (cond) {
}                                      corpo;
                                       update;
                                   }

Então estes dois imprimem a mesma coisa:

O único ponto em que a equivalência vaza é o continue. Em um laço for, continue salta para a atualização do cabeçalho, então o contador ainda avança. Na versão while, continue volta direto para a condição e pula o i++ no fim do corpo - um laço infinito instantâneo:

/* BUG: continue pula o i++, entao o laco gira para sempre no primeiro numero par */
int i = 0;
while (i < 10) {
    if (i % 2 == 0) {
        continue;
    }
    printf("%d ", i);
    i++;
}

Se um laço while usa continue, garanta que a atualização aconteça antes dele - ou use um for, cujo cabeçalho garante isso.

Armadilhas comuns

  • Nada atualiza a condição. O corpo precisa mudar o que a condição lê. Se um programa trava, olhe aqui primeiro.
  • Um ponto e vírgula depois do cabeçalho. while (cond); faz da instrução vazia o corpo.
  • Testar uma variável que nunca foi inicializada. A condição executa antes do corpo, então o valor que ela lê já precisa existir.
  • char em vez de int para getchar. EOF não cabe em um char; a comparação pode então nunca ser verdadeira, ou um byte legítimo pode ser confundido com EOF.
  • while (!feof(f)). Executa uma vez a mais. Teste a leitura.
  • Supor que o corpo executa pelo menos uma vez. Ele não executa. Quando você precisa de uma passagem garantida - imprimir um menu antes de verificar a escolha - isso é um laço do-while.

Perguntas frequentes

Como se escreve um laço while em C?

while (condicao) { corpo }. A condição é testada antes de cada passagem, então o corpo executa só enquanto a condição for diferente de zero, e nem uma vez se ela já começar falsa. Algo dentro do corpo precisa eventualmente mudar a condição, ou o laço nunca termina.

Qual é a diferença entre for e while em C?

Eles têm o mesmo poder - qualquer for pode ser reescrito como while. Use for quando um contador, seu limite e seu passo pertencem juntos a um cabeçalho, e while quando a condição de parada não é uma contagem: ler até o fim do arquivo, tentar de novo até dar certo, ou repetir até uma flag virar.

Como ler entrada até o EOF em C?

Teste o valor de retorno da função de entrada, não o valor que ela leu: while (scanf("%d", &n) == 1) { ... } para no fim do arquivo ou na primeira entrada não numérica, e while ((c = getchar()) != EOF) { ... } lê caractere por caractere. Nunca faça o laço com while (!feof(f)) - ele executa uma vez a mais depois do fim.

Por que meu laço while é infinito em C?

Normalmente porque nada no corpo muda o valor que a condição testa, ou porque um ponto e vírgula perdido depois do cabeçalho (while (i < 10);) transformou a instrução vazia no corpo. Os dois compilam sem reclamar, então verifique se o corpo realmente atualiza a variável da condição.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR