Programmation C/Itérations
Boucle for
modifierSyntaxe
modifierfor (initialisation ; condition ; itération)
bloc
Une boucle for commence par l'initialisation, puis exécute le bloc de code tant que la condition est vérifiée et en appelant l'itération après chaque bloc.
On peut tout de suite remarquer que la boucle for du C est beaucoup plus puissante qu'une boucle for classique, dans le sens où elle ne correspond pas forcément à un nombre fini de tours de boucle.
La norme C99 permet maintenant de déclarer des variables dans la partie initialisation de la boucle for. Ces variables ne peuvent qu'être de classe automatic ou register. Leur portée est limitée à la boucle. Elles n'interfèrent pas avec les variables de même nom déclarées en dehors de la boucle. Leur utilisation pourrait conduire à de possibles optimisations du code par le compilateur.
Exemples
modifierExemple 1
modifierint i;
for (i = 0 ; i < 10 ; i++)
{
printf("%d\n", i);
}
En C++ :
for (int i = 0 ; i < 10 ; i++)
{
printf("%d\n", i);
}
Cet exemple est une boucle for normale, l'indice de boucle i est incrémenté à chaque tour et le bloc ne fait qu'afficher l'indice. Ce code affiche donc les 10 premiers entiers en partant de 0. Le bloc de code étant réduit à une instruction, on aurait pu écrire :
int i;
for (i = 0 ; i < 10 ; i++)
printf("%d\n", i);
Exemple 2
modifierint i = 0;
for( ; i != 1 ; i = rand() % 4)
{
printf("je continue\n");
}
Ce deuxième exemple montre plusieurs choses :
- l'initialisation de la boucle a été omise, en fait n'importe laquelle des trois parties peut l'être (et même les trois à la fois, ce qui résulte en une boucle infinie) ;
- l'expression itération est réellement une expression, on peut y faire appel à des fonctions ;
- le nombre d'itérations n'est pas fixe, le programme affichera « je continue » un nombre (pseudo-)aléatoire de fois.
for(;;)
crée une boucle infinie.Boucle while
modifierSyntaxe
modifierwhile (condition)
bloc
Une boucle while exécute le bloc d'instructions tant que la condition est vérifiée.
Exemple
modifierint i = 0;
while (i < 10)
{
printf("%d\n", i);
i = i + 1;
}
Cet exemple est le même que celui vu précédement pour la boucle for, il affiche les dix premiers entiers à partir de 0.
Boucle do-while
modifierSyntaxe
modifierdo
bloc
while (condition);
Cette boucle est une légère variante de la précédente. Elle exécute donc le bloc au moins une fois, et ce jusqu'à ce que la condition soit fausse (ou tant que la condition est vraie).
Exemple 1
modifier#include <stdio.h>
int main(void)
{
int i = 0;
do
{
printf("%d\n", i);
i = i + 1;
} while (i < 10);
return 0;
}
Exemple identique à celui de la boucle while au dessus, on affiche les nombres de 0 jusqu'à 9.
Exemple 2
modifier#include <stdio.h>
int main(void)
{
char c;
do
{
printf("Veuillez taper la lettre 'o'\n");
scanf("%c", &c);
} while (c != 'o');
return 0;
}
Cette fois on voit l'utilité de la boucle do-while, la variable est initialisée dans la boucle. On doit tester sa valeur à la fin de l'itération. Tant que l'utilisateur n'aura pas tapé la lettre o, le programme redemandera de taper la lettre.
Exemple 3
modifierArrêt et continuation des boucles
modifierIl arrive fréquemment qu'en évaluant un test à l'intérieur d'une boucle, on aimerait arrêter brutalement la boucle ou alors « sauter » certains cas non significatifs. C'est le rôle des instructions break
et continue
.
break
permet de sortir immédiatement d'une bouclefor
,while
oudo-while
. À noter que si la boucle se trouve elle-même dans une autre boucle, seule la boucle où l'instructionbreak
se trouvait est stoppée.
continue
permet de recommencer la boucle depuis le début du bloc. Dans le cas de la bouclefor
, le bloc lié à l'incrémentation sera exécuté, puis dans tous les cas, la condition sera testée.
Saut inconditionnel (goto)
modifierCette instruction permet de continuer l'exécution du programme à un autre endroit, dans la même fonction. On l'utilise de la manière suivante :
goto label;
Où label est un identificateur quelconque. Cet identificateur devra être défini quelque part dans la même fonction, avec la syntaxe suivante :
label:
Ce label peut être mis à n'importe quel endroit dans la fonction, y compris avant ou après le goto
, ou dans un autre bloc que là où sont utilisés la ou les instructions goto
pointant vers ce label. Les labels doivent être uniques au sein d'une même fonction, mais on peut les réutiliser dans une autre fonction.
Un cas où l'emploi d'une instruction goto
est tout à fait justifié, par exemple, est pour simuler le déclenchement d'une exception, pour sortir rapidement de plusieurs boucles imbriquées.
void boucle(void)
{
while (1)
{
struct Evenement_t * event;
attend_evenement();
while ((event = retire_evenement()))
{
switch (event->type) {
case FIN_TRAITEMENT:
goto fin;
/* ... */
}
}
}
fin:
/* ... */
}
Dans ce cas de figure, il serait possible d'utiliser aussi un booléen qui indique que le traitement est terminé, pour forcer la sortie des boucles. L'utilisation de goto
dans cet exemple ne nuisant pas à la lisibilité du programme et étant tout aussi efficace, il est tout à fait légitime de l'utiliser.
Il faut cependant noter que cette instruction est souvent considérée comme à éviter. En effet, elle provoque un saut dans le code, qui se « voit » beaucoup moins bien que les structures de contrôle comme if
ou while
, par exemple. De fait, la pratique a montré qu'un abus de son utilisation rend un code source rapidement peu compréhensible, et difficilement maintenable. L'article de Edsger W. Dijsktra Go to considered harmful anglais, datant de 1968, est l'exemple le plus connu de cette critique, qui a donné naissance à la programmation structurée.