Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 427 minDébutant

Boucles pour, tant que et répéter

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • écrire une boucle Pour, TantQue ou Répéter … Jusqu'à, en pseudo-code et en Python ;
  • choisir la boucle adaptée à un problème ;
  • construire un accumulateur : somme, produit ou compteur ;
  • imbriquer deux boucles et éviter les boucles infinies.

8 exercices corrigés1 schéma

Une boucle répète un bloc d'instructions : un nombre de fois connu à l'avance avec la boucle Pour, ou tant qu'une condition reste vraie avec la boucle TantQue et sa variante Répéter … Jusqu'à. Ce chapitre montre comment choisir la bonne boucle, comment la construire (initialisation, mise à jour, résultat final) et comment éviter la boucle infinie et l'erreur d'un tour en trop.

Pourquoi des boucles ?

Afficher les nombres de 1 à 5, tu peux l'écrire en cinq lignes. De 1 à 1 000, non. Et compter les tickets d'un fichier dont tu ne connais pas la taille, c'est impossible sans boucle. Une boucle décrit une fois un traitement qui s'exécutera autant de fois que nécessaire.

Chaque passage dans le corps de la boucle s'appelle une itération (ou un tour). Le programme du BTS insiste : les structures de contrôle sont le cœur de l'algorithmique, et les évaluations sont centrées sur elles. Ce chapitre est le plus important du cours.

La boucle Pour

La boucle Pour répète un bloc pour chaque valeur d'un compteur, d'une valeur de départ à une valeur d'arrivée. On l'utilise quand le nombre de tours est connu avant d'entrer dans la boucle.

text
Pour i de 1 à 5 Faire
    Afficher(i, " × 7 = ", i × 7)
FinPour
python
for i in range(1, 6):
    print(i, "× 7 =", i * 7)
text
1 × 7 = 7
2 × 7 = 14
3 × 7 = 21
4 × 7 = 28
5 × 7 = 35

À chaque tour, le compteur prend la valeur suivante, automatiquement. Tu n'écris jamais i ← i + 1 dans une boucle Pour.

En pseudo-code, les deux bornes sont incluses : Pour i de 1 à 5 fait 5 tours. En Python, range(début, fin) s'arrête avant fin : pour aller de 1 à 5, on écrit range(1, 6). C'est la source n° 1 des erreurs de traduction.

Pseudo-codePythonValeurs de iTours
Pour i de 0 à 4range(5)0, 1, 2, 3, 45
Pour i de 1 à 5range(1, 6)1, 2, 3, 4, 55
Pour i de 0 à n - 1range(n)0 à n − 1n
Pour i de 0 à 10 pas 2range(0, 11, 2)0, 2, 4, 6, 8, 106
Pour i de 10 à 1 pas -3range(10, 0, -3)10, 7, 4, 14
Pour i de 5 à 4range(5, 5)aucune0

Python sait aussi parcourir directement les éléments d'une liste ou les caractères d'une chaîne, sans compteur :

python
for serveur in ["web01", "web02", "bdd01"]:
    print("Sauvegarde de", serveur)
for lettre in "SIO":
    print(lettre)

C'est la forme à privilégier quand tu n'as pas besoin de la position. Les deux formes de parcours d'un tableau sont comparées au chapitre 7.

La boucle TantQue

La boucle TantQue répète un bloc tant qu'une condition est vraie. La condition est testée avant chaque tour : si elle est fausse dès le départ, le bloc n'est jamais exécuté. On l'utilise quand on ne sait pas à l'avance combien de tours il faudra.

Un capital de 1 000 € est placé à 3 % par an. Au bout de combien d'années aura-t-il doublé ?

text
Algorithme Doublement
Variables
    capital : réel
    annees : entier
Début
    capital ← 1000
    annees ← 0
    TantQue capital < 2000 Faire
        capital ← capital × 1,03
        annees ← annees + 1
    FinTantQue
    Afficher(annees, " ans, capital : ", capital)
Fin
python
capital = 1000.0
annees = 0
while capital < 2000:
    capital = capital * 1.03
    annees = annees + 1
print(annees, "ans, capital :", round(capital, 2))
text
24 ans, capital : 2032.79

Impossible d'écrire une boucle Pour ici : le nombre d'années est justement ce qu'on cherche.

Trois éléments doivent être présents dans toute boucle TantQue :

  1. L'initialisation des variables de la condition, avant la boucle (capital ← 1000).
  2. La condition, testée à chaque tour (capital < 2000).
  3. La mise à jour, dans le corps, d'au moins une variable de la condition, pour que celle-ci finisse par devenir fausse (capital ← capital × 1,03).

La boucle Répéter … Jusqu'à

La boucle Répéter exécute le bloc puis teste la condition. Le bloc est donc exécuté au moins une fois. Attention au sens : on répète jusqu'à ce que la condition soit vraie ; c'est une condition d'arrêt, l'inverse de celle du TantQue.

L'usage typique est la saisie contrôlée : on demande une valeur, et on redemande tant qu'elle est invalide.

text
Répéter
    Afficher("Note entre 0 et 20 ?")
    Saisir(note)
Jusqu'à note ≥ 0 ET note ≤ 20

Python n'a pas de boucle Répéter. On l'écrit avec une boucle while True (infinie en apparence) dont on sort par break quand la condition d'arrêt est vraie :

python
while True:
    note = float(input("Note entre 0 et 20 ? "))
    if 0 <= note <= 20:
        break
print("Note enregistrée :", note)

On peut aussi écrire un TantQue avec une première saisie avant la boucle. C'est un peu plus long, mais sans break :

python
note = float(input("Note entre 0 et 20 ? "))
while note < 0 or note > 20:
    print("Valeur incorrecte.")
    note = float(input("Note entre 0 et 20 ? "))
print("Note enregistrée :", note)

Remarque comment la condition s'inverse en passant d'une version à l'autre : on répète jusqu'à 0 ≤ note ≤ 20, c'est-à-dire tant que note < 0 OU note > 20 (loi de De Morgan, chapitre 2).

TantQue ou Répéter : le test avant ou après

TantQue … Faireconditionvraie ?ouiinstructionsnonsortie0 tour possibleRépéter … Jusqu'àinstructionsconditiond'arrêt vraie ?nonouisortieau moins 1 tour
TantQue teste avant le bloc (0 tour possible) ; Répéter teste après (au moins 1 tour), avec une condition d'arrêt
TantQue … FaireRépéter … Jusqu'à
Moment du testAvant chaque tourAprès chaque tour
Nombre minimal de tours01
Sens de la conditionCondition pour continuerCondition pour s'arrêter
En Pythonwhile condition:while True: … if arret: break
Usage typiqueCalcul jusqu'à un seuil, rechercheSaisie contrôlée, menu

Choisir la bonne boucle

QuestionRéponseBoucle
Connais-tu le nombre de tours avant d'entrer ?Oui (n notes, 12 mois, chaque caractère)Pour
Le traitement doit-il s'exécuter au moins une fois ?Oui (saisie, menu)Répéter
SinonOn s'arrête sur une conditionTantQue

Toute boucle Pour peut s'écrire avec un TantQue (on gère le compteur à la main), mais pas l'inverse. Utilise quand même le Pour dès que c'est possible : il est plus court et il ne peut pas boucler à l'infini.

python
# La même boucle, deux écritures
for i in range(1, 6):
    print(i)

i = 1
while i <= 5:
    print(i)
    i = i + 1

Construire une itération

Le programme décrit la construction d'une boucle en trois temps : la préparation (initialiser les variables), l'itération elle-même (la mise à jour à chaque tour) et la mise en forme finale (ce qu'on fait du résultat après la boucle). Applique-les dans cet ordre et la plupart des boucles s'écrivent seules.

Exemple : la moyenne de n notes saisies.

text
// Préparation
somme ← 0
// Itération
Pour i de 1 à n Faire
    Saisir(note)
    somme ← somme + note
FinPour
// Mise en forme finale
moyenne ← somme / n
Afficher(moyenne)

Une aide pour vérifier une boucle : formuler ce qui est vrai à la fin de chaque tour. Ici : « après le tour i, somme contient la somme des i premières notes ». Si c'est vrai au premier tour, et que chaque tour le conserve, c'est vrai au dernier : somme contient la somme des n notes. Cette phrase s'appelle un invariant de boucle. On ne te demandera pas de démonstration, mais la formuler dans ta tête te dit tout de suite si l'initialisation est la bonne.

Accumulateurs : somme, produit, compteur

Trois motifs reviennent dans presque tous les exercices. Ils s'appuient tous sur une affectation récursive : la variable est mise à jour à partir de sa propre valeur.

MotifInitialisationMise à jourPourquoi cette initialisation
Sommesomme ← 0somme ← somme + x0 est l'élément neutre de l'addition
Produitproduit ← 1produit ← produit × x1 est l'élément neutre de la multiplication
Compteurnb ← 0Si condition Alors nb ← nb + 1Au départ, on n'a rien compté

Les symboles Σ (somme) et Π (produit) des maths se traduisent directement par ces motifs. La somme des entiers de 1 à n, Σ i, et la factorielle n! = Π i = 1 × 2 × … × n :

python
n = 100
somme = 0
for i in range(1, n + 1):
    somme = somme + i
print("Somme de 1 à", n, ":", somme)

n = 5
produit = 1
for i in range(1, n + 1):
    produit = produit * i
print(n, "! =", produit)
text
Somme de 1 à 100 : 5050
5 ! = 120

Python a des raccourcis : somme += i équivaut à somme = somme + i (de même -=, *=, //=). Ils sont courants en Python, en C# et en JavaScript ; en pseudo-code, écris l'affectation complète.

Les boucles imbriquées

Une boucle peut en contenir une autre. Pour chaque tour de la boucle externe, la boucle interne fait tous ses tours. Si l'externe fait n tours et l'interne m, le corps interne s'exécute n × m fois.

python
for i in range(1, 4):
    ligne = ""
    for j in range(1, 6):
        ligne = ligne + str(i * j) + "\t"
    print(ligne)
text
1	2	3	4	5
2	4	6	8	10
3	6	9	12	15

"\t" est une tabulation, qui aligne les colonnes. La variable ligne est réinitialisée à chaque tour de la boucle externe : chaque ligne repart de zéro.

Les bornes de la boucle interne peuvent dépendre du compteur externe. Le programme cite explicitement ce cas (« itérations en dépendance »), en le limitant à deux niveaux :

python
n = 4
for i in range(1, n + 1):
    print("*" * i)
text
*
**
***
****

Ici la boucle interne est cachée dans "*" * i (répéter i fois). Écrite explicitement, elle fait i tours au tour i : 1 + 2 + 3 + 4 = 10 étoiles en tout.

Sortir d'une boucle : break et continue

Python propose deux instructions pour modifier le déroulement d'une boucle :

  • break sort immédiatement de la boucle ;
  • continue passe directement au tour suivant.
python
tickets = [12, 0, 7, -1, 3]
for t in tickets:
    if t < 0:
        print("Valeur sentinelle : arrêt")
        break
    if t == 0:
        continue
    print("Ticket", t)
text
Ticket 12
Ticket 7
Valeur sentinelle : arrêt

Elles sont pratiques, mais elles cachent la condition de sortie au milieu du corps. En pseudo-code d'examen, préfère une condition de boucle explicite (un TantQue avec un booléen trouve, par exemple) ; garde break pour la boucle Répéter traduite en Python.

Les erreurs classiques

ErreurSymptômeCorrection
Boucle infinieLe programme ne s'arrête pasVérifier que le corps modifie une variable de la condition
Un tour de trop ou de moins (off-by-one)Il manque le dernier élément, ou IndexErrorVérifier les bornes : range(1, n + 1) pour aller jusqu'à n ; < ou ≤ dans le TantQue
Accumulateur mal placéLe total ne contient que le dernier élémentInitialiser avant la boucle
Condition de Répéter non inverséeLa saisie valide est redemandée, l'invalide acceptéeJusqu'à prend la condition d'arrêt
Test d'égalité sur des réelswhile x != 1.0 ne s'arrête jamaisComparer avec < ou >, ou utiliser un compteur entier
Compteur modifié dans un PourNombre de tours imprévisibleUtiliser un TantQue

Le dernier piège des réels mérite un exemple : en ajoutant 0,1 dix fois à 0, on n'obtient pas exactement 1.

python
x = 0.0
for i in range(10):
    x = x + 0.1
print(x, x == 1.0)
text
0.9999999999999999 False

Une boucle while x != 1.0: x = x + 0.1 ne s'arrêterait donc jamais. Utilise un compteur entier (for i in range(10)) ou une comparaison while x < 1.0.

Exercices

Exercice 1 sur 8 Traduire des bornes Réussi À revoir

Traduis chaque boucle en Python avec range et donne le nombre de tours.

  1. Pour i de 1 à 12
  2. Pour i de 0 à n - 1
  3. Pour i de 2 à 20 pas 2
  4. Pour i de 10 à 0 pas -1
  5. Pour i de 1 à n
Voir la réponseMasquer la réponse de l'exercice 1
  1. range(1, 13) : 12 tours.
  2. range(n) : n tours.
  3. range(2, 21, 2) : 2, 4, …, 20, soit 10 tours.
  4. range(10, -1, -1) : 10, 9, …, 0, soit 11 tours. Avec range(10, 0, -1), on s'arrêterait à 1.
  5. range(1, n + 1) : n tours.

Tu avais trouvé ?

Exercice 2 sur 8 Combien de tours ? Réussi À revoir

Pour chaque boucle, donne le nombre de tours et la valeur finale de k.

python
# A
k = 0
for i in range(3, 9):
    k = k + 1

# B
k = 1
while k < 100:
    k = k * 3

# C
k = 10
while k > 10:
    k = k - 1
Voir la réponseMasquer la réponse de l'exercice 2
  • A : range(3, 9) donne 3 à 8, soit 6 tours ; k vaut 6.
  • B : k prend les valeurs 3, 9, 27, 81, 243 ; 5 tours ; k vaut 243 (le test 243 < 100 est faux, on sort).
  • C : 0 tour, car 10 > 10 est faux dès le départ ; k vaut 10. C'est le cas où un TantQue ne s'exécute jamais.

Tu avais trouvé ?

Exercice 3 sur 8 Somme et moyenne avec sentinelle Réussi À revoir

Écris un programme qui lit des montants de frais un par un. La saisie de 0 signale la fin (c'est une valeur sentinelle, qui n'est pas un frais). Le programme affiche le nombre de frais, leur total et leur moyenne. Que se passe-t-il si l'on saisit 0 tout de suite ?

Voir la réponseMasquer la réponse de l'exercice 3

On ne connaît pas le nombre de saisies : c'est un TantQue, avec une première saisie avant la boucle.

python
nb = 0
total = 0.0
montant = float(input("Montant (0 pour finir) ? "))
while montant != 0:
    nb = nb + 1
    total = total + montant
    montant = float(input("Montant (0 pour finir) ? "))
if nb > 0:
    print(nb, "frais, total", total, "- moyenne", round(total / nb, 2))
else:
    print("Aucun frais saisi")

Avec 0 tout de suite, la boucle ne s'exécute pas, nb vaut 0 et le programme affiche « Aucun frais saisi ». Sans le test if nb > 0, la division total / nb lèverait ZeroDivisionError. Comparer un réel à 0 avec != est sans risque ici : 0 est saisi tel quel, il n'est pas le résultat d'un calcul.

Tu avais trouvé ?

Exercice 4 sur 8 Nombre de chiffres Réussi À revoir

Écris un algorithme qui compte les chiffres d'un entier positif, en le divisant par 10 jusqu'à ce qu'il soit nul. Fais la trace pour 40597. Quel est le résultat pour 0, et comment le corriger ?

Voir la réponseMasquer la réponse de l'exercice 4
text
nb ← 0
TantQue n > 0 Faire
    n ← n DIV 10
    nb ← nb + 1
FinTantQue
Afficher(nb)
Tournnb
avant405970
140591
24052
3403
444
505

Résultat : 5 chiffres. Pour 0, la boucle ne s'exécute pas et l'algorithme affiche 0, alors que 0 s'écrit avec un chiffre. Une boucle Répéter corrige le problème, car elle fait au moins un tour :

python
n = 0
nb = 0
while True:
    n = n // 10
    nb = nb + 1
    if n == 0:
        break
print(nb)

Tu avais trouvé ?

Exercice 5 sur 8 Devine le nombre Réussi À revoir

Le programme tire un entier au hasard entre 1 et 100. L'utilisateur propose des nombres ; le programme répond « plus grand » ou « plus petit » jusqu'à ce qu'il trouve, puis affiche le nombre d'essais. Écris-le en Python.

Voir la réponseMasquer la réponse de l'exercice 5
python
import random

secret = random.randint(1, 100)
essais = 0
while True:
    proposition = int(input("Ton nombre ? "))
    essais = essais + 1
    if proposition < secret:
        print("plus grand")
    elif proposition > secret:
        print("plus petit")
    else:
        break
print("Trouvé en", essais, "essais")

C'est un Répéter : il faut au moins une proposition. En coupant l'intervalle en deux à chaque essai (proposer 50, puis 25 ou 75…), on trouve toujours en 7 essais au plus. C'est l'idée de la recherche dichotomique.

Tu avais trouvé ?

Exercice 6 sur 8 Suite de Fibonacci Réussi À revoir

La suite de Fibonacci commence par 0 et 1, et chaque terme est la somme des deux précédents. Écris un programme qui affiche les 10 premiers termes.

Voir la réponseMasquer la réponse de l'exercice 6

On garde les deux derniers termes dans deux variables, et on les fait avancer à chaque tour.

python
a = 0
b = 1
for i in range(10):
    print(a, end=" ")
    suivant = a + b
    a = b
    b = suivant
print()
text
0 1 1 2 3 5 8 13 21 34

Les trois affectations reprennent la technique de l'échange de variables : suivant évite d'écraser a trop tôt. En Python, a, b = b, a + b fait la même chose en une ligne.

Tu avais trouvé ?

Exercice 7 sur 8 Triangle de nombres Réussi À revoir

Écris un programme qui, pour n = 4, affiche le triangle ci-dessous, avec deux boucles for imbriquées. Combien de fois le print interne s'exécute-t-il pour n quelconque ?

text
1
1 2
1 2 3
1 2 3 4
Voir la réponseMasquer la réponse de l'exercice 7
python
n = 4
for i in range(1, n + 1):
    for j in range(1, i + 1):
        print(j, end=" ")
    print()

La boucle interne fait i tours au tour i, soit 1 + 2 + … + n = n(n + 1)/2 affichages de nombres : 10 pour n = 4. Le print() vide, dans la boucle externe, passe à la ligne.

Tu avais trouvé ?

Exercice 8 sur 8 Suite de Syracuse Réussi À revoir

On part d'un entier n > 0. S'il est pair, on le divise par 2 ; sinon, on le remplace par 3n + 1. On recommence jusqu'à obtenir 1. Écris un programme qui affiche le nombre d'étapes pour un n saisi. Combien pour 6 ? pour 7 ?

Voir la réponseMasquer la réponse de l'exercice 8
python
n = int(input("n ? "))
etapes = 0
while n != 1:
    if n % 2 == 0:
        n = n // 2
    else:
        n = 3 * n + 1
    etapes = etapes + 1
print(etapes, "étapes")

Pour 6 : 6, 3, 10, 5, 16, 8, 4, 2, 1, soit 8 étapes. Pour 7 : 16 étapes. Personne n'a jamais démontré que cette boucle s'arrête pour tout n (c'est la conjecture de Syracuse), même si on l'a vérifié pour d'immenses quantités de nombres : un bel exemple de boucle dont la finitude n'est pas évidente.

Tu avais trouvé ?

Chapitre terminé !

Fais les 8 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Trace d'exécution, jeux d'essai et débogageRevoir le sommaire du cours