do...while
On a souvent besoin de répéter un bout de programme tant qu'une condition est vraie (par exemple tant que la précision d'un calcul est insuffisante). Le C propose les deux structures suivantes pour cela:
while (condition) { /* structure 1: condition à l'entrée du code */ instructions à répéter; } do { /* structure 2: condition à la sortie du code */ instructions à répéter; } while (condition);
Le bloc entre les accolades {}
est répété dans les deux
cas tant que la conditions est vraie. Dans le cas de la première
structure, la condition est évaluée en tout premier, il est donc
possible (si la condition est fausse dès le départ) que les
instructions ne soient pas exécutés du tout. Avec la deuxième
structure on sait en revanche que les instructions seront exécutées au
moins une fois, puisque la condition est évaluée à la fin de chaque
répétition.
Parfois on aimerait faire évaluer la condition ni au début, ni à la
fin de la boucle, mais quelque part au milieu (voir l'exemple qui
suit). L'astuce consiste alors à créer une boucle infinie (condition
toujours vraie) et à utiliser l'instruction break
, qui
fait sortir immédiatement de la boucle:
while (1) { /* structure 3: condition dans la boucle */
instructions...;
if (condition) break;
instructions...;
}
for ( ; ; ) ...
Il arrive fréquemment qu'on veuille exécuter une suite d'instructions
un nombre connu de fois (par exemple pour évaluer une fonction en
N points). On utilise alors la construction for ( ; ; ) ...
,
dont la syntaxe générale est:
for (initialisation du compteur ; condition testée à chaque pas ; modification du compteur) { bloc d'instructions exécuté à chaque pas de la boucle ; }
Elle est strictement équivalente à
initialisation du compteur ; while (condition testée à chaque pas) { bloc d'instructions exécuté à chaque pas de la boucle ; modification du compteur ; }
mais elle est en général plus lisible (si on ne met que le stricte nécessaire à l'intérieur des parenthèses, notamment une condition simple: > , < , ==, ...). Par exemple, pour calculer la somme des 100 premiers entiers :
int main(void) { int i, somme; somme = 0; /* on initialise la somme a 0 */ for (i=1 ; i<=100 ; i=i+1) { /* boucle, i varie de 1 a 100, par pas de 1 */ somme = somme + i ; /* on ajoute la valeur actuelle de i a la somme */ } printf ("%d\n", somme) ; /* le résultat est écrit a l'écran */ return 0; }
Dans cet exemple la boucle est exécutée 100 fois (le compteur vaut
successivement 1,2,3,...,100), et la valeur du compteur i
à la sortie de la boucle est 101 (la boucle est quittée quand la
condition devient fausse, ce qui arrive pour la première fois pour
cette valeur).
Comme pour les conditions, on décale les blocs à exécuter pour plus de
clarté; voir le chapître entrées/sorties pour le
printf
.
Comme pour les boucles while
, on peut utiliser
break
pour sortir de la boucle. On pourrait par exemple
réécrire notre exemple précédent sous la forme :
i = 1 ; for ( ; ; ) { /* boucle infinie */ somme = somme + i ; if (i == 100) break ; /* condition d'arrêt */ i = i + 1 ; }
Le paragraphe précédent illustre la liberté que le C donne au programmeur pour l'écriture de boucles: une même boucle peut être écrite de nombreuses manières équivalentes. Profitez en pour penser avant tout à la clarté de l'organisation de votre code. Il s'est en particulier cristallisé un certain nombre d'"expressions figées" très usitées et particulièrement claires. Adoptez-les dès le début, elles diminueront la probabilité de faire une erreur (toute construction exotique sautera aux yeux et fera réfléchir).
Dans une boucle, on effectue souvent une incrémentation simple d'une variable :
i = i + 1 ;
Le C permet une écriture plus compacte de ce type d'expression
grâce aux opérateurs de type +=
:
notation longue | notation courte équivalente |
i = i + 5 ; | i += 5 ; |
i = i - 9 ; | i -= 9 ; |
i = i / 7 ; | i /= 7 ; |
i = i * 2 ; | i *= 2 ; |
Enfin, dans le cas des opération +
et -
, et
si la modification est d'une unité (incrément ou décrément), il y a
deux opérateurs spéciaux ++
et --
:
i++ ; // augmente la valeur de i d'une unité i-- ; // diminue la valeur de i d'une unité
Faites attention en mélangeant ces opérateurs abrégés avec d'autres opérations:
int i,j ; i = 2; /* i vaut 2 */ j = i++; /* i vaut 3 et j vaut 2 */ i = 2; /* i vaut 2 */ j = ++i; /* i et j valent 3 */
Dans le cas des opérateurs i++
ou i--
, la
variable est bien modifiée d'une unité, mais uniquement
après avoir utilisé son ancienne valeur pour le reste
de l'expression (on parle de "post-(in/de)crémentation"). À l'inverse,
les opérateurs ++i
ou --i
modifient la
variable avant que sa valeur soit considéré pour le
reste de l'expression ("pré-(in/de)crémentation").
for
100
fois une suite d'instructions s'écrit
int i, n = 100; for (i=0 ; i<n; i++) { instructions; }
Affichez, compilez et exécutez les programmes suivants :
prog4.c : boucle 'for'
prog5.c : boucle 'for' : opérateur +=
prog6.c : boucle 'for' : opérateur ++