![]() ![]() ![]() | Funktioner |
Tændstikgrafik anvendes her for simple stregtegninger af sammensatte figurer, f.eks. mennesker med hoved, arme, krop og ben.
|
11.1. Eksempel: En tændstikpige (1)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I program 11.2 ser vi først en main funktion, som kalder en abstraktion, prn_match_girl. prn_match_girl udskriver konturerne af en pige i termer af hoved, arme, krop, ben ved at kalde prn_head, prn_arms, prn_body og prn_legs. Den ønskede tegning af pigen er vist herunder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | * * * * * * * * * * ------------- /\ / \ / \ / \ / \ / \ ------------- /\ / \ / \ / \ / \ / \ | |||
|
Vi ønsker at tegne en 'tændstikpige' ved brug af simpel tegngrafik |
1 2 3 4 5 6 7 8 9 10 11 | int main(void){ prn_match_girl(); return 0; } void prn_match_girl(void){ prn_head(); prn_arms(); prn_body(); prn_legs(); } | |||
|
Ovenstående er udtryk for en programmeringsidé som kaldes programudvikling af trinvis forfinelse. Vi anvender først prn_match_girl i main, uden at have denne til rådighed i forvejen. Når vi således har indset behovet for denne abstraktion, programmerer vi den som næste punkt på dagsordenen. Tilsvarende sker det med prn_head, prn_arms, prn_body og prn_legs.
Tegneprocessen udføres top-down. Det udtrykkes at en tændstikpige tegnes som et hoved, arme, krop og ben. I næste trin må vi definere, hvordan disse kropsdele tegnes. |
11.2. Eksempel: En tændstikpige (2)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi fortsætter den trinvise forfinelse af programmet som tegner tændstikpigen. Vi har brugt prn_head, prn_arms, prn_body og prn_legs i program 11.2, men vi har ikke lavet disse primitiver endnu. Det råder vi bod på i program 11.3.
Pigens hoved, arme, krop og ben tegnes ved kald af generelle geometriske tegne procedurer |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void prn_head(void){ prn_circle(); } void prn_arms(void){ prn_horizontal_line(); } void prn_body(void){ prn_reverse_v(); prn_horizontal_line(); } void prn_legs(void){ prn_reverse_v(); } | |||
|
Vi ser at et hoved tegnes som en cirkel, armene som en vandret streg, kroppen som et omvendt, lukket v, og benene som et omvendt v. Vi gør brug af tre nye primitiver, prn_circle, prn_horizontal_line og prn_reverse_v.
11.3. Eksempel: En tændstikpige (3)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Der er nu tilbage at realisere tegningen af cirkler, vandrette streger og den omvendte v form. Dette gør vi på helt simpel vis i program 11.4.
Man kan spørge om vi virkelig ønsker så mange niveauer for den relativt simple overordnede tegneopgave, som vi startede i kapitel 11. Svaret er et klart ja.
Vi får for det første nedbrudt den komplekse og sammensatte tegneopgave i en række simple tegneopgaver. Generelt er det måden at beherske indviklede og komplicerede programmeringsudfordringer.
Genbrugelighed er en anden markant fordel. I tegningen af tændstikpigen bruges den omvendte V form to forskellige steder. Det er en helt åbenbar fordel at disse to steder kan deles om tegningen af denne form. Dette gøres ved at kalde prn_reverse_v fra både prn_body og prn_legs. Selve implementationen af prn_reverse_v findes naturligvis kun ét sted.
Cirkler, linier og andre former tegnes ved brug af primitiv tegngrafik |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> void prn_circle(void){ printf(" * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * \n"); } void prn_horizontal_line(void){ printf("------------- \n"); } void prn_reverse_v(void){ printf(" /\\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf("/ \\ \n"); } | |||
|
I program 11.4 ser det lidt underligt ud at der tilsyneladende udskrives en dobbelt backslash '\'. Dette skyldes at backslash er et såkaldt escape tegn, som påvirker betydningen af de efterfølgende tegn. Derfor noterer '\\' reelt et enkelt bagvendt skråstreg i en C tekststreng. Tilsvarende noterer '\n' et linieskift.
11.4. Eksempel: En tændstikpige (4)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I dette afsnit viser figur 11.1 et overblik over strukturen af de abstrationer, vi har indført i afsnit 11.1 - afsnit 11.3. Men først repeteres de essentielle observationer om den benyttede fremgangsmåde:
Programmet er lavet top-down. Programmering ved trinvis forfinelse. Programmet designes og implementeres i et antal niveauer med postulering og efterfølgende realisering af et antal procedurer |
Figur 11.1 En illustration of problemer og delproblemer i forbindelse med tegning af en tændstikpige |
Læg igen mærke til den hierarkiske nedbrydning og hvordan nogle abstraktioner bruges mere end ét sted.
11.5. Eksempel: En tændstikpige (5)
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
I dette afsnit vil vi vise, hvordan vi konkret i C kan organisere de abstraktioner, som er præsenteret i de forrige afsnit. Som en central idé introducerer vi et separat char graphics library. I program 11.5 inkluderer vi dette bibliotek i den røde del. I den blå del skriver vi såkaldte funktionsprototyper for de funktioner, vi 'skubber foran os' i programmet. Dernæst følger abstraktionerne som printer hele pigen, hovedet, arme, krop og ben.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include "char-graphics.h" void prn_match_girl(void); void prn_head(void); void prn_arms(void); void prn_body(void); void prn_legs(void); int main(void){ prn_match_girl(); return 0; } void prn_match_girl(void){ prn_head(); prn_arms(); prn_body(); prn_legs(); } void prn_head(void){ prn_circle(); } void prn_arms(void){ prn_horizontal_line(); } void prn_body(void){ prn_reverse_v(); prn_horizontal_line(); } void prn_legs(void){ prn_reverse_v(); } | |||
|
I program 11.6 viser vi den såkaldte header fil for char graphics biblioteket. Det er denne fil vi inkluderede i den røde del af program 11.5.
1 2 3 4 5 6 7 8 9 10 11 | /* Very simple graphical character-based library */ /* Print a circle */ void prn_circle(void); /* Print a horizontal line */ void prn_horizontal_line(void); /* Print a reverse v shape */ void prn_reverse_v(void); | |||
|
Herunder, i program 11.7 ser vi selve implementationen af det grafiske bibliotek. For hver funktionsprototype i program 11.6 har vi en fuldt implementeret funktion i program 11.7.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> void prn_circle(void){ printf(" * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * * \n"); printf(" * \n"); } void prn_horizontal_line(void){ printf("------------- \n"); } void prn_reverse_v(void){ printf(" /\\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf(" / \\ \n"); printf("/ \\ \n"); } | |||
|
Endelig viser vi herunder hvordan vi først kan oversætte det grafiske bibliotek, og dernæst programmet som tegner tændstikpigen. Læg mærke til de forskellige compiler options, som giver udvidede fejlcheck.
1 2 3 4 5 6 7 | * Compilation of the char-graphics.c library: gcc -ansi -pedantic -Wall -O -c char-graphics.c * Compilation of the match-girl.c program: gcc -ansi -pedantic -Wall -O match-girl.c char-graphics.o | |||
|
Her følger nogle overordnede observationer af vores programorganisering:
Funktioner skal erklæres før brug. Genbrugelige funktioner organiseres i separat oversatte filer. Prototyper af sådanne funktioner skrives i såkaldte header filer. |
11.6. Del og hersk
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Efter at have overlevet det forholdsvis lange eksempel i de forrige afsnit er det nu tid til at gøre status.
Vi taler om del og hersk problemløsning. Ved at dele problemet op i mindre delproblemer hersker og behersker vi mange af de komplikationer, som vi støder på. Evnen til at dele problemer i mindre problemer er meget vigtig. Det er naturligvis tilfældet når vi prøver kræfter på store programmeringsopgaver. Men det gælder faktisk også ved løsning af de småopgaver, vi møder ved øvelserne i dette kursus. Jeg vil kraftigt opfordre alle til at tænke på dette næste gang I skriver et program!
Komplekse problemer kan ofte opdeles i et antal simplere delproblemer. Delproblemernes løsninger kan ofte sammensættes til en løsning på det oprindelige problem. |
Figur 11.2 Opdelning af et kompleks problem i delproblemer |
|
I næste kapitel vil vi se nærmere på funktionsbegrebet, herunder naturligvis funktioner i programmeringssproget C.