Pourquoi les boucles sont délicates
Une boucle sert à répéter une action. En logique de programmation, les erreurs les plus fréquentes viennent de deux points : (1) une condition d’arrêt mal formulée (boucle infinie ou arrêt trop tôt) ; (2) un mauvais placement des mises à jour (compteur, somme, index), ce qui provoque des résultats faux ou des erreurs « off-by-one » (décalage de 1).
Dans ce chapitre, on se concentre sur : boucles bornées (pour), boucles conditionnelles (tant que), compteur, accumulateur, sentinelle, critères d’arrêt et invariants simples (ce qui reste vrai à chaque tour).
Deux familles de boucles
1) Boucle bornée : pour (quand on connaît le nombre de répétitions)
On l’utilise quand on sait à l’avance combien de fois répéter (ex. 10 lignes, 12 mois, N éléments).
- Avantage : limite claire, moins de risques de boucle infinie.
- Risque : erreurs d’index (commencer à 0 ou 1 ? s’arrêter à N ou N-1 ?).
pour i de 1 à 5 inclus faire afficher(i)Ici, l’invariant simple est : « à chaque tour, i est un entier compris entre 1 et 5 ».
2) Boucle conditionnelle : tant que (quand on ne connaît pas la durée)
On l’utilise quand on s’arrête dès qu’un critère est atteint (ex. dépasser un seuil, trouver un élément, lire jusqu’à une sentinelle).
Continuez dans notre application.
Vous pouvez écouter le livre audio écran éteint, recevoir un certificat gratuit pour ce cours et accéder également à 5 000 autres cours en ligne gratuits.
Ou poursuivez votre lecture ci-dessous...Téléchargez l'application
- Avantage : flexible, s’adapte aux données.
- Risques : oublier de faire évoluer l’état (variable qui ne change pas) ou inverser la condition d’arrêt.
tant que condition_est_vraie faire ... mettre_à_jour_les_variablesRègle pratique : dans une boucle tant que, identifiez explicitement la ou les variables qui rendent la condition fausse à terme (sinon, boucle infinie).
Compteur, accumulateur, sentinelle
Compteur
Variable qui compte des tours ou des éléments (ex. nbJours, i). Elle augmente (ou diminue) de façon régulière.
compteur ← 0tant que ... faire ... compteur ← compteur + 1Accumulateur
Variable qui cumule une valeur (somme, produit, concaténation). Elle se met à jour à chaque tour.
somme ← 0pour chaque dépense faire somme ← somme + dépenseSentinelle
Valeur spéciale qui signifie « stop » (ex. entrée utilisateur = 0 pour arrêter, ou chaîne vide). On boucle tant qu’on ne rencontre pas la sentinelle.
lire x tant que x ≠ 0 faire traiter(x) lire xPiège classique : lire la valeur une seule fois avant la boucle et oublier de relire à la fin (la condition ne change jamais).
Critères d’arrêt et invariants simples
Critères d’arrêt
- Arrêt par limite : on s’arrête quand un compteur atteint une borne (ex.
i = N). - Arrêt par seuil : on s’arrête quand une valeur cumulée dépasse/atteint un seuil (ex.
somme ≥ limite). - Arrêt par découverte : on s’arrête quand on a trouvé ce qu’on cherche (ex. premier jour où on dépasse un objectif).
- Arrêt par sentinelle : on s’arrête quand une donnée spéciale apparaît.
Invariants simples (outil anti-bug)
Un invariant est une phrase vraie avant et après chaque itération. Il aide à vérifier qu’on met à jour les bonnes variables au bon moment.
- Exemple d’invariant pour une somme : «
somme= total des dépenses déjà traitées ». - Exemple d’invariant pour une recherche : « aucun jour avant
journe dépasse l’objectif ».
Méthode pratique en 6 étapes pour écrire une boucle
Choisir le type :
poursi le nombre de tours est connu, sinontant que.Nommer les variables : compteur, accumulateur, seuil, index, résultat.
Initialiser correctement (souvent 0 pour une somme, 1 pour un compteur de jours, etc.).
Écrire la condition d’arrêt en pensant : « quand est-ce que je veux sortir ? » puis traduire en condition de continuation.
Mettre à jour les variables à l’intérieur (sans oublier la variable qui fait évoluer la condition).
Tracer 3 à 6 tours à la main (tableau des variables) pour repérer off-by-one et condition inversée.
Pièges classiques à éviter
- Condition d’arrêt inversée : écrire
tant que somme ≥ limiteau lieu detant que somme < limite. - Off-by-one : inclure un élément de trop ou en oublier un (borne inclusive/exclusive).
- Compteur mal placé : incrémenter avant d’utiliser la valeur, ou après alors qu’on voulait l’inverse.
- État non mis à jour : oublier de lire la prochaine valeur, oublier d’incrémenter, etc.
Exercices (9 à 12) avec solutions commentées et traces
Exercice 9 — Somme des dépenses jusqu’à une limite
Énoncé : on a une liste de dépenses (en euros) et une limite. Calculer la somme en ajoutant les dépenses dans l’ordre jusqu’à atteindre ou dépasser la limite. On doit s’arrêter dès que la limite est atteinte/dépassée. Renvoyer la somme finale et le nombre de dépenses prises en compte.
Données d’exemple : dépenses = [12, 8, 15, 6, 10], limite = 30. Résultat attendu : somme = 35, nb = 3 (12+8+15).
Idée : boucle conditionnelle, accumulateur (somme), compteur (i), arrêt par seuil.
somme ← 0i ← 0tant que i < longueur(dépenses) ET somme < limite faire somme ← somme + dépenses[i] i ← i + 1retourner somme, iInvariant : après chaque tour, somme est la somme des i premières dépenses (indices 0 à i-1).
Trace d’exécution (dépenses = [12, 8, 15, 6, 10], limite = 30)
| Tour | i (avant) | somme (avant) | dépense ajoutée | somme (après) | i (après) | Condition somme < limite ? |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 12 | 12 | 1 | oui |
| 2 | 1 | 12 | 8 | 20 | 2 | oui |
| 3 | 2 | 20 | 15 | 35 | 3 | non (35 ≥ 30) |
Pièges :
- Écrire
tant que somme ≤ limiteau lieu desomme < limite: cela ajoute une dépense de trop quandsommevaut exactement la limite. - Oublier
i < longueur(dépenses): risque de dépasser la liste si la limite n’est jamais atteinte.
Exercice 10 — Trouver le premier jour dépassant un objectif (attention au compteur)
Énoncé : on a une liste de valeurs journalières (ex. pas, ventes, pages lues). Trouver le premier jour (numéroté à partir de 1) où la valeur dépasse un objectif. Si aucun jour ne dépasse l’objectif, renvoyer 0.
Données d’exemple : valeurs = [80, 95, 100, 101, 99], objectif = 100. Résultat attendu : jour = 4 (101 est le premier strictement > 100).
Idée : boucle tant que avec compteur/index. On avance tant qu’on n’a pas dépassé l’objectif.
i ← 0tant que i < longueur(valeurs) ET valeurs[i] ≤ objectif faire i ← i + 1si i = longueur(valeurs) alors retourner 0sinon retourner i + 1Invariant : pour tout index j < i, on a valeurs[j] ≤ objectif (donc aucun jour avant i+1 ne dépasse).
Trace d’exécution (valeurs = [80, 95, 100, 101, 99], objectif = 100)
| Tour | i (avant) | valeurs[i] | Test valeurs[i] ≤ objectif | i (après) |
|---|---|---|---|---|
| 1 | 0 | 80 | vrai | 1 |
| 2 | 1 | 95 | vrai | 2 |
| 3 | 2 | 100 | vrai | 3 |
| 4 | 3 | 101 | faux | 3 (on sort) |
On sort avec i = 3, donc le jour est i+1 = 4.
Pièges :
- Compteur mal placé : incrémenter
iavant de tester la valeur fait sauter le jour 1. - Off-by-one : renvoyer
iau lieu dei+1si les jours sont numérotés à partir de 1. - Condition inversée : écrire
valeurs[i] > objectifdans letant que(on bouclerait seulement quand on a déjà réussi).
Exercice 11 — Générer une table de multiplication lisible
Énoncé : générer une table de multiplication de 1 à N (ex. N=5) sous forme de grille lisible. Chaque ligne i contient i×1, i×2, ..., i×N.
Idée : double boucle bornée (pour). Un accumulateur de chaîne (ou une ligne) pour construire l’affichage.
N ← 5pour i de 1 à N inclus faire ligne ← "" pour j de 1 à N inclus faire produit ← i * j ligne ← ligne + format(produit, largeur=4) afficher(ligne)Trace d’exécution (N=3, on montre les variables clés)
| i | j | produit | ligne (après ajout) |
|---|---|---|---|
| 1 | 1 | 1 | " 1" |
| 1 | 2 | 2 | " 1 2" |
| 1 | 3 | 3 | " 1 2 3" |
| 2 | 1 | 2 | " 2" |
| 2 | 2 | 4 | " 2 4" |
| 2 | 3 | 6 | " 2 4 6" |
Pièges :
- Oublier de réinitialiser
ligneà chaque nouveaui: toutes les lignes se collent. - Bornes : faire
j de 1 à N-1par erreur (dernière colonne manquante). - Lisibilité : sans largeur fixe, les colonnes se décalent (ex. 9 puis 10).
Exercice 12 — Estimer le nombre d’itérations pour atteindre un seuil (croissance progressive)
Énoncé : une valeur augmente progressivement selon une règle simple. Estimer le nombre d’itérations nécessaires pour atteindre ou dépasser un seuil.
Scénario : vous commencez avec valeur = 10. À chaque itération, elle augmente de 20% (multiplication par 1,2). Combien d’itérations pour atteindre au moins 50 ?
Idée : boucle tant que avec accumulateur (valeur) et compteur (tours). Arrêt par seuil.
valeur ← 10tours ← 0tant que valeur < 50 faire valeur ← valeur * 1.2 tours ← tours + 1retourner tours, valeurInvariant : après tours itérations, valeur = 10 * 1.2^tours (utile pour vérifier la cohérence).
Trace d’exécution
| Tour | valeur (avant) | valeur (après) | tours (après) | valeur < 50 ? |
|---|---|---|---|---|
| 1 | 10,00 | 12,00 | 1 | oui |
| 2 | 12,00 | 14,40 | 2 | oui |
| 3 | 14,40 | 17,28 | 3 | oui |
| 4 | 17,28 | 20,74 | 4 | oui |
| 5 | 20,74 | 24,88 | 5 | oui |
| 6 | 24,88 | 29,86 | 6 | oui |
| 7 | 29,86 | 35,83 | 7 | oui |
| 8 | 35,83 | 43,00 | 8 | oui |
| 9 | 43,00 | 51,60 | 9 | non |
On atteint le seuil en 9 itérations, avec une valeur finale d’environ 51,60.
Pièges :
- Condition d’arrêt inversée :
tant que valeur ≥ 50ne tournera jamais au départ. - Oublier d’incrémenter
tours: vous obtenez la bonne valeur finale mais pas le bon nombre d’itérations. - Arrondi trop tôt : arrondir
valeurà chaque tour peut changer le nombre d’itérations ; arrondir seulement pour l’affichage.