C Language
Énoncés d'itération / boucles: pour, pendant et après
Recherche…
Syntaxe
- /* toutes les versions */
- pour ([expression]; [expression]; [expression]) one_statement
- for ([expression]; [expression]; [expression]) {zéro ou plusieurs déclarations}
- while (expression) one_statement
- while (expression) {zéro ou plusieurs déclarations}
- faire one_statement while (expression);
- faire {une ou plusieurs déclarations} while (expression);
- // depuis C99 en plus du formulaire ci-dessus
- pour (déclaration; [expression]; [expression]) one_statement;
- for (declaration; [expression]; [expression]) {zéro ou plusieurs déclarations}
Remarques
L'énoncé d'itération / les boucles se divisent en deux catégories:
- instruction / boucles d'itération contrôlée par la tête
- instruction d'itération / boucles contrôlées par le pied
Relevé d'itération / boucles sous contrôle de la tête
for ([<expression>]; [<expression>]; [<expression>]) <statement>
while (<expression>) <statement>
for ([declaration expression]; [expression] [; [expression]]) statement
Relevé d'itération / boucles contrôlées au pied
do <statement> while (<expression>);
Pour la boucle
Afin d'exécuter un bloc de code sur une nouvelle fois, des boucles apparaissent dans l'image. La boucle for
doit être utilisée lorsqu'un bloc de code doit être exécuté un nombre de fois fixe. Par exemple, pour remplir un tableau de taille n
avec les entrées utilisateur, nous devons exécuter scanf()
n
fois.
#include <stddef.h> // for size_t
int array[10]; // array of 10 int
for (size_t i = 0; i < 10; i++) // i starts at 0 and finishes with 9
{
scanf("%d", &array[i]);
}
De cette façon, l'appel de la fonction scanf()
est exécuté n
fois (10 fois dans notre exemple), mais n'est écrit qu'une seule fois.
Ici, la variable i
est l’indice de boucle et il est préférable de le déclarer comme présenté. Le type size_t
( type de taille ) doit être utilisé pour tout ce qui compte ou parcourt des objets de données.
Cette façon de déclarer des variables dans le for
est uniquement disponible pour les compilateurs mis à jour avec le standard C99. Si pour une raison quelconque vous êtes toujours bloqué avec un ancien compilateur, vous pouvez déclarer l'index de la boucle avant la boucle for
:
#include <stddef.h> /* for size_t */
size_t i;
int array[10]; /* array of 10 int */
for (i = 0; i < 10; i++) /* i starts at 0 and finishes at 9 */
{
scanf("%d", &array[i]);
}
En boucle
A while
la boucle est utilisée pour exécuter un morceau de code tandis qu'une condition est vraie. Le while
en boucle doit être utilisé quand un bloc de code doit être exécuté un nombre variable de fois. Par exemple, le code affiché reçoit l'entrée utilisateur, à condition que l'utilisateur insère des nombres qui ne sont pas 0
. Si l'utilisateur insère 0
, la condition while n'est plus vraie, donc l'exécution quittera la boucle et passera à n'importe quel code suivant:
int num = 1;
while (num != 0)
{
scanf("%d", &num);
}
Boucle Do-While
Contrairement for
boucles for
et while
boucles do-while
vérifient la vérité de la condition à la fin de la boucle, ce qui signifie que le bloc do
s'exécutera une fois, puis vérifie l'état du while
en bas du bloc. Ce qui signifie qu'une boucle do-while
fong sera toujours exécutée au moins une fois.
Par exemple, cette boucle do-while
while aura des nombres d'utilisateurs, jusqu'à ce que la somme de ces valeurs soit supérieure ou égale à 50
:
int num, sum;
num = sum = 0;
do
{
scanf("%d", &num);
sum += num;
} while (sum < 50);
do-while
boucles do-while
sont relativement rares dans la plupart des styles de programmation.
Structure et flux de contrôle dans une boucle for
for ([declaration-or-expression]; [expression2]; [expression3])
{
/* body of the loop */
}
Dans une boucle for
, la condition de la boucle a trois expressions, toutes facultatives.
- La première expression,
declaration-or-expression
, initialise la boucle. Il est exécuté exactement une fois au début de la boucle.
Il peut s'agir d'une déclaration et d'une initialisation d'une variable de boucle ou d'une expression générale. S'il s'agit d'une déclaration, la portée de la variable déclarée est restreinte par l'instruction for
.
Les versions historiques de C permettaient uniquement une expression, ici, et la déclaration d'une variable de boucle devait être placée avant le for
.
- La deuxième expression,
expression2
, est la condition de test . Il est d'abord exécuté après l'initialisation. Si la condition esttrue
, le contrôle entre dans le corps de la boucle. Sinon, il passe à l'extérieur du corps de la boucle à la fin de la boucle. Par la suite, cette condition est vérifiée après chaque exécution du corps ainsi que la déclaration de mise à jour. Lorsquetrue
, le contrôle revient au début du corps de la boucle. La condition est généralement destinée à vérifier le nombre d'exécutions du corps de la boucle. C'est le moyen principal de sortir d'une boucle, l'autre étant d'utiliser des instructions de saut . - La troisième expression,
expression3
, est la déclaration de mise à jour . Il est exécuté après chaque exécution du corps de la boucle. Il est souvent utilisé pour incrémenter un nombre de variables du nombre de fois que le corps de la boucle a été exécuté, et cette variable est appelée un itérateur .
Chaque instance d'exécution du corps de la boucle est appelée une itération .
Exemple:
for(int i = 0; i < 10 ; i++)
{
printf("%d", i);
}
La sortie est la suivante:
0123456789
Dans l'exemple ci-dessus, i = 0
est d'abord exécuté, en initialisant i
. Ensuite, la condition i < 10
est vérifiée, ce qui est considéré comme true
. Le contrôle entre dans le corps de la boucle et la valeur de i
est imprimée. Ensuite, le contrôle passe à i++
, en mettant à jour la valeur de i
de 0 à 1. La condition est à nouveau vérifiée et le processus continue. Cela continue jusqu'à ce que la valeur de i
devienne 10. Ensuite, la condition i < 10
false
, après quoi le contrôle sort de la boucle.
Boucles infinies
Une boucle est dite une boucle infinie si le contrôle entre mais ne quitte jamais le corps de la boucle. Cela se produit lorsque la condition de test de la boucle n'est jamais évaluée à false
.
Exemple:
for (int i = 0; i >= 0; )
{
/* body of the loop where i is not changed*/
}
Dans l'exemple ci-dessus, la variable i
, l'itérateur, est initialisée à 0. La condition de test est initialement true
. Cependant, i
ne i
modifié nulle part dans le corps et l'expression de mise à jour est vide. Par conséquent, i
resterai 0 et la condition de test ne sera jamais évaluée à false
, conduisant à une boucle infinie.
En supposant qu'il n'y ait pas d' instruction de saut, une autre manière de former une boucle infinie consiste à conserver la condition de façon explicite:
while (true)
{
/* body of the loop */
}
Dans une boucle for
, l'instruction de condition est facultative. Dans ce cas, la condition est toujours true
, conduisant à une boucle infinie.
for (;;)
{
/* body of the loop */
}
Cependant, dans certains cas, la condition peut être conservé true
volontairement, avec l'intention de sortir de la boucle en utilisant une instruction de saut comme la break
.
while (true)
{
/* statements */
if (condition)
{
/* more statements */
break;
}
}
Loop Unrolling et Duff's Device
Parfois, la boucle directe ne peut pas être entièrement contenue dans le corps de la boucle. En effet, la boucle doit être amorcée par certaines instructions B. Ensuite, l'itération commence par quelques instructions A , qui sont ensuite suivies par B avant de boucler.
do_B();
while (condition) {
do_A();
do_B();
}
Pour éviter réduire le potentiel / problèmes de pâte à répéter B deux fois dans le code, le dispositif de Duff pourrait être appliquée pour démarrer la boucle à partir du milieu du while
corps, en utilisant une instruction switch et tomber par un comportement.
switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default: do_B(); /* FALL THROUGH */
}
Le dispositif de Duff a été inventé pour implémenter le déroulement des boucles. Imaginez appliquer un masque à un bloc de mémoire, où n
est un type intégral signé avec une valeur positive.
do {
*ptr++ ^= mask;
} while (--n > 0);
Si n
était toujours divisible par 4, vous pourriez facilement le dérouler comme suit:
do {
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
} while ((n -= 4) > 0);
Mais, avec Device Duff, le code peut suivre cet idiome déroulant qui saute au bon endroit au milieu de la boucle si n
n'est pas divisible par 4.
switch (n % 4) do {
case 0: *ptr++ ^= mask; /* FALL THROUGH */
case 3: *ptr++ ^= mask; /* FALL THROUGH */
case 2: *ptr++ ^= mask; /* FALL THROUGH */
case 1: *ptr++ ^= mask; /* FALL THROUGH */
} while ((n -= 4) > 0);
Ce type de déroulement manuel est rarement requis avec les compilateurs modernes, car le moteur d'optimisation du compilateur peut dérouler les boucles au nom du programmeur.