CHAPITRE III PROGRAMMATION C LES ACTIONS ITÉRATIVES Par : Khaled Hassine Khaled.hassine@fsg.rnu.tn Khaled Hassine 1 Khaled Hassine 2 Khaled Hassine 3 Khaled Hassine 4 LFSI 1 LARI 1 1
Besoin des boucles Boucle en C Pour des nombreux problèmes, il est nécessaire de pouvoir exprimer qu'une action simple ou composée doit être exécutée plusieurs fois. Or, les actions simples (affectation, lecture et écriture) et conditionnelles (si, selon, etc.) ne permettent pas d'exprimer ceci, alors que les actions itératives (dites aussi répétitives) permettent de contrôler la répétition d'une même action. On parle de boucle. L'exemple trivial qu'on peut traiter avec des telles structures est les traitements des suites. Avant de détailler les structures itératives, signalons que tout programme peut être exprimé par l'une (ou une combinaison) des trois structures : séquences, conditionnelles, itératives. Ce sont donc les structures de base pour l'écriture d'un programme. C dispose de deux déclarations possibles des traitements itératifs : la déclaration for et la déclaration while. Pour le contrôle du flux de programme dans une boucle, on peut utiliser les déclarations. Khaled Hassine 5 Khaled Hassine 6 Boucles en C Qui dit contrôle de la boucle, dit qu'il faut pouvoir s'arrêter!!! Plusieurs cas sont possibles : Le nombre de répétitions (itérations) est connu à l'avance : répéter un traitement 100 fois. Ceci peut être exprimée par la structure itérative Pour (ou for en C). Le nombre de répétitions n'est pas connu à l'avance. Il dépend d'une condition logique. Ceci peut être exprimé par la structure tant que (ou while... do en C) ou aussi dans certains cas par Répéter... Jusqu'à (ou do... while en C). Khaled Hassine 7 Khaled Hassine 8 LFSI 1 LARI 1 2
Forme algorithmique générale Boucle while do La structure algorithmique générale d'une boucle Tant que est la suivante : Tant que <Condition > Faire /*Condition est à Vrai*/ <Traitement> /* Condition est mise à jours dans traitement*/ FinFaire La sémantique : refaire <Traitement>, dit aussi corps de la boucle, tant que <Condition> est évaluée à Vrai. Ceci sous-entend que <condition> peut-être une expression logique ou une variable Booléenne. Si Condition est évaluée à faux avant d'entrer dans la boucle, la partie <Traitement> n'est jamais exécutée. Remarquons que la structure tant que est la plus générale. En effet, toutes les structures itératives peuvent être exprimées sous forme de while. Syntaxe : while <Expression> <Traitement> Comme c est le cas pour le traitement conditionnel, <Expression> est une expression logique, arithmétique, qui retourne une valeur. Si cette valeur est non nulle, on refait le corps de la boucle. Si la valeur retournée est nulle, on passe à la déclaration qui suit le while. Comme dans le cas des actions conditionnelles, si <Traitement> est composé de plusieurs actions (simples, itératives, conditionnelles, etc. ), il faut le délimiter par { et. Khaled Hassine 9 Khaled Hassine 10 Exemple 1: Puissance de 2 On veut afficher les 10 premières puissances de 2. Le format d'affichage est le suivant : 0 1 1 2 2 4 3 8 etc. Exemple 1 { int i=0, P2 = 1; /* Respectivement un Compteur et la puissance de 2 */ printf("table des Puissances de 2\n"); /* Partie initialisation des variables de la boucle */ while (i<10) { printf ("%d%20d\n", i, P2); i++; P2 *= 2; /* A ce niveau I = 10 > 9 */ Khaled Hassine 11 Khaled Hassine 12 LFSI 1 LARI 1 3
Exemple 2 : Lecture / Écriture répétitifs Attention aux boucles Infinies main () { int A, B; /* Les variables du calcul */ char Rep = 'O'; /*'O' pour continuer, 'N' pour s'arrêter*/ while (Rep == 'O') { printf("donnez deux entiers : "); scanf("%d %d", &A, &B) ; printf("%d + %d = %d", A, B, A+B); printf("%d x %d = %d", A, B, A*B); printf("continuer (O/N) : "); scanf("%c",&c); /* A ce niveau Rep 'O' */ main () { int A, B; /* Les variables du calcul */ char Rep = 'O'; /*'O' pour continuer, 'N' pour s'arrêter*/ while (Rep = 'O') { printf("donnez deux entiers : "); scanf("%d %d", &A, &B) ; printf("%d + %d = %d", A, B, A+B); printf("%d x %d = %d", A, B, A*B); printf("continuer (O/N) : "); scanf("%c",&c); /* A ce niveau Rep 'O' */ Khaled Hassine 13 Khaled Hassine 14 Condition générale d application de la boucle Pour On peut se trouver devant le cas où le nombre d'itérations est connu à l'avance : refaire une action N fois. Ceci est exprimé facilement par la boucle POUR. C'est en, effet, une forme d'actions répétitives qui correspond au cas où la condition de boucle ne porte que sur le contrôle d'une variable simple (généralement entière, appelée compteur) incrémentée ou décrémentée d'un pas (généralement ± 1). Khaled Hassine 15 Khaled Hassine 16 LFSI 1 LARI 1 4
Forme algorithmique générale Equivalent algorithmique de la boucle Pour La forme la plus générale de la structure Pour est la suivante : Pour <Compteur> de <VI> à <VF> Par Pas de <Pas> Faire <Traitement> FinFaire. Avec VI est la Valeur Initiale et VF est la Valeur Finale. On répète ainsi <Traitement> (VF-VI + 1) fois si <Pas> est égal à 1. Compteur = VI Tant que Compteur VF Faire <Traitement> Compteur = Compteur + <Pas> FinFaire Ainsi, si VF > VI, la partie Traitement n'est exécutée aucune fois. Khaled Hassine 17 Khaled Hassine 18 Syntaxe C de la boucle for for ([<Initialisations>;] [<Condition>;][<incrément>]) <Traitement> où <Initialisations> est la condition de départ. Plusieurs initialisations sont possibles séparées par des virgules. <Condition> : la boucle est effectuée tant que cette condition est vérifiée. L'évaluation de la condition se fait avant l'entrée dans la boucle. <expression d incrément> : c'est qu'il faut faire après chaque itération. Plusieurs instructions sont possibles séparées par des virgules. <Traitement> : corps de la boucle Ordre de traitement de la boucle for 1. <expression initiale> : initialise toutes les valeurs nécessaires à la déclaration de la boucle. 2. <condition> : Si elle est vraie, on passe à l'étape suivante. Sinon, on passe à la déclaration suit la boucle. 3. <expression d'incrément> : met à jour les variables utilisées dans le contrôle de la boucle. 4. <Traitement> est exécuté à moins de rencontrer une déclaration : break : on quitte la boucle Continue : on revient à l'étape 2. Khaled Hassine 19 Khaled Hassine 20 LFSI 1 LARI 1 5
Remarque Comme pour les structures conditionnelles et la structure while, si <Traitement> est composé de plusieurs actions, il faut le délimiter par { et. Exemple puissance de 2 : 1 ère version Dans l'exemple de puissance de 2, on répète le même traitement 10 Fois et ceci est connu à l'avance. Le programme correspondant s'écrit alors aisément avec la structure for. { int i,p2; /* Respectivement un Compteur et la puissance de 2 */ printf("table des Puissances de 2"); /* Partie initialisation des variables de la boucle */ for (i=0, P2=1; i<10; i++) { printf (" %d \t \t %d\n", i, P2); P2 *= 2; /* A ce niveau I = 11 > 10 */ Khaled Hassine 21 Khaled Hassine 22 Exemple puissance de 2 : 2 ème version Autre exemple { int i,p2; /* Respectivement un Compteur et la puissance de 2 */ printf("table des Puissances de 2"); /* Partie initialisation des variables de la boucle */ for (i=1, P2=1; i<10; i++, P2 *=2) printf (" %d \t \t %d\n", i, P2); { int i,j; Résultat de l exécution : i : 2 - j : 4 i : 3 - j : 3 for (i=2, j = 4; (i<5) && (j>2); i++, j--) printf ("i : %d - j : %d\n", i, j); Khaled Hassine 23 Khaled Hassine 24 LFSI 1 LARI 1 6
Forme générale Dans certains cas, on est sûr d'exécuter le corps de la boucle au moins une fois. Dans ces conditions, il est préférable, voire meilleur, en C d'employer la structure do... while. Cette structure provoque l exécution de la première itération indépendamment de la condition puis la répétition de Traitement tant que Condition est évaluée à vrai. Khaled Hassine 25 Khaled Hassine 26 Syntaxe do { /*Quelque soit l'état de Condition pour la première fois, pour les autres Expression est évaluée à vrai */ <Traitement> {Corps de la boucle /*Mise à jour de <Expression> * while <Expression >; Equivalent algorithmique de do while Forcer <Expression> à une valeur positive. Tant que <Expression> Faire <Traitement> FinFaire Khaled Hassine 27 Khaled Hassine 28 LFSI 1 LARI 1 7
Exemple : lecture contrôlée Lecture contrôlée : traduction en C La structure do... while est très utile pour les lectures contrôlées. Par exemple; on peut exprimer le fait que OP doit appartenir à {'+', '- ','*' comme suit : Faire Lire (op) Tant que OP ['+', '-','*'] { char C; do scanf("%c", &op) ; while ((op!= '+') && (op!= '-') && (op!= '*')); Khaled Hassine 29 Khaled Hassine 30 Autre exemple de lecture contrôlée { char Rep; do printf("continuer (O/N) : "); scanf("%c", &Rep) ; while ((Rep!= 'O') && (Rep!= 'o') && (Rep!= 'N') && (Rep!= 'n')); Khaled Hassine 31 Khaled Hassine 32 LFSI 1 LARI 1 8
Sortie des boucles : Pour le contrôle du flux de programme dans une boucle, on peut utiliser les instructions. L instruction break termine une boucle (for, while, do while) après on passe à l instruction qui suit le corps de la boucle. L'instruction continue permet de passer directement à l'itération suivante. On interrompe ainsi l'exécution de l'itération en cours mais on ne sort pas de la boucle. On reprend selon le type de la boucle, au niveau de la condition pour une boucle while et au niveau de la l'incrément au niveau de la boucle for. Exemple { int i,j; scanf("%d %d", &i,&j Le résultat est si on introduit 2 3 : i : 2 - j : 3 i : 1 - j : 2 for (; (i>0) && (j>0); i--, j--) { if (i==5) continue ; printf ("i : %d - j : %d\n", i, j); if (j==5) break ; Le résultat est si on introduit 6 3 : i : 6 - j : 3 i : 4 - j : 1 Le résultat est si on introduit 3 5 : i : 3 - j : 5 Khaled Hassine 33 Khaled Hassine 34 Autre exemple { int i=0; while (i < 10) { printf("\nau début de la boucle i : %d",i); if (i == 3) break; i++; printf("\na la fin de la boucle i : %d",i); Quel est le résultat de l exécution de ce programme? boucle infinie { int i=0; while (i < 10) { printf("\nau début de la boucle i : %d",i); if (i == 3) continue; i++; printf("\na la fin de la boucle i : %d",i); Khaled Hassine 35 Khaled Hassine 36 LFSI 1 LARI 1 9
Autre exemple { int i=3; while (1) /* condition toujours vrai */ { if (!--i) break ; printf ("i : %d \n", i); if (!--i) est équivalent à if (--i ==0) puisque l'opérateur -- est prioritaire par rapport à ==. Le résultat est alors : i : 2 i : 1 i : 0 Remarque for ( ; ; ) est une instruction syntaxiquement correcte mais donne lieu à une boucle infinie sans l'instruction break. Khaled Hassine 37 Khaled Hassine 38 Khaled Hassine 39 LFSI 1 LARI 1 10