Zoeken…


Syntaxis

  • /* alle versies */
  • voor ([expressie]; [expressie]; [expressie]) one_statement
  • voor ([expressie]; [expressie]; [expressie]) {nul of meerdere beweringen}
  • terwijl (expressie) one_statement
  • terwijl (expressie) {nul of meerdere beweringen}
  • do one_statement while (expressie);
  • doe {een of meer statements} while (expressie);
  • // sinds C99 naast het bovenstaande formulier
  • voor (verklaring; [uitdrukking]; [uitdrukking]) one_statement;
  • voor (verklaring; [uitdrukking]; [uitdrukking]) {nul of meerdere verklaringen}

Opmerkingen

Iteratie Statement / Loops vallen in twee categorieën:

  • head-gecontroleerde iteratie statement / loops
  • voetgestuurde iteratie-instructie / lussen

Head-Controlter Iteration Statement / Loops

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

Voetgestuurde herhalingstekst / lussen

do <statement> while (<expression>);

For loop

Om een codeblok opnieuw en opnieuw uit te voeren, komen lussen in beeld. De for lus moet worden gebruikt wanneer een codeblok een vast aantal keren moet worden uitgevoerd. Om bijvoorbeeld een array met grootte n te vullen met de gebruikersinvoer, moeten we scanf() n keer uitvoeren.

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

Op deze manier wordt de functie-aanroep scanf() n keer uitgevoerd (10 keer in ons voorbeeld), maar wordt deze slechts eenmaal geschreven.

Hier is de variabele i de lusindex en kan deze het beste als gepresenteerd worden opgegeven. Het type size_t (type formaat) moet worden gebruikt voor alles dat telt of lussen door middel van data-objecten.

Deze manier om variabelen in de for declareren, is alleen beschikbaar voor compilers die zijn bijgewerkt naar de C99-standaard. Als je om de een of andere reden nog steeds met een oudere compiler zit, kun je de lusindex vóór de for lus declareren:

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

Herhalingslus

Een while lus wordt gebruikt om een stukje code uit te voeren terwijl een voorwaarde waar is. De while lus moet worden gebruikt wanneer een codeblok een variabel aantal keren moet worden uitgevoerd. De getoonde code krijgt bijvoorbeeld de invoer van de gebruiker, zolang de gebruiker getallen invoert die niet 0 . Als de gebruiker 0 invoegt, is de voorwaarde while niet meer waar, dus de uitvoering verlaat de lus en gaat door naar een volgende code:

int num = 1;

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

Do-While-lus

Anders dan for en while lussen, controleren do-while lussen de waarheid van de voorwaarde aan het einde van de lus, wat betekent dat het do blok één keer wordt uitgevoerd en vervolgens de toestand van de while code onderaan het blok controleert. Dit betekent dat een do-while lus altijd minstens één keer wordt uitgevoerd.

Deze do-while lus krijgt bijvoorbeeld getallen van de gebruiker, totdat de som van deze waarden groter is dan of gelijk is aan 50 :

int num, sum;
num = sum = 0;

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

} while (sum < 50);

do-while lussen zijn relatief zeldzaam in de meeste programmeerstijlen.

Structuur en controlestroom in een for-lus

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

In een for lus heeft de lusvoorwaarde drie expressies, alle optioneel.

  • De eerste expressie, declaration-or-expression , initialiseert de lus. Het wordt precies één keer aan het begin van de lus uitgevoerd.
C99

Het kan een declaratie en initialisatie van een lusvariabele zijn, of een algemene uitdrukking. Als het een verklaring is, wordt het bereik van de gedeclareerde variabele beperkt door de instructie for .

C99

Historische versies van C stonden hier alleen een expressie toe en de verklaring van een lusvariabele moest vóór de for worden geplaatst.

  • De tweede expressie, expression2 , is de testvoorwaarde . Het wordt eerst uitgevoerd na de initialisatie. Als de voorwaarde true , komt de besturing in het lichaam van de lus. Zo niet, dan verschuift deze naar buiten het lichaam van de lus aan het einde van de lus. Vervolgens wordt deze voorwaarde gecontroleerd na elke uitvoering van de hoofdtekst en de update-instructie. Als het true , gaat de besturing terug naar het begin van het lichaam van de lus. De voorwaarde is meestal bedoeld als een controle op het aantal keren dat de body van de lus wordt uitgevoerd. Dit is de primaire manier om een lus te verlaten, de andere manier is om jump-instructies te gebruiken .
  • De derde expressie, expression3 , is de update-instructie . Het wordt uitgevoerd na elke uitvoering van het lichaam van de lus. Het wordt vaak gebruikt om een variabele te verhogen die het aantal keren dat het luslichaam heeft uitgevoerd, verhoogt en deze variabele wordt een iterator genoemd .

Elke uitvoering van het luslichaam wordt een iteratie genoemd .

Voorbeeld:

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

De output is:

0123456789

In het bovenstaande voorbeeld wordt eerst i = 0 uitgevoerd, waardoor i wordt geïnitialiseerd. Vervolgens wordt de voorwaarde i < 10 gecontroleerd, die evalueert als true . De besturing gaat het lichaam van de lus binnen en de waarde van i wordt afgedrukt. Vervolgens verschuift de besturing naar i++ , waarbij de waarde van i wordt bijgewerkt van 0 naar 1. Vervolgens wordt de voorwaarde opnieuw gecontroleerd en gaat het proces verder. Dit gaat door totdat de waarde van i wordt. Vervolgens wordt de voorwaarde i < 10 false geëvalueerd, waarna de besturing uit de lus komt.

Oneindige lussen

Van een lus wordt gezegd dat het een oneindige lus is als de besturing binnenkomt maar nooit het lichaam van de lus verlaat. Dit gebeurt wanneer de testvoorwaarde van de lus nooit als false evalueert.

Voorbeeld:

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

In het bovenstaande voorbeeld wordt de variabele i , de iterator, geïnitialiseerd op 0. De testvoorwaarde is aanvankelijk true . i wordt echter nergens in het lichaam gewijzigd en de update-expressie is leeg. Daarom zal i 0 blijven en zal de testvoorwaarde nooit als false evalueren, wat leidt tot een oneindige lus.

Ervan uitgaande dat er geen springinstructies zijn, is een andere manier om een oneindige lus te vormen, door de voorwaarde expliciet waar te houden:

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

In een for lus is de voorwaarde-instructie optioneel. In dit geval is de toestand altijd vacuuum true , wat leidt tot een oneindige lus.

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

In bepaalde gevallen kan de voorwaarde echter opzettelijk true worden gehouden, met de bedoeling de lus te verlaten met behulp van een jump-statement zoals break .

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

Loop Unrolling en Duff's Device

Soms kan de rechtlijnige lus niet volledig in het luslichaam worden opgenomen. Dit komt omdat de lus moet worden gevuld met enkele uitspraken B. Vervolgens begint de iteratie met enkele uitspraken A , die vervolgens weer worden gevolgd door B voordat een lus wordt gemaakt.

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

Om mogelijke knip / plak problemen met het tweemaal herhalen van B in de code te voorkomen, kan Duff's Device worden toegepast om de lus vanaf het midden van de while body te starten, met behulp van een schakelinstructie en doorvalgedrag.

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

Duff's Device is eigenlijk uitgevonden om lusafrollen te implementeren. Stel je voor dat je een masker op een geheugenblok toepast, waarbij n een getekend integraal type is met een positieve waarde.

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

Als n altijd deelbaar was door 4, zou je dit gemakkelijk kunnen uitrollen als:

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

Maar met Duff's Device kan de code dit afrollende idioom volgen dat op de juiste plaats in het midden van de lus springt als n niet deelbaar is door 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);

Dit soort handmatig uitrollen is zelden vereist bij moderne compilers, omdat de optimalisatie-engine van de compiler namens de programmeur lussen kan uitrollen.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow