Kurt Nørmark
Institut for Datalogi, Aalborg Universitet
| Sammendrag Forrige lektion Næste lektion Stikord Referencer Indhold | I denne lektion gennemgår vi funktions- og procedure begrebet, herunder lokale variable og parametre. Vi ser naturligvis også på detaljer omkring funktioner i C. |
| Procedurer og funktioner |
| Programmer og Algoritmer Slide Indhold Stikord Referencer |
| Begrebet algoritme: En algoritme er endelig liste af instruktioner til løsning af problem, som karakteriseres af nul, en eller flere input og ét output. Hver instruktion skal være klar, utvetydig, og praktisk gennemførbar for en person som ønsker at følge algoritmen. |
|
| Procedurer og Funktioner Slide Indhold Stikord Referencer |
|
| Begrebet abstraktion: En abstraktion indkapsler, navngiver og parametriserer en samling af programdetaljer | ||
| Begrebet procedure: En procedure er en abstraktion over en sekvens af kommandoer | ||
| Begrebet funktion: En funktion er en abstraktion over et udtryk |
|
|
| Funktionsdefinitioner uden parametre i C Slide Indhold Stikord Referencer |
|
| Syntax: En funktionsdefinition i C |
|
|
|
| Eksempel: Rødder i en andengradsligning Slide Indhold Stikord Referencer |
|
|
| Program: En funktion der finder rødder i en andengradsligning. |
|
|
|
|
| Kald af funktioner uden parametre - lokale variable Slide Indhold Stikord Referencer |
| Syntax: Et funktionskald i C |
|
|
| Program: Illustration af ulovlig anvendelse af en lokal variabel. |
|
| Program: Illustration af uinitialiseret lokal variabel. |
|
| Program: Illustration af funktionsdefinition efter funktionskald. |
|
| Program: Løsning af 'definition efter kald' med brug af en prototype. |
|
| Top-down programmering ved trinvis forfinelse |
| Lasagne al forno Slide Indhold Stikord Referencer |
|
|
| Struktureret lasagne Slide Indhold Stikord Referencer |
|
| Program: Ustruktureret lasagne. |
|
| Program: Struktureret Lasagne. |
|
| Program: Lav en portion lasagneplader. |
|
| Program: Lav en portion hvid sovs. |
|
| Program: Lav en portion kødsovs. |
|
|
| Lasagne ala C Slide Indhold Stikord Referencer |
|
| Program: Et pseudo C program som laver lasagne. |
|
| Program: Et pseudo C program som laver lasagne - funktioner med parametre. |
|
| En tændstikpige (1) Slide Indhold Stikord Referencer |
|
| Program: Det ønskede output - tændstikpigen. |
|
| Program: Udskrivning af tændstikpige i termer af udskrivning af hoved, arme, krop og ben. |
|
|
| En tændstikpige (2) Slide Indhold Stikord Referencer |
|
| Program: Udskrivning af hoved, arme, krop og ben i termer af generelle geometriske figurer. |
|
|
| En tændstikpige (3) Slide Indhold Stikord Referencer |
|
| Program: Udskrivning af cirkler, linier og andre geometriske figurer. |
|
| En tændstikpige (4) Slide Indhold Stikord Referencer |
|
| Figur. En illustration of problemer og delproblemer i forbindelse med tegning af en tændstikpige | ![]() |
| En tændstikpige (5) Slide Indhold Stikord Referencer |
|
| Program: Tændstikpige programmet. |
|
| Program: Filen char-graphics.h - header fil med prototyper af de grafiske funktioner. |
|
| Program: Filen char-graphics.c - implementationen af de grafiske funktioner. |
|
| Program: Oversættelse af programmerne. |
|
| Program: Oversættelse af programmerne - med mange warnings. |
|
| Program: Makefile - som automatiserer oversættelsen. |
|
| Program: Makefile med makroer. |
|
|
|
| Del og hersk - del og kombiner Slide Indhold Stikord Referencer |
|
| Figur. Opdelning af et kompleks problem i delproblemer | ![]() |
|
| C funktioner med input parametre |
| Formelle og aktuelle parametre Slide Indhold Stikord Referencer |
|
| Syntax: En funktionsdefinition i C |
|
|
| Syntax: Et funktionskald i C |
|
| Program: Illustration af formelle og aktuelle parametre. |
|
|
|
| Eksempel: Rødder i en andengradsligning Slide Indhold Stikord Referencer |
|
|
| Program: En funktion der finder rødder i en andengradsligning - nu med input parametre. |
|
|
|
|
| Opgave 4.2. Trinvis forfinelse af solveQuadraticEquation | På mange måder er funktionen solveQuadraticEquation fra programmet på den tilhørende slide en god løsning på at finde rødderne i den generelle andengradsligning a x2 + b x + c = 0. Dog udestår, som omtalt på tilhørende slide en tilfredsstillende løsning på aflevering af outputtet: Antallet af rødder og rødderne selv. Men det kommer lidt senere i kurset. I denne opgave vil vi nedbryde problemløsningen endnu mere, og vi vil på systematisk vis programmere C funktioner som løser disse delproblemer. Opgaven går altså ud på at anvende ideerne om trinvis forfinelse og top-down programmering. Programmer hvert af følgende delproblemer som en separat funktion:
Hvis der kun er én rod, anses første og anden rod for at være ens. Hvis der ikke findes rødder må de to sidstenævnte funktioner ikke kaldes. Find gode navne til funktionerne, der løser ovenstående tre delproblemer, og forsyn funktionerne med relevante input parametre. Funktionernes output skal formidles via funktionernes returværdi. Omskriv programmet så det kalder de tre funktioner. Programmer endvidere main således at solveQuadraticEquation kaldes i en løkke. Afslut løkken når alle de tre koeficienter a, b og c er lig med 0 I denne opgave bedes du programmere det hele i én C fil. Der skal således ikke laves en header fil med prototyper. |
| Eksempel: Temperaturomregninger Slide Indhold Stikord Referencer |
|
| Program: Et program som omregner frysepunkt og kogepunkt til Fahrenheit grader. |
|
| Program: Et program som omregner frysepunkt og kogepunkt til Fahrenheit grader - uden abstraktion. |
|
| Figur. To kald af fahrenheit_temperature funktionen | ![]() |
| Program: Et program som udskriver en celcius fahrenheit tabel. |
|
| Program: Output fra ovenstående program. |
|
| Eksempel: Antal dage i en måned Slide Indhold Stikord Referencer |
|
| Program: Et program der beregner antal dage i en måned med en funktion. |
|
|
| Program: Et program der beregner antal dage i en måned med en funktion - uden IsLeapYear funktionen. |
|
|
| Eksempel: GCD Slide Indhold Stikord Referencer |
|
| Program: Et program der beregner største fælles divisor med en funktion. |
|
|
| Opgave 4.5. Find de første n primtal | Denne opgave giver dig blandt andet træning i programmering af et C program, der anvender en header file (.h fil) og en tilhørende .c fil. Du skal skrive et program med en main funktion der udskriver de første n primtal. Skriv dit program i en fil der hedder test-primes.c. Der ønskes følgende output hvis n er 100: prime 1: 2 prime 2: 3 prime 3: 5 prime 4: 7 prime 5: 11 prime 6: 13 prime 7: 17 prime 8: 19 prime 9: 23 prime 10: 29 ... prime 99: 523 prime 100: 541 Du kan bruge følgende funktion, der placeres i filen primes.h, og som fortæller om et tal n er et primtal: /* Return if n is a prime number */ int is_prime(int n); I din main funktion skal du - ganske enkelt - gennemløbe så mange positive heltal, som det er nødvendigt, for at finde de første n primtal. For at få alt dette til at virke skal du placere følgende programlinier i filen primes.c, og oversætte denne c fil separat. #include "primes.h"
#include <math.h>
#include <assert.h>
/* Return if i is a prime number. It is assumed as a precondition that
the parameter i is non-negative */
int is_prime(int i)
{
assert(i >= 0);
if (i == 1)
return 0;
else if (i == 2)
return 1;
else if (i % 2 == 0)
return 0;
else{
int k, limit;
limit = (int)(ceil(sqrt(i)));
for (k = 3; k <= limit; k += 2)
if (i % k == 0)
return 0;
return 1;
}
}
Compilering af programmet: Følg mønstret fra vores gennemgang af oversættelse af tændstikpige programmet. Inspirationen til denne opgave er fra bogen C by Dissection - anvendt med tilladelse fra forlaget. |
| Opgave 4.5. Goldbachs Formodning | Goldbachs formodning udtrykker en påstand om at alle lige heltal større end to er summen af to primtal. Denne formodning er hverken bevist eller modbevist. I denne opgave vil vi beskæftige os med følgende variation af påstanden:
Skriv et program der beviser denne formodning for alle lige heltal mellem to givne grænser. Eksempelvis for alle lige heltal mellem 7 og 2.000.000. Hvis du er i stand til at finde et modeksempel, er berømmelsen måske lige om hjørnet... Det foreslås at funktionen is_prime fra en tidligere opgave bruges ved løsningen af denne opgave. Det er for stor en mundfuld at løse dette problem uden opdeling i mindre delproblemer. Det foreslås derfor at I skriver en funktion, som undersøger påstanden for et bestemt lige heltal, n. Denne funktion kan så kaldes for alle lige heltal n mellem f.eks. 7 og 2.000.000. Hint: Når I skal bevise påstanden for et tal, n, anbefales det at gennemløbe alle mulige summer (n-i) + i, og dermed undersøge om I kan finde et i så både n-i og i er ulige primtal. Hvis I bliver hurtigt færdige med denne opgave bedes I se på den variant, der på Wikipedia beskrives som Goldbach's weak conjecture. Som en anden udfordring, kan det være interessant at se alle mulige summer- ikke kun den første. Eller denne variant: Hvilket af de testede tal har det største antal opløsninger? Denne opgave stammer fra bogen C by Dissection - anvendt med tilladelse fra forlaget. |
| Opgave 4.5. RGB Pixels | I en tidligere opgave har vi arbejdet med PPM grafik, hvor vi med tre kald af fputc skrev én pixel bestående af tre bytes (rød, grøn, blå) på en fil. Denne opgave forbereder vores fremtidige programmering af PPM grafik med en eksplict og relativ kompakt repræsentation af farverne i én pixel. I denne opgave vil vi repræsentere en pixel i en unsigned int, som antages at fylde 4 bytes, på følgende måde:
Skriv en funktion unsigned int make_pixel(int red, int green, int blue); som indsætter tre heltal (som hver forudsættes at være mellem 0 og 255) i en unsigned int, og returnerer den resulterende pixels (som en unsigned int). Skriv endvidere tre funktioner, som udtrækker hhv. den røde grønne og blå komponent af en pixel: int get_red(unsigned int p); int get_green(unsigned int p); int get_blue(unsigned int p); Det skal naturligvis være således at
Check at dette er tilfældet gennem en række eksempler. Organiser de fire funktioner ovenfor i filen pixels.c, og lav en tilsvarende header fil pixels.h. Vær sikker på at du kan oversætte (compilere) filen pixels.c separat. Det er attraktivt - men ikke strengt nødvendigt - at anvende de bitvise operatorer (eksempelvis <<, >> og &). Disse er beskrevet i appendix C, side C-3 i lærebogen. |
| Regler for overførsel af værdiparametre i C Slide Indhold Stikord Referencer |
|
|
| Begrebet formel parameter: En parameter, som optræder i en funktionsdefinition, kaldes en formel parameter. En formel parameter er et navn. | ||
| Begrebet aktuel parameter: En parameter, som optræder i et kald af en funktion, kaldes en aktuel parameter. En aktuel parameter er et udtryk, som beregnes inden det overføres. |
|
| Eksempel: Rodsøgning (1) Slide Indhold Stikord Referencer |
|
| Figur. En kontinuert funktion f med en rod mellem l og u | ![]() |
|
| Eksempel: Rodsøgning (2) Slide Indhold Stikord Referencer |
| Program: Rodsøgningsfunktionen. |
|
| Program: Funktionerne sameSign, middleOf og isSmallNumber. |
|
| Program: Hele rodsøgningsprogrammet. |
|
| Forskellige problemer med input parametre og returværdi Slide Indhold Stikord Referencer |
|
| Program: Det gode program. |
|
| Program: En double funktion som glemmer at bruge return. |
|
| Program: En void funktion som printer. |
|
| Program: En funktion hypotenuse kan ikke se en anden funktions lokale variable. |
|
| Program: Brug af globale variable til input i stedet for parametre. |
|
| Program: Brug af globale variable til input og output. |
|
| C funktioner med output parametre |
| Output fra funktioner Slide Indhold Stikord Referencer |
|
|
|
| Introduktion til Pointere (1) Slide Indhold Stikord Referencer |
|
| Figur. En variabel v og en pointer til v | ![]() |
| Introduktion til Pointere (2) Slide Indhold Stikord Referencer |
|
| Figur. En variabel v og en pointer til v | ![]() |
| Program: Det tilsvarende C program. |
|
| Program: Program output. |
|
| To operatorer knyttet til pointere Slide Indhold Stikord Referencer |
|
|
|
|
| Output parametre - ift. input parametre Slide Indhold Stikord Referencer |
|
| Figur. Værdi parametre (til input) og reference parametre (til output) | ![]() |
| Program: Funktionen f modtager værdierne af to variable som input - figur til venstre. |
|
| Program: Program output. |
|
| Program: Funktionen f modtager værdierne af to udtryk som input. |
|
| Program: Program output. |
|
| Program: Funktionen f ændrer på værdierne af de to formelle parametre. |
|
| Program: Program output. |
|
| Program: En funktion g der modtager to pointere til variable som input - med henblik på tilbageføring af output - figur til højre. |
|
| Program: Program output. |
|
| Program: En funktion g der modtager to pointere til udtryk som input - Giver ikke mening. |
|
| Program: Tilbageføring af output fra g med scanf. |
|
| Program: Program input og output. |
|
| Eksempel: Rødder i en andengradsligning Slide Indhold Stikord Referencer |
|
|
| Program: En funktion der finder rødder i en andengradsligning - både input og output parametre. |
|
|
|
| Opgave 4.8. Celcius til fahrenheit med output parameter | Vi har tidligere programmeret en simpel funktion, der omregner fra en celcius temperatur til fahrenheit temperatur. Det er helt naturligt at celcius temperaturen er en call by value input parameter. Ligeledes er det naturligt at fahrenheit temperaturen returneres med return fra funktionen. Omskriv nu funktionen således at fahrenheit temperaturen returneres gennem en output parameter - en pointer. Omskriv også main, således at kaldet ændres til denne nye parameterprofil. Hvilken version foretrækker du? |
| Opgave 4.8. Timer, minutter og sekunder - igen, igen | Vi har på et tidligt tidspunkt i kurset skrevet et program, som omregner et antal sekunder til timer, minutter og sekunder efter de sædvanlige principper. Skriv nu en funktion, hours_minutes_seconds, som tager antal af sekunder som en input parameter, og som returnerer de tre outputs (timer, minutter og sekunder) som output parametre (pointere, call-by-reference). |
| Opgave 4.8. Seddeludlevering i pengeautomat | Dette program handler om seddeludlevering fra en amerikansk pengeautomat, hvor der kun anvendes 100, 50, 20 og 10 dollar sedler. Programmet skal som input acceptere et dollar beløb, der er dividerbart med 10. Programmet skal beregne antallet af udleverede 100, 50, 20 og 10 dollar sedler svarende til beløbet. Der skal udleveres så få sedler som muligt. Problemet skal løses med en funktion der tager både input og output parametre. Beløbet, der skal veksles, skal være en input parameter. Antallet af udleverede 100, 50, 20 og 10 dollar sedler skal være output parametre. |
| Rekursive funktioner |
| Introduktion til rekursive funktioner Slide Indhold Stikord Referencer |
|
|
| Program: Et program med en rekursivt defineret fakultetsfunktion. |
|
| Program: Et tilsvarende program med en iterativ fakultetsfunktion. |
|
| Program: Output fra ovenstående programmer. |
|
|
| Program: En rekursiv version af funktionen findRootBetween. |
|
| Program: Hele rodsøgningsprogrammet. |
|
|
| Pointere til funktioner |
| Pointere til funktioner Slide Indhold Stikord Referencer |
|
|
| Program: Rodsøgning i en funktionen, som overføres som parameter til findRootBetween. |
|
| Program: En version uden dereferencing og address operator på funktionerne. |
|
|
|
| Coding Style |
| Indrykning Slide Indhold Stikord Referencer |
|
| Program: K & R Style. |
|
| Program: K & R Style, med curly braces om enkelt sætninger. |
|
| Program: Mindre variant af K & R style. Alternativ opsætning af else. |
|
| Program: Meget kompakt formatering - ofte anvendt i disse noter. |
|
| Program: Allman style. |
|
| Program: Whitesmiths style. |
|
| Program: Inkonsistent indrykning - blandet anvendelse af indrykningsreglerne. |
|
| Program: Inkonsistent indrykning - ujævn mængde af indrykning. |
|
| Program: Udrykning - ikke indrykning. |
|
| Program: Så bliver det ikke meget værre... |
|
| Variabelnavne Slide Indhold Stikord Referencer |
|
| Program: Lower camel case. |
|
| Program: Upper camel case. |
|
| Program: Underscore. |
|
|
| Program: Brug af meget korte navne. |
|
| Program: Hungarian notation - forkortede typenavne anvendt som prefix på alle variable. |
|
| Program: All caps - som et eksempel på at små/store bogstaver kan bruges til at signalere rollen af navne. |
|
| Ekstra Opgaver |
| Ekstra Opgaver Slide Indhold Stikord Referencer |
| Opgave 4.10. Skudårsfunktionen | Vi har tidligere i denne lektion mødt skudårsfunktionen int isLeapYear(int year){
int res;
if (year % 400 == 0)
res = 1;
else if (year % 100 == 0)
res = 0;
else if (year % 4 == 0)
res = 1;
else res = 0;
return res;
}
Programmer en ny skudårsfunktion med brug af && og ||, og uden brug af if-else og uden brug af betingede udtryk. Kald begge skudårsfunktioner for alle årstal mellem år 1900 og år 2100. Giver de to funktioner samme resultat på alle årstal? |
| Opgave 4.10. En simpel lommeregner | Skriv et program der modellerer en simpel lommeregner. Hver input-line skal bestå af den næste operation, som skal udføres, efterfulgt af den højre operand. Antag at den venstre operand er akkumulatoren (den beregnede værdi, i starten 0). Du skal have en funktion, scan_data, med to output parametre som returnerer en operator og den højre operand fra en data linje. Du skal også have en funktion, do_next_op, som udfører den påkrævede operation. do_next_op skal have to input parametre (operator og operand) og en input/output parameter (akkumulatoren). Her er de gyldige operationer: + addition - subtraktion * multiplikation / division ^ potensopløftning q quit Din lommeregner skal vise den akkumulerede værdi efter hver operation. Her er et eksempel: + 5.0 result so far is 5.0 ^ 2 result so far is 25.0 / 2.0 result so far is 12.5 q 0 final result is 12.0 (Denne opgave svarer til opgave 10 side 360 i 6. udgave af lærebogen, og den minder om opgave 10 side 391 i 7. udgave). |
| PPM Grafik |
| PPM grafik funktioner Slide Indhold Stikord Referencer |
|
|
| Program: Header filen pixel.h. |
|
| Program: Den tilsvarende fil pixel.c - en mulig implementation. |
|
| Program: Header filen ppm.h. |
|
| Program: Den tilsvarende fil ppm.c - en mulig implementation. |
|
|
| Program: Et simpelt program der genererer og udskriver et PPM billede. |
|
| Program: Makefilen som styrer oversættelsen af programmerne. |
|
|
| Opgave 4.11. Flere PPM funktioner | I denne opgave vil vi - trin for trin - tilføje nye nyttige funktioner, som arbejder på PPM billeder. De første er forholdsvis simple. De senere er lidt mere udfordrende. I en tidligere opgave genererede vi PPM billeder i en dobbelt for-løkke. I denne opgave er billedet tilgængelig i en passende datastruktur, som vi dog ikke har behov for at gå i dybden med på nuværende tidspunkt. Arbejdet vil basere sig på nogle allerede programmerede funktioner, som kan aflæse og sætte én pixel i et PPM billede. Du kan også tænke på en pixel som en farve. Der findes en zip-fil, som indeholder alt det nødvendige for at komme igang. Du kan også tilgå de enkelte filer. README filen giver anvisninger på hvordan du kan compilere programmerne. Nogle af jer har allerede lavet lidt forarbejde, nemlig funktioner som arbejder med RGB pixels. Det anbefales først at læse ppm.h og det simple eksempel på anvendelse af nogle af funktionerne fra ppm.h. Denne anvendelse genererer dette billede. Programmer nu følgende:
Arbejdet kan fortsættes med endnu flere primitiver, i forskellige retninger. Tegning af stiplede linier er en mulighed. Eller indnu mere ambitiøst, indsættelse af tegn (fra en bestemt font) i et ppm billede. |
Kapitel 4: Funktioner
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: 6. november 2012, 16:28:07