#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("----------------------------------------\n");
printf(" Boucle for\n");
printf("----------------------------------------\n");
#if 0
for (initialisation ; condition ; itération)
bloc
#endif
/* 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. */
int i;
for (i = 0; i < 3; i++)
{
printf("i = %d\n", i);
}
/* 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. */
// En C99 :
for (int j = 0; j < 3; j++)
{
printf("j = %d\n", j);
}
// Le bloc de code étant réduit à une instruction, on aurait pu écrire :
for (int k = 0; k < 3; k++)
printf("k = %d\n", k);
int l = 0;
for( ; l != 1; l = rand() % 4)
{
printf("je continue\n");
}
/* cet exemple montre plusieurs choses :
1. 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) ;
2. l'expression itération est réellement une expression, on peut y faire appel à
des fonctions ;
3. le nombre d'itérations n'est pas fixe, le programme affichera « je continue »
un nombre (pseudo-)aléatoire de fois. */
printf("\n----------------------------------------\n");
printf(" Boucle while\n");
printf("----------------------------------------\n");
#if 0
while (condition)
bloc
#endif
// Une boucle while exécute le bloc d'instructions tant que la condition est vérifiée.
int m = 0;
while (m < 3)
{
printf("m = %d\n", m);
m = m + 1;
}
printf("\n----------------------------------------\n");
printf(" Boucle do-while\n");
printf("----------------------------------------\n");
#if 0
do
bloc
while (condition);
#endif
/* 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). */
int n = 0;
do
{
printf("n = %d\n", n);
n = n + 1;
} while (n < 3);
char c;
do
{
printf("Veuillez taper la lettre 'o'\n");
scanf("%c", &c);
getchar();
} while (c != 'o');
/* Tant que l'utilisateur n'aura pas tapé la lettre o, le programme redemandera de
taper la lettre. */
printf("\n----------------------------------------\n");
printf(" Arrêt et continuation des boucles\n");
printf("----------------------------------------\n");
/* Il 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 boucle for, while ou do-while. À noter
que si la boucle se trouve elle-même dans une autre boucle, seule la boucle où le
l'instruction break se trouvait est stoppée. */
/* continue permet de recommencer la boucle depuis le début du bloc. Dans le cas de
la boucle for, le bloc lié à l'incrémentation sera exécuté, puis dans tous les
cas, la condition sera testée. */
printf("\n----------------------------------------\n");
printf(" Saut inconditionnel (goto)\n");
printf("----------------------------------------\n");
/* Cette 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. */
#if 0
void boucle(void)
{
while (1)
{
struct Evenement_t * event;
attend_evenement();
while ((event = retire_evenement()))
{
switch (event->type) {
case FIN_TRAITEMENT:
goto fin;
/* ... */
}
}
}
fin:
/* ... */
}
#endif
/* 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. */
return 0;
}