C Language
Iterazioni / loop di iterazione: per, while, do-while
Ricerca…
Sintassi
- / * tutte le versioni * /
- per ([espressione]; [espressione]; [espressione]) one_statement
- for ([espressione]; [espressione]; [espressione]) {zero o più affermazioni}
- while (espressione) one_statement
- while (espressione) {zero o più istruzioni}
- fai uno_statoment while (espressione);
- fare {una o più affermazioni} mentre (espressione);
- // dal C99 in aggiunta al modulo sopra
- per (dichiarazione; [espressione]; [espressione]) one_statement;
- for (declaration; [expression]; [expression]) {zero o più istruzioni}
Osservazioni
Iteration Statement / Loops si dividono in due categorie:
- istruzione / loop di iterazione controllata dalla testa
- istruzione / loop di iterazione comandata a pedale
Dichiarazione / cicli di iterazione controllati dalla testa
for ([<expression>]; [<expression>]; [<expression>]) <statement>
while (<expression>) <statement>
for ([declaration expression]; [expression] [; [expression]]) statement
Iterazione / loop di iterazione a pedale
do <statement> while (<expression>);
Per ciclo
Per eseguire un blocco di codice su un altro, i loop entrano in scena. Il ciclo for
deve essere utilizzato quando un blocco di codice deve essere eseguito un numero fisso di volte. Ad esempio, per riempire una matrice di dimensione n
con gli input dell'utente, è necessario eseguire scanf()
per n
volte.
#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]);
}
In questo modo la chiamata della funzione scanf()
viene eseguita n
volte (10 volte nel nostro esempio), ma viene scritta una sola volta.
Qui, la variabile i
è l'indice del ciclo e viene dichiarata come presentata. Il tipo size_t
( tipo di dimensione ) deve essere utilizzato per tutto ciò che conta o esegue il ciclo tra gli oggetti dati.
Questo modo di dichiarare le variabili all'interno di for
è disponibile solo per i compilatori che sono stati aggiornati allo standard C99. Se per qualche motivo sei ancora bloccato con un compilatore più vecchio, puoi dichiarare l'indice del ciclo prima del ciclo 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]);
}
Mentre loop
Un ciclo while
viene utilizzato per eseguire un pezzo di codice mentre una condizione è vera. Il ciclo while
deve essere usato quando un blocco di codice deve essere eseguito un numero variabile di volte. Ad esempio, il codice mostrato ottiene l'input dell'utente, a condizione che l'utente inserisca numeri che non sono 0
. Se l'utente inserisce 0
, la condizione while non è più true, quindi l'esecuzione uscirà dal ciclo e continuerà su qualsiasi codice successivo:
int num = 1;
while (num != 0)
{
scanf("%d", &num);
}
Ciclo Do-While
A differenza for
cicli while
e while
, i loop do-while
verificano la verità della condizione alla fine del ciclo, il che significa che il blocco do
verrà eseguito una volta, quindi verificherà la condizione del while
nella parte inferiore del blocco. Il che significa che un do-while
ciclo sarà sempre eseguito almeno una volta.
Ad esempio questo ciclo do-while
otterrà i numeri dall'utente, fino a quando la somma di questi valori è maggiore o uguale a 50
:
int num, sum;
num = sum = 0;
do
{
scanf("%d", &num);
sum += num;
} while (sum < 50);
do-while
cicli di do-while
sono relativamente rari nella maggior parte degli stili di programmazione.
Struttura e flusso di controllo in un ciclo for
for ([declaration-or-expression]; [expression2]; [expression3])
{
/* body of the loop */
}
In un ciclo for
, la condizione del ciclo ha tre espressioni, tutte opzionali.
- La prima espressione,
declaration-or-expression
, inizializza il ciclo. Viene eseguito esattamente una volta all'inizio del ciclo.
Può essere una dichiarazione e l'inizializzazione di una variabile di loop o un'espressione generale. Se si tratta di una dichiarazione, l'ambito della variabile dichiarata è limitato dall'istruzione for
.
Le versioni storiche di C consentivano solo un'espressione, qui, e la dichiarazione di una variabile di loop doveva essere posizionata prima del for
.
- La seconda espressione,
expression2
, è la condizione di test . Viene prima eseguito dopo l'inizializzazione. Se la condizione ètrue
, il controllo entra nel corpo del ciclo. In caso contrario, si sposta all'esterno del corpo del ciclo alla fine del ciclo. Successivamente, questa condizione viene verificata dopo ogni esecuzione del corpo, nonché la dichiarazione di aggiornamento. Quando ètrue
, il controllo torna all'inizio del corpo del loop. La condizione è solitamente intesa come un controllo sul numero di volte in cui il corpo del ciclo viene eseguito. Questo è il modo principale di uscire da un ciclo, l'altro modo è usare le istruzioni di salto . - La terza espressione,
expression3
, è l' istruzione di aggiornamento . Viene eseguito dopo ogni esecuzione del corpo del loop. Viene spesso usato per incrementare una variabile tenendo conto del numero di volte che il corpo del ciclo ha eseguito, e questa variabile è chiamata iteratore .
Ogni istanza di esecuzione del corpo del ciclo viene chiamata iterazione .
Esempio:
for(int i = 0; i < 10 ; i++)
{
printf("%d", i);
}
L'output è:
0123456789
Nell'esempio sopra, viene eseguito first i = 0
, inizializzando i
. Quindi, viene controllata la condizione i < 10
, che risulta essere true
. Il controllo entra nel corpo del ciclo e il valore di i
viene stampato. Quindi, il controllo passa a i++
, aggiornando il valore di i
da 0 a 1. Quindi, la condizione viene nuovamente controllata e il processo continua. Questo va avanti finché il valore di i
diventa 10. Quindi, la condizione i < 10
valutata false
, dopo di che il controllo si sposta fuori dal ciclo.
Cicli infiniti
Si dice che un ciclo è un ciclo infinito se il controllo entra ma non lascia mai il corpo del ciclo. Questo accade quando la condizione di test del loop non è mai false
.
Esempio:
for (int i = 0; i >= 0; )
{
/* body of the loop where i is not changed*/
}
Nell'esempio sopra, la variabile i
, l'iteratore, viene inizializzata su 0. La condizione di test è inizialmente true
. Tuttavia, i
non viene modificato in qualsiasi parte del corpo e l'espressione aggiornamento è vuoto. Quindi, i
rimarrà 0, e la condizione di prova sarà mai valutata come false
, portando ad un ciclo infinito.
Supponendo che non ci siano istruzioni di salto, un altro modo in cui un loop infinito potrebbe essere formato è mantenendo esplicitamente la condizione vera:
while (true)
{
/* body of the loop */
}
In un ciclo for
, l'istruzione condizione facoltativa. In questo caso, la condizione è sempre true
vacuo, portando a un ciclo infinito.
for (;;)
{
/* body of the loop */
}
Tuttavia, in alcuni casi, la condizione potrebbe essere mantenuta true
intenzionalmente, con l'intenzione di uscire dal ciclo usando un'istruzione jump come break
.
while (true)
{
/* statements */
if (condition)
{
/* more statements */
break;
}
}
Loop srotolamento e dispositivo di Duff
A volte, il ciclo diretto non può essere interamente contenuto all'interno del corpo del loop. Questo perché, il ciclo deve essere innescato da alcune affermazioni B. Quindi, l'iterazione inizia con alcune istruzioni A , che sono poi seguite da B di nuovo prima del ciclo.
do_B();
while (condition) {
do_A();
do_B();
}
Per evitare potenziali problemi di taglia / incolla ripetendo B due volte nel codice, è possibile applicare il dispositivo di Duff per avviare il loop dal centro del corpo while
usa l' istruzione switch e il comportamento di caduta.
switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default: do_B(); /* FALL THROUGH */
}
Il dispositivo di Duff è stato in realtà inventato per implementare lo srotolamento del loop. Immagina di applicare una maschera a un blocco di memoria, dove n
è un tipo integrale firmato con un valore positivo.
do {
*ptr++ ^= mask;
} while (--n > 0);
Se n
fosse sempre divisibile per 4, potresti srotolarlo facilmente come:
do {
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
} while ((n -= 4) > 0);
Ma con Duff's Device, il codice può seguire questo idioma di svolgimento che salta nel punto giusto nel mezzo del ciclo se n
non è divisibile per 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);
Questo tipo di srotolamento manuale è raramente richiesto con i moderni compilatori, poiché il motore di ottimizzazione del compilatore può srotolare loop per conto del programmatore.