Menu

Laço do-while em C: sintaxe, exemplos e quando usar

O laço do C que executa o corpo primeiro: como o do-while garante uma passagem antes de testar, por que ele termina com ponto e vírgula, os padrões de menu e de nova tentativa para os quais foi feito, e como se diferencia do while simples.

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

O laço que sempre executa uma vez

Um laço while testa antes de agir, então pode executar zero vezes. Isso normalmente está certo. Às vezes está exatamente errado: você não tem como saber se deve repetir um pedido antes de tê-lo exibido, e não tem como julgar a entrada do usuário antes de ter lido alguma. O do-while move o teste para o fim, então o corpo executa primeiro e a condição decide apenas se vai de novo.

A condição i < 5 é falsa desde o início. O laço while executa zero vezes; o do-while executa exatamente uma. Essa é toda a diferença entre os dois.

Sintaxe, e aquele ponto e vírgula

do {
    /* corpo - sempre executa pelo menos uma vez */
} while (condicao);

A ordem se lê do jeito que executa: faça (do) o corpo, enquanto (while) a condição ainda valer, faça de novo.

O ponto e vírgula depois do parêntese de fechamento é obrigatório. do ... while (cond); é uma instrução, e instruções em C terminam em ponto e vírgula. Omita-o e o compilador continua lendo, depois relata um erro de sintaxe em algum ponto abaixo - por isso o erro real costuma estar várias linhas acima da linha apontada.

Este também é o único lugar em C onde while (cond); com ponto e vírgula está correto em vez de ser um bug. Em um laço while comum, a mesma pontuação cria um corpo vazio e normalmente um laço infinito; aqui ela está fechando um do.

As chaves são opcionais para um corpo de uma instrução só mas, como em toda outra estrutura de controle do C, escreva-as mesmo assim.

O padrão de validação de entrada

É para isto que o do-while foi projetado. Você precisa ler algo antes de poder dizer se é aceitável, então a leitura tem que acontecer antes do teste:

O laço continua lendo até um valor passar, e a mesma condição que rejeita um valor ruim é a que pede outra passagem. Escrita como um while, a leitura teria que aparecer duas vezes - uma antes do laço para preparar a condição, outra no fim do corpo - que é a duplicação que o do-while elimina.

Com entrada real, o corpo chamaria scanf:

int idade;
do {
    printf("Digite sua idade (1-120): ");
    if (scanf("%d", &idade) != 1) {
        while (getchar() != '\n') { }   /* descarta a linha ruim */
        idade = -1;                      /* forca outra passagem */
    }
} while (idade < 1 || idade > 120);

Note o while interno que esvazia o resto da linha. Se o scanf falha ao converter, o texto problemático continua no buffer de entrada e toda leitura posterior falha nele também - um laço que gira para sempre imprimindo o pedido. Limpá-lo faz parte do padrão.

O padrão de menu

O outro uso clássico: mostrar as opções, ler uma escolha, agir sobre ela e repetir até o usuário sair. O menu precisa aparecer antes de existir qualquer escolha a testar.

O break dentro do switch encerra o switch, não o laço - um ponto que vale precisar, já que os dois usam a mesma palavra-chave. Aqui o laço termina porque escolha != 4 se torna falso. Se você quisesse mesmo sair do laço de dentro do switch, return ou uma variável de flag seriam o caminho; o break sozinho não consegue.

Uma primeira passagem garantida pode ser um bug

Como o corpo executa antes de qualquer teste, o do-while processa alegremente dados que não existem:

/* BUG: imprime a[0] mesmo quando n e 0 */
int i = 0;
do {
    printf("%d\n", a[i]);
    i++;
} while (i < n);

Com n == 0 isso lê a[0] em um array vazio - comportamento indefinido. Qualquer laço sobre uma coleção que possa estar vazia quer um while ou um for, cujo teste vem primeiro.

A regra prática: use do-while só quando uma execução de zero iterações for impossível pela natureza do problema, não apenas improvável na prática. Pedir algo ao usuário, jogar dados até um alvo aparecer, gerar e testar um candidato - esses genuinamente não podem ser julgados antes da primeira passagem. Percorrer uma lista não pode alegar isso.

break e continue em um do-while

Os dois funcionam, e o continue tem uma peculiaridade que vale conhecer: ele salta para o teste da condição, não para o topo do corpo.

O i++ no topo do corpo executa em toda passagem, inclusive nas que o continue interrompe, então o laço continua avançando. Coloque a atualização depois de um continue e o laço trava - a mesma armadilha dos laços while.

O break sai do laço imediatamente e pula a condição por completo.

Escolhendo entre os três laços

Os três laços do C têm o mesmo poder; a escolha é sobre qual deles declara a intenção.

for        um contador, seu limite e seu passo pertencem juntos - "n vezes"
while      repete até uma condição mudar, e talvez nem uma vez - "até que"
do-while   o mesmo, mas a primeira passagem e garantida - "pelo menos uma vez"

Na prática o do-while é de longe o mais raro dos três. A maioria dos laços ou conta ou precisa tratar o caso vazio, e ambos querem o teste no topo. Recorra ao do-while quando se pegar duplicando uma instrução logo antes de um laço while para preparar a condição dele - essa duplicação é o sinal.

Perguntas frequentes

Como se escreve um laço do-while em C?

do { corpo } while (condicao); - o corpo vem primeiro, o teste vem depois, e a instrução inteira termina com um ponto e vírgula. O corpo sempre executa pelo menos uma vez e depois se repete enquanto a condição for diferente de zero.

Qual é a diferença entre while e do-while em C?

Onde fica o teste. Um laço while verifica a condição antes da primeira passagem, então pode executar zero vezes. Um do-while verifica depois, então sempre executa pelo menos uma vez. Escolha do-while só quando essa primeira passagem garantida for genuinamente o que o problema exige.

Por que um laço do-while precisa de ponto e vírgula no fim?

Porque do ... while (cond); é uma única instrução e, como toda instrução em C, termina com ponto e vírgula. Omiti-lo produz um erro de sintaxe confuso apontando para a linha seguinte, já que o compilador continua lendo à procura do resto da instrução.

Quando devo usar um laço do-while?

Quando o corpo precisa executar antes de você ter como saber se deve repetir: exibir um menu antes de ler a escolha, pedir de novo até a entrada ser válida, ou gerar um valor e então testá-lo. Se a condição pode ser verificada de antemão, um laço while diz isso de forma mais direta.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR