• Aucun résultat trouvé

Les répétitions : for, while, do…while, continue, break

On veut pouvoir répéter une action (c'est-à-dire une suite d'instructions) un certain nombre de fois. Deux cas se présentent :

• le nombre de répétitions est prévisible (c'est le cas le plus fréquent) ; on utilise alors de préférence l'instruction for ;

• la répétition de l'action doit avoir lieu tant qu'une condition est vraie, sans qu'on puisse prévoir

le nombre de répétitions qui seront nécessaires ; on utilise alors de préférence les instructions

while et do while.

5.1.1

L'instruction while

L'itération while permet de répéter une action tant qu'une condition est vraie, sans connaître à l’avance le nombre de répétitions.

Elle réalise l'instruction en « pseudo-code » suivante :

tant que condition vraie faire { ... }

Sa syntaxe en Langage C est :

Les instructions du bloc instructions sont répétées tant que l'expression condition reste vraie (non nulle). Cette expression est testée avant l'exécution de l'itération : si l'expression est fausse (nulle) dès le départ, les instructions ne seront jamais exécutées.

Pas de point-virgule sur la ligne while !

L'instruction à répéter peut être simple ou composée (c'est-à-dire formée d'une séquence d'instructions appelée bloc) ; le bloc d'instructions est entouré d'accolades { et }.

Exemple 23. Utilisation de while pour répéter une saisie

avec calcul par une boucle for de la factorielle n! = n*(n-1)* ...*2*1

while ( condition )

{

instructions ;

Sauf cas particulier (par exemple en informatique industrielle sur un microcontrôleur), il faut absolument éviter les boucles infinies du style :

while(1) {…}

Une telle boucle est syntaxiquement correcte (1 est non nul, donc la condition est toujours vraie). Mais sur un PC, elle est douteuse du point de vue programmation et on peut toujours l'éviter.

Si on utilise ce genre de boucle, il faut prévoir une possibilité de sortie, par return (voir

chapitre "Fonctions") ou par break (voir paragraphe correspondant) ou par la fonction exit

(qui met fin à l'exécution du programme).

5.1.2

L'instruction do while

Comme while, l'itération do while permet de répéter une action tant qu'une condition est vraie. Mais la condition est cette fois testée en fin d'itération.

Elle réalise donc l'instruction en « pseudo-code » suivante :

répéter { ... }

tant que condition vraie

Sa syntaxe est : do { instruction(s) ; } while ( condition ) ;

Le traitement est effectué une première fois, puis la condition est testée. Si elle est vraie, on répète le traitement ; sinon l'exécution passe à l'instruction suivante.

A la différence de while, la condition est testée après l'exécution de l'itération : le traitement a donc lieu au

moins une fois, même si l'expression de la condition est fausse (nulle) dès le départ.

Cette fois, il y a un point-virgule sur la ligne while : il s'agit en effet de la fin de

l'instruction.

Exemple 24. Utilisation de do ... while

Une boucle while correctement initialisée peut souvent être utilisée à la place d’un do… while.

void main(void) {

short int n=-1 ; /* valeur par défaut pour prévenir certaines erreurs de saisie */ do

{

printf("\n Entrez un entier positif : ") ; rewind(stdin) ;

scanf("%hd", &n) ; }

while (n<0) ; /* reboucle aussi si on tape une lettre */

printf("\n La racine carree de %hd est %lf", n, sqrt(n) ) ; }

5.1.3

L'instruction for

C'est l'itération la plus utilisée, grâce en particulier à son utilité pour les tableaux. En général, elle est employée quand le nombre de répétitions est prévisible

Dans sa forme la plus utile et la plus simple, elle fait intervenir l'initialisation d'un compteur, son incrémentation et un test de fin de comptage.

(dès la compilation ou bien à l'exécution).

Sa syntaxe générale est :

Dans cette syntaxe figurent trois expressions séparées par des points virgule :

• l'action initiale est effectuée avant l'itération ; elle consiste souvent à initialiser le compteur de boucle ;

• le test de continuation de boucle (et non de fin de boucle !) est une expression qui est évaluée à

chaque début

• l'action d'évolution modifie la valeur de la condition : elle consiste souvent à incrémenter le compteur de boucle. Elle est effectuée

d'itération : tant que l'expression est vraie (non nulle), les instructions sont

exécutées ;

à chaque fin

Voici un premier exemple, le plus courant : celui où un compteur de boucle (cpt) permet de répéter une action un nombre de fois connu (ici, 100).

d'itération (après les instructions et avant le

test de continuation).

Les trois expressions qui composent l'instruction for sont facultatives.

Les instructions for et while sont en réalité équivalentes en Langage C. Mais for est plus

compacte, donc plus utilisée.. En effet, l'instruction :

for ( expr1 ; expr2 ; expr3 ) {

instructions ; }

peut toujours être remplacé par :

expr1 ; /* action initiale (avant l’itération) */

while( expr2 ) /* test de continuation (en début d’itération)*/ {

instructions ;

expr3 ; /* action d’évolution (effectuée en fin d’itération) /* }

for ( [action initiale] ; [test de continuation] ; [action d'evolution] )

{

instructions ;

}

for ( cpt=1 ; cpt<=100 ; cpt++ ) { Action_à_répéter_100_fois() ; }

Exemple 25. Utilisation de la boucle for

Exemple 26. Boucles for imbriquées

Ce programme affiche : ligne=1 colonne=3 colonne=2 colonne=1 ligne=2 colonne=3 colonne=2 colonne=1 ligne=3 colonne=3 colonne=2 colonne=1

boucle terminée : ligne=4 (eh oui...)

void main(void) {

short int lig, col ;

for (lig=1 ; lig<=3 ; lig++)

{

printf("\n ligne=%hd", lig) ;

for (col=3 ; col>0 ; col--)

printf("\n\t colonne=%hd",col) ;

}

printf("\n boucle terminee : ligne=%hd", lig) ; }

Exemple 1 : affiche les entiers de 1 à 10 inclus

void main(void) {

short int i ;

for (i=1 ; i<=10 ; i++)

printf("\n i=%hd",i) ; /* accolades optionnelles car une seule instruction */ /* attention : à la sortie de la boucle, i vaut maintenant 11 ! */

}

Exemple 2 : calcul de la factorielle de n n! = n*(n-1)*(n-2)* ...*3*2*1

void main(void) {

short int n=5, copie_n ; /* n est initialisé à 5 pour le test */

double fact ; /* réel pour éviter les dépassements dans le calcul */

fact=1.0 ;

for ( copie_n=n ; copie_n>1 ; copie_n-- )

fact = fact * copie_n ; /* accolades optionnelles car une seule instruction */

printf("\n La factorielle demandee est %12.5le", fact) ; }

5.1.4

L'instruction continue

L'instruction continue insérée dans une boucle permet de sauter les instructions restantes du traitement en cours, puis de continuer l'itération. L'action d'évolution est exécutée dans le cas du for. Le test de continuation est effectué dans tous les cas.

Comme pour l'instruction break qui suit, il faut éviter d'utiliser ce genre d'instructions de

"rupture de boucle" (auxquelles appartient le célèbre et hideux goto, strictement prohibé).

Le bon programmeur trouve généralement une autre solution...

Les instructions de ruptures de séquence sont à réserver aux « sorties d’urgence » (quand le programme risque de « planter » si on continue). C’est le marteau brise-vitre des trains !

Exemple 27. Utilisation de continue dans une itération

Exemple syntaxiquement correct, mais douteux du point de vue de la qualité de programmation.

Cet exemple montre ce qu’il ne faut pas faire : répéter une action en sautant une partie de l’itération avec

continue. Pour éviter d’exécuter la ligne printf… sans utiliser l’instruction continue, la bonne solution

consiste à l’intégrer dans un if bien écrit (remarquez l’inversion de la condition…) :

Exemple 28. Remplacement de continue dans une itération for

5.1.5

L'instruction break

L'instruction break permet de sortir de toute itération (for, while ...) qui la contient. Son effet est limité à un seul niveau d'imbrication.

Elle est surtout utilisée avec l'instruction switch qui sera étudiée au paragraphe correspondant.

A l'exception de son utilisation dans switch, break doit être évitée au même titre que continue : les "ruptures de boucle" ne sont pas les bienvenues dans une programmation propre.

void main(void) /* EXEMPLE A NE PAS SUIVRE ! */ {

short int i ; for (i=1 ; i<5 ; i++)

{

printf("\n La valeur %hd de i vous convient-elle <o/n> ?", i) ; rewind(stdin); /* vide le tampon pour la lecture d'un caractère */ if (getchar()=='n') continue ; /* saut conditionnel à l'itération suivante */ printf("\n La valeur i=%hd est retenue", i) ;

} }

void main(void) {

short int i ;

for (i=1 ; i<5 ; i++) {

printf("\n La valeur %hd de i vous convient-elle <o/n> ?", i) ; rewind(stdin); /* vide le tampon pour la lecture d'un caractère */ if (getchar() != 'n') /* la ligne suivante sera exécutée sous condition */ printf("\n La valeur i=%hd est retenue", i) ;

} }

break permet de sortir de boucles apparemment infinies du type while(1)2

while(1) /* on évite au maximum cette boucle infinie (sauf sur microcontrôleur) */

. Mais aucune programmation propre (hors microcontrôleur) n'utilise ce genre de boucle infinie !

{ ...

if (expression) break ; ...

}

Dans ce cas, on ne connaît pas à l’avance le nombre d’itérations. Donc la bonne solution consiste à utiliser une boucle while avec une condition bien écrite.

5.2. Les exécutions conditionnelles : if…else, switch, ?: