Aller au contenu

Programmation C/Itérations

Un livre de Wikilivres.


for (initialisation ; condition ; itération)
    bloc

Une boucle for commence par l'initialisation, puis exécute le bloc de code tant que la condition est vérifiée et en appelant l'itération après chaque bloc.

On peut tout de suite remarquer que la boucle for du C est beaucoup plus puissante qu'une boucle for classique, dans le sens où elle ne correspond pas forcément à un nombre fini de tours de boucle.

La norme C99 permet maintenant de déclarer des variables dans la partie initialisation de la boucle for. Ces variables ne peuvent qu'être de classe automatic ou register. Leur portée est limitée à la boucle. Elles n'interfèrent pas avec les variables de même nom déclarées en dehors de la boucle. Leur utilisation pourrait conduire à de possibles optimisations du code par le compilateur.

int i;
for (i = 0 ; i < 10 ; i++)
{
    printf("%d\n", i);
}

En C++ :

for (int i = 0 ; i < 10 ; i++)
{
    printf("%d\n", i);
}

Cet exemple est une boucle for normale, l'indice de boucle i est incrémenté à chaque tour et le bloc ne fait qu'afficher l'indice. Ce code affiche donc les 10 premiers entiers en partant de 0. Le bloc de code étant réduit à une instruction, on aurait pu écrire :

int i;
for (i = 0 ; i < 10 ; i++)
    printf("%d\n", i);
int i = 0;
for( ; i != 1 ; i = rand() % 4)
{
        printf("je continue\n");
}

Ce deuxième exemple montre plusieurs choses :

  1. l'initialisation de la boucle a été omise, en fait n'importe laquelle des trois parties peut l'être (et même les trois à la fois, ce qui résulte en une boucle infinie) ;
  2. l'expression itération est réellement une expression, on peut y faire appel à des fonctions ;
  3. le nombre d'itérations n'est pas fixe, le programme affichera « je continue » un nombre (pseudo-)aléatoire de fois.
 for(;;) crée une boucle infinie.
while (condition)
    bloc

Une boucle while exécute le bloc d'instructions tant que la condition est vérifiée.

int i = 0;
while (i < 10)
{
        printf("%d\n", i);
        i = i + 1;
}

Cet exemple est le même que celui vu précédement pour la boucle for, il affiche les dix premiers entiers à partir de 0.

Boucle do-while

[modifier | modifier le wikicode]
do
    bloc
while (condition);

Cette boucle est une légère variante de la précédente. Elle exécute donc le bloc au moins une fois, et ce jusqu'à ce que la condition soit fausse (ou tant que la condition est vraie).

#include <stdio.h>

int main(void)
{
    int i = 0;
    do
    {
        printf("%d\n", i);
        i = i + 1;
    } while (i < 10);
    return 0;
}

Exemple identique à celui de la boucle while au dessus, on affiche les nombres de 0 jusqu'à 9.

#include <stdio.h>

int main(void)
{
    char c;
    do
    {
        printf("Veuillez taper la lettre 'o'\n");
        scanf("%c", &c);
    } while (c != 'o');
    return 0;
}

Cette fois on voit l'utilité de la boucle do-while, la variable est initialisée dans la boucle. On doit tester sa valeur à la fin de l'itération. Tant que l'utilisateur n'aura pas tapé la lettre o, le programme redemandera de taper la lettre.

http://fr.wikibooks.org/wiki/Discussion:Programmation_C/Pointeurs#Exemple_Complet_sur_les_boucles.2C_les_tableaux_et_les_pointeurs

Arrêt et continuation des boucles

[modifier | modifier le wikicode]

Il arrive fréquemment qu'en évaluant un test à l'intérieur d'une boucle, on aimerait arrêter brutalement la boucle ou alors « sauter » certains cas non significatifs. C'est le rôle des instructions break et continue.

  • break permet de sortir immédiatement d'une boucle for, while ou do-while. À noter que si la boucle se trouve elle-même dans une autre boucle, seule la boucle où l'instruction break se trouvait est stoppée.
  • continue permet de recommencer la boucle depuis le début du bloc. Dans le cas de la boucle for, le bloc lié à l'incrémentation sera exécuté, puis dans tous les cas, la condition sera testée.

Saut inconditionnel (goto)

[modifier | modifier le wikicode]

Cette instruction permet de continuer l'exécution du programme à un autre endroit, dans la même fonction. On l'utilise de la manière suivante :

goto label;

label est un identificateur quelconque. Cet identificateur devra être défini quelque part dans la même fonction, avec la syntaxe suivante :

label:

Ce label peut être mis à n'importe quel endroit dans la fonction, y compris avant ou après le goto, ou dans un autre bloc que là où sont utilisés la ou les instructions goto pointant vers ce label. Les labels doivent être uniques au sein d'une même fonction, mais on peut les réutiliser dans une autre fonction.

Un cas où l'emploi d'une instruction goto est tout à fait justifié, par exemple, est pour simuler le déclenchement d'une exception, pour sortir rapidement de plusieurs boucles imbriquées.

void boucle(void)
{
    while (1)
    {
        struct Evenement_t * event;

        attend_evenement();

        while ((event = retire_evenement()))
        {
            switch (event->type) {
            case FIN_TRAITEMENT:
                goto fin;
            /* ... */
            }
        }
    }
    fin:
    /* ... */
}

Dans ce cas de figure, il serait possible d'utiliser aussi un booléen qui indique que le traitement est terminé, pour forcer la sortie des boucles. L'utilisation de goto dans cet exemple ne nuisant pas à la lisibilité du programme et étant tout aussi efficace, il est tout à fait légitime de l'utiliser.

Il faut cependant noter que cette instruction est souvent considérée comme à éviter. En effet, elle provoque un saut dans le code, qui se « voit » beaucoup moins bien que les structures de contrôle comme if ou while, par exemple. De fait, la pratique a montré qu'un abus de son utilisation rend un code source rapidement peu compréhensible, et difficilement maintenable. L'article de Edsger W. Dijsktra Go to considered harmful anglais, datant de 1968, est l'exemple le plus connu de cette critique, qui a donné naissance à la programmation structurée.