La boucle qui s'exécute toujours une fois
Une boucle while teste avant d'agir, elle peut donc s'exécuter zéro fois. C'est généralement ce qu'il faut. Parfois c'est exactement l'inverse : vous ne pouvez pas savoir s'il faut répéter une invite avant de l'avoir affichée, et vous ne pouvez pas juger la saisie d'un utilisateur avant d'en avoir lu un peu. do-while déplace le test à la fin : le corps s'exécute d'abord et la condition décide seulement s'il faut recommencer.
La condition i < 5 est fausse dès le départ. La boucle while s'exécute zéro fois ; la do-while exactement une. C'est toute la différence entre elles.
La syntaxe, et ce point-virgule
do {
// corps - s'execute toujours au moins une fois
} while (condition);
L'ordre se lit comme il s'exécute : fais le corps, tant que la condition tient, refais-le.
Le point-virgule final après la parenthèse fermante est obligatoire. do ... while (cond); est une instruction, et les instructions C se terminent par un point-virgule. Omettez-le et le compilateur continue de lire, puis signale une erreur de syntaxe plus bas - c'est pourquoi la vraie faute est souvent à plusieurs lignes de celle que l'erreur pointe.
C'est aussi le seul endroit en C où while (cond); avec un point-virgule est correct plutôt qu'un bug. Dans une simple boucle while, la même ponctuation crée un corps vide et généralement une boucle infinie ; ici, elle ferme un do.
Les accolades sont facultatives pour un corps d'une seule instruction mais, comme pour toute autre structure de contrôle C, écrivez-les quand même.
Le motif de validation de saisie
C'est ce pour quoi do-while a été conçu. Vous devez lire quelque chose avant de pouvoir dire si c'est acceptable, donc la lecture doit avoir lieu avant le test :
La boucle continue de lire jusqu'à ce qu'une valeur passe, et la condition même qui rejette une mauvaise valeur est celle qui demande un nouveau passage. Écrite en while, la lecture devrait apparaître deux fois - une avant la boucle pour amorcer la condition, une à la fin du corps - c'est cette duplication que do-while supprime.
Avec une vraie saisie, le corps appellerait scanf :
int age;
do {
printf("Entrez votre age (1-120) : ");
if (scanf("%d", &age) != 1) {
while (getchar() != '\n') { } /* jeter la ligne fautive */
age = -1; /* forcer un nouveau passage */
}
} while (age < 1 || age > 120);
Notez le while interne qui vide le reste de la ligne. Si scanf échoue à convertir, le texte fautif reste dans le tampon d'entrée et toutes les lectures ultérieures échouent dessus aussi - une boucle qui tourne indéfiniment en affichant l'invite. Le vider fait partie du motif.
Le motif du menu
L'autre usage classique : afficher les options, lire un choix, agir dessus, et répéter jusqu'à ce que l'utilisateur quitte. Le menu doit apparaître avant qu'il y ait un choix à tester.
Le break dans le switch termine le switch, pas la boucle - un point qui mérite d'être précis, puisque les deux utilisent le même mot-clé. Ici, la boucle se termine parce que choice != 4 devient faux. Si vous vouliez vraiment quitter la boucle depuis le switch, return ou une variable drapeau seraient la solution ; break seul ne peut pas le faire.
Un premier passage garanti peut être un bug
Parce que le corps s'exécute avant tout test, do-while traitera volontiers des données qui n'existent pas :
/* BUG: affiche a[0] meme quand n vaut 0 */
int i = 0;
do {
printf("%d\n", a[i]);
i++;
} while (i < n);
Avec n == 0, ceci lit a[0] sur un tableau vide - comportement indéfini. Toute boucle sur une collection potentiellement vide veut un while ou un for, dont le test vient en premier.
La règle empirique : n'utilisez do-while que quand une exécution à zéro itération est impossible par nature du problème, et non simplement improbable en pratique. Interroger un utilisateur, lancer des dés jusqu'à obtenir une cible, générer et tester un candidat - tout cela ne peut réellement pas être jugé avant le premier passage. Parcourir une liste ne peut pas prétendre à cela.
break et continue dans un do-while
Les deux fonctionnent, et continue a une subtilité à connaître : il saute vers le test de condition, pas vers le début du corps.
Le i++ en haut du corps s'exécute à chaque passage, y compris ceux que continue interrompt, donc la boucle avance quand même. Mettez la mise à jour après un continue et la boucle bloque - le même piège que dans les boucles while.
break quitte la boucle immédiatement et saute entièrement la condition.
Choisir entre les trois boucles
Les trois boucles du C sont également puissantes ; le choix porte sur celle qui exprime l'intention.
for un compteur, sa limite et son pas vont ensemble - "n fois"
while repeter jusqu'a ce qu'une condition change, peut-etre jamais - "jusqu'a"
do-while pareil, mais le premier passage est garanti - "au moins une fois"
En pratique, do-while est de loin la plus rare des trois. La plupart des boucles soit comptent, soit doivent gérer le cas vide, et les deux veulent le test en haut. Prenez do-while quand vous vous surprenez à dupliquer une instruction juste avant une boucle while pour amorcer sa condition - cette duplication est le signal.
Questions fréquentes
Comment écrit-on une boucle do-while en C ?
do { corps } while (condition); - le corps vient d'abord, le test après, et toute l'instruction se termine par un point-virgule. Le corps s'exécute toujours au moins une fois, puis se répète tant que la condition est non nulle.
Quelle est la différence entre while et do-while en C ?
La position du test. Une boucle while vérifie la condition avant le premier passage, elle peut donc s'exécuter zéro fois. Une do-while vérifie après, elle s'exécute donc toujours au moins une fois. Ne choisissez do-while que quand ce premier passage garanti est vraiment ce dont le problème a besoin.
Pourquoi une boucle do-while a-t-elle besoin d'un point-virgule à la fin ?
Parce que do ... while (cond); est une instruction unique, et comme toute autre instruction C, elle se termine par un point-virgule. L'omettre produit une erreur de syntaxe déroutante pointant la ligne suivante, puisque le compilateur continue de lire pour trouver la suite de l'instruction.
Quand faut-il utiliser une boucle do-while ?
Quand le corps doit s'exécuter avant qu'on puisse savoir s'il faut répéter : afficher un menu avant de lire un choix, redemander jusqu'à ce que la saisie soit valide, ou générer une valeur puis la tester. Si la condition peut être vérifiée d'avance, une boucle while le dit plus clairement.