Kurt Nørmark
Institut for Datalogi, Aalborg Universitet
Sammendrag Forrige lektion Næste lektion Stikord Referencer Indhold | I denne lektion gennemgår vi forskellige former for konstrolstrukturer, i hovedsagen forskellige former for selektion og iteration. Som en vigtig og relevant detalje, ser vi også på logiske udtryk, som styrer de fleste kontrolstrukturer. |
Gentagelse af kommandoer |
Gentagelse med while (1) Slide Indhold Stikord Referencer |
|
Syntax: Syntaksen af en while løkke i C. |
|
Figur. Flow graf for en while løkke |
|
|
Gentagelse med while (2) Slide Indhold Stikord Referencer |
|
Program: Euclids algoritme - største fælles divisor - programmeret med en while løkke. |
|
Program: En udgave af Euclids algoritme som udskriver den beregnede talrække. |
|
Program: Talrækken udskrevet fra programmet med input 315 og 120. |
|
Program: En mere basal udgave af Euclids algoritme. |
|
Program: En mere basal udgave af Euclids algoritme - med C compound assignments. |
|
Program: En mere basal udgave af Euclids algoritme - som printer rækken af tal. |
|
|
Opgave 4.4. Forklaring af et program med while løkke og udtryk med assignments | Forklar hvad der udskrives af følgende program. Hvor mange gange udføres kroppen af while-løkken? Og hvilken række af tal udskriver programmet (helt præcist)? Forudsig først resultatet, og kør dernæst programmet. #include <stdio.h> int main(void){ int i = 0, power = 1; while (++i <= 10) printf("%5d", power *= 2); printf("\n"); return 0; } ++i tæller i en op og power *= 2 fordobler power. Men vær sikker på at du forstår værdierne af de to udtryk ++i og power *= 2. Hvad sker der hvis ++i erstattes af i++? Det viste program er skrevet i typisk, koncis C-stil, og er på denne måde en typisk repræsentant for den programmeringsstil, som dyrkes af mange C programmører. Omskriv programmet (stadig med brug af en while-løkke) således at assignments (ala *=) og increments (++) kun har en effekt på variable, men uden direkte at anvende værdierne af disse udtryk, som det er gjort i ovenstående program. Det er også interessant at omskrive programmet, så det bruger en for-løkke i stedet for en while-løkke. Prøv dette! Vurder selv hvilken udgave af programmet du foretrækker. |
Opgave 4.4. Sum af tal i interval som er dividerbare med samme tal | I denne opgave gives tre positive heltal m, n og k, hvor k er større end 1. Skriv et program der adderer alle heltal mellem m og n (begge inklusive) hvor i k går op. Eksempler:
Denne opgave stammer fra bogen C by Dissection - anvendt med tilladelse fra forlaget. |
Opgave 4.4. Endnu en sum af tal i et interval | Skriv et program som læser et heltal n. Programmet skal addere alle tal i intervallet fra n til 2 * n hvis n er ikke negativ. Hvis n er negativ, skal programmet addere tallene fra 2 * n til n. Skriv først en version med for-løkker. Dernæst en version med while løkker. Denne opgave stammer fra bogen C by Dissection - anvendt med tilladelse fra forlaget. |
Gentagelse med do (1) Slide Indhold Stikord Referencer |
|
Syntax: Syntaksen af en do-løkke i C |
|
Figur. Flow graf for en do løkke |
|
Gentagelse med do (2) Slide Indhold Stikord Referencer |
|
Program: Et program som ønsker et 'yes/no' svar. |
|
Gentagelse med for (1) Slide Indhold Stikord Referencer |
|
Syntax: Opbygningen af en for-løkke i C. |
|
Program: En typisk for-løkke med et forudbestemt antal gentagelser. |
|
|
Gentagelse med for (2) Slide Indhold Stikord Referencer |
|
Program: En for løkke med to kontrol variable. |
|
Program: Euclids algoritme - største fælles divisor - programmeret med en for-løkke 'uden krop'. |
|
|
Program: En for løkke, der optæller en variabel uendeligt. |
|
|
Opgave 4.5. Generering af grafik-filer | I denne opgave vil vi generere grafik filer med flotte mønstre. Vi vil benytte et meget simpelt fil-format, Portable Pixmap (PPM). Du kan se på Wikipedia artiklen Netpbm format, som giver et godt overblik over formatet. Der findes også en video der diskuterer formatet, og videoen lægger kort op til denne opgave. Her følger et velkommenteret C program, som genererer et 500 x 500 rødt rektangel: #include <stdio.h> int main(void) { FILE *image_file; /* The file on which to write the image */ int i, j; image_file = fopen("image-file-1.pnm", "wb"); /* Open a file for writing. */ fputs("P6\n", image_file); /* Write the header, including the */ /* so-called magic number P6 */ fputs("500 500\n", image_file); /* Width: 500, Height: 500 */ fputs("255\n", image_file); /* 255 colors per byte. */ for(i = 0; i < 500; i++) for (j = 0; j < 500; j++){ fputc(255, image_file); /* Writing the red byte */ fputc(0, image_file); /* Write the green byte */ fputc(0, image_file); /* Write the blue byte */ } fclose(image_file); /* Close the file. */ return 0; } Her er en variation af programmet, som genererer et lidt mere spændende resultat: #include <stdlib.h> #include <stdio.h> int main(void) { FILE *image_file; int i, j; int r, g, b; image_file = fopen("image-file-4.pnm", "wb"); fputs("P6\n", image_file); fputs("500 500\n", image_file); fputs("255\n", image_file); for(i = 0; i < 500; i++) for (j = 0; j < 500; j++){ r = i % 256; g = j % 256; b = (i+j) % 256; fputc(r, image_file); fputc(g, image_file); fputc(b, image_file); } fclose(image_file); return 0; } Begge programmer udskriver, via den ydre for-løkke, RGB bytes (red, green, blue) række for række. Den kreative udfordringen består i at lave flotte mønstre ved at variere programmerne ovenfor. I denne opgave er det dog en betingelse at de to for-løkker, som kontrollerer hhv. række og søjler i bitmønstret, bibeholdes. Du skal ikke forsøge at lave et stort array af RGB værdier, og ændre i dette. Senere i kurset vil vi udvikle varianter af programmet, som gør det meget mere fleksibelt at tegne forskellige geometriske figurer i en stor tabel (array) af pixels. Det er naturligvis vigtigt, at du kan se den grafik som genereres af dit program. Her er et antal muligheder, som jeg ved virker:
|
Komma operatoren Slide Indhold Stikord Referencer |
|
|
Program: Eksempler på brug af komma operatoren - gode og dårlige. |
|
Program: Output fra programmet. |
|
|
Klassificering af gentagelser Slide Indhold Stikord Referencer |
|
|
Eksempler på forskellige former af gentagelser Slide Indhold Stikord Referencer |
|
Program: Eksempel på counter controlled loop. |
|
Program: Eksempel på sentinel-controlled loop. |
|
Program: Eksempel på sentinel-controlled loop - med typisk fejl. |
|
Program: Eksempel på sentinel-controlled loop - med typisk fejl og forklaring. |
|
Program: Et forsøg på at lave sentinel controlled loop med do-while - med fejl. |
|
Program: Et forsøg på at lave sentinel controlled loop med do-while - med fejl og forklaring. |
|
Program: Et forsøg på at lave sentinel controlled loop med do-while - nu OK. |
|
Program: Eksempel på input validation loop. |
|
Program: Eksempel på input validation loop - med særlig håndtering af første prompt. |
|
Program: Eksempel på general condition loop - Euclids algoritime igen. |
|
Program: Eksempel på flag-controlled loop - Euclids algoritime igen. |
|
Nestede gentagelser Slide Indhold Stikord Referencer |
|
Program: Et eksempel på indlejrede gentagelser. |
|
Program: Program output. |
|
|
Program: Et andet eksempel på indlejrede gentagelser - et kvadrat af bogstaver fra A - Z. |
|
Program: Program output. |
|
Break, continue og return Slide Indhold Stikord Referencer |
|
|
Program: Illustration af break og continue i en for-løkke. |
|
|
Konvertering af do og for løkker til while Slide Indhold Stikord Referencer |
|
Tabel. |
|
|
Flere Opgaver Slide Indhold Stikord Referencer |
Opgave 4.7. En simplificeret udgave af Euclids algoritme | Denne opgaver tager udgangspunkt i følgende udgave af Euclids algoritme, som vi har studeret nøje i denne lektion: /* General condition loop - Euclid again*/ #include <stdio.h> int main(void) { int i, j, small, large, remainder; printf("Enter two positive integers: "); scanf("%d %d", &i, &j); small = i <= j ? i : j; large = i <= j ? j : i; while (small > 0){ remainder = large % small; large = small; small = remainder; } printf("GCD of %d and %d is %d\n\n", i, j, large); return 0; } Hvad sker der hvis vi dropper ombytningen af i og j, og således risikerer at small bliver større end large i while-løkken? Her er en sådan version af programmet: #include <stdio.h> int main(void) { int a, b, i, j, remainder; printf("Enter two non-negative integers: "); scanf("%d %d", &a, &b); i = a; j = b; /* We don't know if i > j */ while (j > 0){ remainder = i % j; i = j; j = remainder; } printf("GCD of %d and %d is %d\n\n", a, b, i); return 0; } Virker dette - hvorfor, eller hvorfor ikke? |
Opgave 4.7. Ligefrem programmering af 'største fælles divisor' | I denne lektion har vi set at der findes fine, smarte, og effektive algoritmer til at finde den største fælles divisor af to positive heltal. Se her. Målet med denne opgave er at træne dig i programmering med løkker, herunder at vælge gode iterative kontrolstrukturer til opgaven. Som altid er det også målet at lave et velopstillet program med god indrykning, og med brug af gode variabelnavne. I denne opgave skal du skrive et ligefrem program, der på en simpel og intuitiv måde finder den største fælles divisor af to ikke-negative heltal a og b. Programmet skal på en systematisk måde - med brug af en løkke - afprøve om forskellig, nøje udvalgte tal er divisorer i både a og b. Overvej omhyggeligt hvordan løkken starter, og hvordan den slutter. Programmet skal finde den største sådanne divisor: altså største fælles divisor. Overvej også om der er nogle specialtilfælde vi skal tage os af, inden vi starter løkken? Programmet skal indlæse de to heltal a og b af hvilke vi ønsker at finde den største fælles divisor. Men for ikke at starte programmet forfra hver gang vi ønsker at finde den største fælles divisor af to tal (a og b) bedes du lave programmet således at den gentager beregningen af den største fælles divisor af to indlæste tal indtil et af tallene er negativ. |
Kapitel 4: Flere Kontrolstrukturer
Kursets hjemmeside Forfatteren's hjemmeside Om frembringelsen af disse sider Forrige lektion (top) Næste lektion (top) Forrige lektion (bund) Næste lektion (bund)
Genereret: 9. maj 2022, 13:58:39