Szukaj…


Składnia

  • /* wszystkie wersje */
  • for ([wyrażenie]; [wyrażenie]; [wyrażenie]) one_statement
  • for ([wyrażenie]; [wyrażenie]; [wyrażenie]) {zero lub kilka instrukcji}
  • while (wyrażenie) one_statement
  • while (wyrażenie) {zero lub kilka instrukcji}
  • wykonaj one_statement while (wyrażenie);
  • do {jedna lub więcej instrukcji} while (wyrażenie);
  • // od C99 oprócz powyższego formularza
  • for (deklaracja; [wyrażenie]; [wyrażenie]) one_statement;
  • for (deklaracja; [wyrażenie]; [wyrażenie]) {zero lub kilka instrukcji}

Uwagi

Instrukcja iteracyjna / Pętle dzielą się na dwie kategorie:

  • instrukcja / pętle iteracji sterowane głowicą
  • instrukcja / pętle iteracji sterowane stopą

Oświadczenie o iteracji sterowane przez głowę / pętle

for ([<expression>]; [<expression>]; [<expression>]) <statement>
while (<expression>) <statement>
C99
for ([declaration expression]; [expression] [; [expression]]) statement

Oświadczenie / pętle sterowane stopą

do <statement> while (<expression>);

Dla pętli

Aby ponownie wykonać blok kodu, na obrazie pojawia się pętla. Pętli for należy używać, gdy blok kodu ma być wykonywany określoną liczbę razy. Na przykład, aby wypełnić tablicę rozmiaru n danymi wejściowymi użytkownika, musimy wykonać scanf() n razy.

C99
#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]);
}

W ten sposób wywołanie funkcji scanf() jest wykonywane n razy (w naszym przykładzie 10 razy), ale jest zapisywane tylko raz.

Tutaj zmienna i jest indeksem pętli i najlepiej jest ją zadeklarować zgodnie z prezentacją. Typ size_t ( typ rozmiaru ) powinien być używany do wszystkiego, co się liczy lub zapętla obiekty danych.

Ten sposób deklarowania zmiennych wewnątrz for jest dostępny tylko dla kompilatorów, które zostały zaktualizowane do standardu C99. Jeśli z jakiegoś powodu nadal tkwisz w starszym kompilatorze, możesz zadeklarować indeks pętli przed pętlą for :

C99
#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]);
}

Podczas pętli

while pętla jest używana do wykonania kawałek kodu, podczas gdy warunek jest prawdziwy. while pętla ma być stosowane, gdy blok kodu jest wykonywane różną liczbę razy. Na przykład pokazany kod pobiera dane wejściowe użytkownika, o ile użytkownik wstawi cyfry, które nie są 0 . Jeśli użytkownik wstawi 0 , warunek while nie jest już spełniony, więc wykonanie opuści pętlę i przejdzie do dowolnego kolejnego kodu:

int num = 1;

while (num != 0)
{
    scanf("%d", &num);
}

Pętla Do-While

W przeciwieństwie for i while pętli do-while Pętle sprawdzić prawdziwość stanu na koniec pętli, co oznacza, że do blok będzie wykonać raz, a następnie sprawdzić stan while w dolnej części bloku. Oznacza to, że pętla „ do-while while” zawsze będzie działać co najmniej raz.

Na przykład ta pętla „ do-while while” otrzyma liczby od użytkownika, aż suma tych wartości będzie większa lub równa 50 :

int num, sum;
num = sum = 0;

do 
{
  scanf("%d", &num);
  sum += num;

} while (sum < 50);

pętle do-while są stosunkowo rzadkie w większości stylów programowania.

Struktura i przepływ kontroli w pętli for

for ([declaration-or-expression]; [expression2]; [expression3])
{
    /* body of the loop */
}

W pętli for warunek pętli ma trzy wyrażenia, wszystkie opcjonalne.

  • Pierwsze wyrażenie, declaration-or-expression , inicjuje pętlę. Jest wykonywany dokładnie raz na początku pętli.
C99

Może to być deklaracja i inicjalizacja zmiennej pętli lub ogólne wyrażenie. Jeśli jest to deklaracja, zakres deklarowanej zmiennej jest ograniczony przez instrukcję for .

C99

Historyczne wersje C pozwalały tylko na wyrażenie, a deklaracja zmiennej pętli musiała być umieszczona przed for .

  • Drugie wyrażenie, expression2 , jest warunkiem testu . Najpierw jest wykonywany po inicjalizacji. Jeśli warunek jest true , formant wchodzi w ciało pętli. Jeśli nie, przesuwa się na zewnątrz korpusu pętli na końcu pętli. Następnie ten warunek jest sprawdzany po każdym wykonaniu treści oraz instrukcji aktualizacji. Gdy jest to true , formant przesuwa się z powrotem na początek korpusu pętli. Warunkiem jest zwykle sprawdzenie, ile razy wykonuje się treść pętli. Jest to podstawowy sposób na wyjście z pętli, innym sposobem jest użycie instrukcji skoku .
  • Trzecie wyrażenie, expression3 , jest instrukcją aktualizacji . Jest wykonywany po każdym wykonaniu treści pętli. Jest często używany do zwiększania zmiennej zliczającej liczbę wykonań ciała pętli, a ta zmienna nazywana jest iteratorem .

Każde wystąpienie wykonania elementu pętli nazywane jest iteracją .

Przykład:

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

Dane wyjściowe to:

0123456789

W powyższym przykładzie pierwsze i = 0 jest wykonywane, inicjując i . Następnie sprawdzany jest warunek i < 10 , który uznaje się za true . Element sterujący wchodzi w ciało pętli i drukowana jest wartość i . Następnie formant przesuwa się do i++ , aktualizując wartość i z 0 na 1. Następnie warunek jest ponownie sprawdzany i proces jest kontynuowany. Trwa to do momentu, aż wartość i osiągnie 10. Następnie warunek i < 10 ocenia false , po czym kontrola wychodzi z pętli.

Nieskończone pętle

Mówi się, że pętla jest nieskończoną pętlą, jeśli element sterujący wejdzie, ale nigdy nie opuści ciała pętli. Dzieje się tak, gdy warunek testowy pętli nigdy nie jest równy false .

Przykład:

C99
for (int i = 0; i >= 0; )
{
    /* body of the loop where i is not changed*/
}

W powyższym przykładzie, zmienna i , iterator, jest inicjowany na 0. Stan test jest początkowo true . Jednak i nie jest modyfikowany w dowolnym miejscu ciała i wyrazem aktualizacja jest pusty. Stąd też i pozostanie 0, a stan testu nigdy oceni na false , co prowadzi do nieskończonej pętli.

Zakładając, że nie ma instrukcji skoku, innym sposobem utworzenia nieskończonej pętli jest jawne zachowanie warunku:

while (true)
{
    /* body of the loop */
}

W pętli for instrukcja warunku jest opcjonalna. W takim przypadku warunek jest zawsze true próżniowo, co prowadzi do nieskończonej pętli.

for (;;)
{
    /* body of the loop */
}

Jednak w niektórych przypadkach warunek może być celowo true , z zamiarem wyjścia z pętli za pomocą instrukcji skoku, takiej jak break .

while (true)
{
    /* statements */
    if (condition)
    {
         /* more statements */
         break;
    }
}

Rozwijanie pętli i urządzenie Duffa

Czasami prosta pętla nie może być całkowicie zawarta w treści pętli. Wynika to z tego, że pętla musi zostać zainicjowana przez niektóre instrukcje B. Następnie iteracja rozpoczyna się od niektórych instrukcji A , po których następuje powtórka B przed zapętleniem.

do_B();
while (condition) {
    do_A();
    do_B();
}

Aby uniknąć potencjalnych problemów z wycinaniem / wklejaniem przy dwukrotnym powtarzaniu B w kodzie, można zastosować Urządzenie Duffa, aby uruchomić pętlę od środka ciała while , używając instrukcji switch i przechodząc przez zachowanie.

switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default:    do_B(); /* FALL THROUGH */
}

Urządzenie Duffa zostało faktycznie wynalezione w celu zaimplementowania rozwijania pętli. Wyobraź sobie zastosowanie maski do bloku pamięci, gdzie n jest znakiem całki ze znakiem o wartości dodatniej.

do {
    *ptr++ ^= mask;
} while (--n > 0);

Gdyby n było zawsze podzielne przez 4, można to łatwo rozwinąć jako:

do {
    *ptr++ ^= mask;
    *ptr++ ^= mask;
    *ptr++ ^= mask;
    *ptr++ ^= mask;
} while ((n -= 4) > 0);

Ale w urządzeniu Duffa kod może podążać za rozwijającym się idiomem, który przeskakuje we właściwe miejsce na środku pętli, jeśli n nie jest podzielne przez 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);

Tego rodzaju ręczne rozwijanie rzadko jest wymagane w nowoczesnych kompilatorach, ponieważ silnik optymalizacji kompilatora może rozwijać pętle w imieniu programisty.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow