GEF 243B Programmation informatique appliquée Boucles
Revue Quand devriez-vous utiliser un énoncé else-if au lieu d’un switch Donnez une expression ternaire pour incrémenter a si b > 0, sinon, décrémentez a et assigné la vielle valeur de a à c else-if when the checked variable takes on a range of possible values, switch when the checked variable takes on various integral values use conditional expression: b >= 0 ? a++ : (c = a--);
Synopsis Le concept des boucles Boucle for Boucle while Boucle do-while Les énoncés continue et break Optimization du code avec les expressions logiques court-circuit
Boucles Qu’est ce qu’un ordinateur peut faire très bien Opérations répétitives … (vous comprenez) Les répétitions pour accomplir une tâche sont partout dans la programmation Ces répétitions s’appelles boucles et sont d’autres abstractions d’un langage de haut niveau
Boucles – le concept Un action ou une série d’actions Cette boucle représente une machine à actions perpétuelle (il n’y a pas de sortie … laissez-moi sortir !!!).
Boucles – le concept Si nous ne voulons pas une machine perpétuelle (et pour la plus part du temps on n’en veut pas), nous devons imposer quelques genres de conditions sur la boucle pour qu’elle termine. Ces conditions sont des expressions logiques qui sont évaluées pour déterminer si il y a eu assez de travail de fait Ou dans certain cas si nous avons même besoin d’entrer dans la boucle Il y a deux sortes de tests qui nous permettent de terminer des boucles: Pré-test Post-test
Boucles – le concept Pré-test: L’expression logique est évaluée en premier. Si L’expression évalue à vrai, alors les actions dedans la boucle sont exécutées; si faux, la boucle termine. Post-test: Les actions sont exécutées en premier et l’expression est évaluée après. On utilise ce genre de boucle si on veut que le code dans la boucle exécute au moins une fois
Boucles – le concept Show them that the location of the condition test and the “entry” of the loop in the post-test forces the execution of the actions at least once. While the other loop can exit without ever executing a statement if the condition is false Also tell them that this is their first contact with flowcharts. We will talk more about flowcharts in the next lecture.
Boucles – le concept Show them that the location of the condition test and the “entry” of the loop in the post-test forces the execution of the actions at least once. While the other loop can exit without ever executing a statement if the condition is false Also tell them that this is their first contact with flowcharts. We will talk more about flowcharts in the next lecture.
Boucles – le concept Il y a des questions qui se posent par rapport à l’évaluation des expressions logiques: Quelles sont les conditions initiales de l’expression? Comment est-ce que les conditions changent pour permettre à la boucle de terminer? Est-ce que j’attend pour un événement ou simplement un nombre donné d’itérations? Est-ce que la boucle va se terminer un jour?
Boucles – le concept Changement des conditions: Pour qu’une boucle se termine, une ou des conditions doivent changer Ce changement de condition est due aux actions dans la boucle (compteur, EOF, EOL,…) ou Comme résultat de stimuli externes (interruption qui change l’état du pare choc de notre robot Lego). Si vos conditions ne changent pas, ou qu’elles changent de la mauvaise façon vous pouvez avoir une boucle infinie!!! We will talk about common programming errors in the next lecture. Errors that are made in conditional and loop statements
Boucles – le concept changement de condition Make them notice the initialization and the updating blocks. We should mention that if one of the two (initialization or updating) is not right, then, the program may not terminate or the loop might be “dead” code and never run. En majorité les programmes qui sont fautifs le sont dans l’aspect logique des contrôles de flot
Boucles – le concept changement de condition Make them notice the initialization and the updating blocks. We should mention that if one of the two (initialization or updating) is not right, then, the program may not terminate or the loop might be “dead” code and never run. En majorité les programmes qui sont fautifs le sont dans l’aspect logique des contrôles de flot
Boucle for L’énoncé for… C’est une boucle avec pré-test! La boucle for contient trois expressions: expr1: établie la condition initiale pour la boucle expr2: contient la condition limite pour la boucle expr3: contient l’information de mise à jour for (expr1; expr2; expr3) énoncé Remind them that statement can be any statement: a function, a block, or yes a single statement.
Boucle for - exemples for (i=1; i<=maxIteration; i++) factoriel *= i; //notez où le ; est for (j=10; j>0; j--) //boucle qui décrémente { som += j; cputs(“Fini”); //vous allez utiliser cette fctn } To put the ; at the wrong place terminates the statement. Do not worry about the mistakes that can be made in this kind of loop, next lecture will cover that including using = when == is intended or using < as a limit when we use a decrementing loop.
Boucle while while (expression) L’énoncé while est une autre boucle avec pré-test. Si l’expression évalue à faux avec les conditions initiales, la boucle termine sans qu’aucun énoncé dans la boucle exécute Un contrôle de boucle simple. … while (expression) énoncé Est-ce que ça pourrait être plus simple?
Boucle while - exemples while (i++ < n) factoriel *= i; //c’est tout!! while ((c = getchar()) != EOF) //End of File { if(c>=‘a’ && c<= ‘z’) minusculesCompte++; nombreTotalDeCaractères++; } Tell them that we will look at all the logical operators next class.
Boucle do-while Et vous l’avez deviné, do-while est la boucle avec post-test. do énoncé while (expression); Remarquez le ; Comme vous le voyez, l’expression logique est à la fin de la boucle. Donc l’énoncé VA exécuter Soyez prudent, vous devez vous assurer que l’énoncé peut exécuter même si la condition initiale évalue à faux Java in hex.
Boucle do-while - exemples //Ici on compte des Smarties dans une //boite, on assume que le singulier de //Smarties est Smarty et que la boite //n’est pas vide quand on commence do { if (couleurDuSmarty == "rouge") smartiesRouges++; else autresSmarties++; boite -= 1; } while (boite != vide);
Énoncés continue et break L’énoncé continue n’arrête pas une boucle, il fait seulement arrêter l’itération en cours et recommence la boucle Pour les boucles do-while et while, continue transfert le contrôle pour réévaluer la condition limite Pour la boucle for, continue met à jour l’expression logique (i.e. i++) et vérifie la condition limite
Énoncés continue while (expression) { … if (condition) continue; }
Énoncés continue et break Nous avons vue l’énoncé break avec l’énoncé switch. Le break peut être utilisé dans n’importe quelle boucle pour terminer si ‘une autre’ condition se produit. Si il y a des boucles imbriquées, seulement la boucle courante se termine. while (condition) { … for (…;…;…;) { … if (autreCondition) break; //for arrête, while arrête pas … } x = x + y; Mention to them that both break and continue in loops are unstructured programming like goto (Forouzan p. 261-262) and it is not encouraged. We mention it here to be complete.
Énoncés continue et break Quelle est le résultat de ce code? for (cnt=0; cnt<10; cnt++) { if (cnt==4) //boucle for loop termine, continue; if (cnt==6) break; printf("cnt=%d\n",cnt); } cnt=0 cnt=1 cnt=2 cnt=3 cnt=5
Optimisations du code avec les expressions logiques Dans certains langages, l’expression logique entière d’une boucle ou une sélection est évaluée avant que la décision soit prise (Pascal, Ada, Cobol,…) En C, l’expression est évaluée de la gauche vers la droite et aussitôt que la condition nécessaire est évaluée, et le reste de l’expression ne l’est pas On nomme cela un court circuit A necessary condition would be for example that the first term in a && expression is false, or if the first term in a || expression is true. The rest of the expression does not need to be evaluated, because the decision has been made. Example. Test1 prints out 1 and test2 prints out 0. #include <stdio.h> #include <conio.h> void main(void) { int test1=0, test2=0; int red=1, wet=1; if( (test1=red)==0 && (test2=wet)==0 ) printf("Test should not be true"); printf("The value of test1 is %d and the value of test2 is %d", test1, test2); getch(); }
Optimisations du code avec les expressions logiques Conditions nécessaires utilisées pour court-circuit Si le premier terme dans une expression && est fausse Si le premier terme dans une expression || est vraie Le reste de l’expression n’a pas besoin d’être évaluée, pcq la décision a été faite Ceci est plus vite, mais programmeur fait attention!!!
Court-circuit dans une expression logique if(numAttacks++ < maxAttacks && soldiers > 0) { victim=ChooseOpponent(); AttackCountry(victim, soldiers); } return numAttacks; You are playing a wargame, you need two conditions: You still have attacks available, You have soldiers to carry out the attack The problem is that the number of attacks will be incremented (numAttacks++) even if no attack takes place (when soldiers <=0)
Court-circuit dans une expression logique #include <stdio.h> #include <conio.h> void main(void) { int test1=0, test2=0; int rouge=1, bleue=2; if( (test1=rouge)==0 && (test2=bleue)==0 ) printf("Le test évalue à faux"); printf("La valeur test1 est %d et test2 est %d", test1, test2); getch(); } You are playing a wargame, you need two conditions: You still have attacks available, You have soldiers to carry out the attack The problem is that the number of attacks will be incremented (numAttacks++) even if no attack takes place (when soldiers <=0)
Optimisations du code avec les expressions logiques Côté positif: Ceci peut vous permettre d’optimiser votre code si vous placez les conditions en ordre dans lequel elles sont le plus probables Côté négatif: Si vous avez des effets secondaires dans une condition (++, --), et que cette condition n’est pas évaluée, alors les effets secondaires ne seront pas exécutés. Dans une expression avec || mettez la condition qui est le plus susceptible d’être vrai en premier Dans une expression avec && mettez la condition qui est le plus susceptible d’être fausse en premier So in a || expression, place the condition that is most likely to be TRUE first and in an && place the most likely to be FALSE first Give an example on the blackboard for the second: a && b++ <= c If a evaluates to FALSE (0) then b will never be incremented. Now that could be the intent, but that makes for terrible code. Never, never oh never do that.
Court-circuit dans une expression logique Dernier test, que ce passe-t-il ici? int a=0, b=1, c=2; if(a && b++ <= c) printf("What did this do?"); because a is 0 (false), the rest of the expression is never evaluated: b is not incremented b is never compared to c the sentence is not printed.
Erreurs communes dans les structures de contrôle de flot Comme vous pouvez le voir sur la dernière diapo, il y a un potentiel pour des erreurs de logique dans les expressions logiques. En déboguant, le plus difficile est de trouver les erreurs de logique. Pourquoi? Et bien c’est parce que vous êtes déjà convaincu que vous aviez raison en premier lieu! Dans un cours nous allons discuter des organigrammes (flowcharts) comme une façon de ‘voir’ votre logique Aujourd’hui nous discutons des erreurs de logique communes When you read your code, you should never read it thinking that it is right, it is wrong until you prove otherwise. Human tendency is to read what they think they see, not what is actually there. Here we do not cover errors that the compiler will detect, we discuss errors that you would most likely say “why is this not working, I’ve done everything right.”
Erreurs communes dans les structures de contrôle de flot La boucle brisée: Une condition que vous voulez qui se produise n’arrivera jamais. Par exemple si a ne peut jamais être plus grand que z alors vous avez une boucle infinie: while (a < z) {…} Une erreur de logique grossière. “Une idée brisée”: while (a > b && a == b) //exécute jamais for (i = 1; i < 20; i--) //arrête jamais The first one is difficult to debug because there may be no way to know that the condition will never occur. The second bullet with the two examples indicates an error in pure human logic, a screw up.
Erreurs communes dans les structures de contrôle de flot Une erreur en ponctuation: for (i = 1; i <= 100; i++); {…} La boucle roule sur un énoncé vide Ensuite le code dans les accolades exécute exactement une fois if (a < b); {…} if exécute (ou pas) un énoncé vide encore Le bloc entre les accolades exécute peu importe le résultat du test L’énoncé composé n’e fait pas parti du if First bullet: The first example, the loop will run on a “nothing” statement than the code in the {} will execute exactly once, the second example, the if will execute but the statements will always execute regardless of the result of the condition. (the compound statement is not part of the if statement). Second bullet : The i = 10 in the loop will assign the value of 10 to i. The compiler will generate a warning in this case, which is why you should always read the warnings and try to correct them unless you REALLY know the warning can be ignored. & and | are bitwise operators, you will not get an error, because they are allowed to be used. Third bullet: Instead of using == do the following ( if (abs(a-b) < 0.00001) {…} (write this on the board.
Erreurs communes dans les structures de contrôle de flot Une erreur dans l’utilisation de l’opérateur (erreur logique) = au lieu de == for (i = 1; i = 10; i++) {…} Le i=10 dans la boucle va assigner la valeur 10 à i Le compilateur va générer un attention dans ce cas, et c’est pourquoi vous devriez toujours lire les attentions et essayer de les corriger First bullet: The first example, the loop will run on a “nothing” statement than the code in the {} will execute exactly once, the second example, the if will execute but the statements will always execute regardless of the result of the condition. (the compound statement is not part of the if statement). Second bullet : The i = 10 in the loop will assign the value of 10 to i. The compiler will generate a warning in this case, which is why you should always read the warnings and try to correct them unless you REALLY know the warning can be ignored. & and | are bitwise operators, you will not get an error, because they are allowed to be used. Third bullet: Instead of using == do the following ( if (abs(a-b) < 0.00001) {…} (write this on the board.
Erreurs communes dans les structures de contrôle de flot Une erreur dans l’utilisation de l’opérateur (erreur logique) Utilisation des opérateur logique sur les bits & et | au lieu de && et || while (a & b | c) {…} C’est permi par le compilateur Ne génére pas d’attention ou erreur Ne vous donnera pas les résultats attendus First bullet: The first example, the loop will run on a “nothing” statement than the code in the {} will execute exactly once, the second example, the if will execute but the statements will always execute regardless of the result of the condition. (the compound statement is not part of the if statement). Second bullet : The i = 10 in the loop will assign the value of 10 to i. The compiler will generate a warning in this case, which is why you should always read the warnings and try to correct them unless you REALLY know the warning can be ignored. & and | are bitwise operators, you will not get an error, because they are allowed to be used. Third bullet: Instead of using == do the following ( if (abs(a-b) < 0.00001) {…} (write this on the board.
Erreurs communes dans les structures de contrôle de flot Une erreur dans la comparaison des floats (a et b sont floats: if (a == b) {…} Exactement égale est trop exacte pour la comparaison de floats if (fabs(a-b) < 0.00001) {…} First bullet: The first example, the loop will run on a “nothing” statement than the code in the {} will execute exactly once, the second example, the if will execute but the statements will always execute regardless of the result of the condition. (the compound statement is not part of the if statement). Second bullet : The i = 10 in the loop will assign the value of 10 to i. The compiler will generate a warning in this case, which is why you should always read the warnings and try to correct them unless you REALLY know the warning can be ignored. & and | are bitwise operators, you will not get an error, because they are allowed to be used. Third bullet: Instead of using == do the following ( if (abs(a-b) < 0.00001) {…} (write this on the board.
Erreurs communes dans les structures de contrôle de flot L’oublie d’une mise à jour dans une condition de boucle: while (a < b) {… //a ne change jamais dans la boucle } Pas assez … je voulais faire dix itérations: for (i=1; i <10; i++) //9 itérations Remind them that a loop must have an initial condition and an update of a condition to terminate
Erreurs communes dans les structures de contrôle de flot Mettre trop souvent à jour une condition : While (i != 13) {… i++; //met i to 1, 3, 5, …, 13 … i++; //met i to 2, 4, 6, …, 14 … // (13 ne se produira jamais) } for (i = 1; i <= 10; i++) i++; //Probablement une erreur
Quiz Time Je lit un fichier, mais je ne sait pas si il est vide ou combien d’items il y a dedans. Quelle genre de boucle est-ce que je devrait utiliser? Quand j’appelle ma fonction, je sais combien d’itérations je veux prendre. Quelle genre de boucle? Je veut lire un senseur au moins une fois même si il n’y a pas d’urgence. Quelle boucle? Quelle boucle(s) utilise un pré-test?