440 likes | 585 Vues
This code example demonstrates a simple C program that utilizes two functions within one file. The program starts by summoning a function named `butler` which greets the user. Then, it prompts for an initial capital amount and calculates the capital growth over a specified number of years at a defined interest rate. It neatly prints the annual balance based on the input, showing positive and negative growth scenarios. This clear division of tasks into functions enhances code readability and maintainability.
E N D
Enkelt program med funktion /* two_func.c - a program that uses two functions in one file *//* from Stephen PrataC Primer Plus ISBN 1-57169-161-8 */#include <stdio.h> #include <stdlib.h> void butler(void); /* ANSI C function prototype */ int main( void) { printf("I will summon the butler function.\n"); butler(); printf("Yes. Bring me some tea.\n"); system("PAUSE"); return 0; } void butler(void) /* start of function definition */{ printf("You rang, sir?\n");}
Funktionernågot in och något annat ut Parametrar Funktion Returvärde
Funktionerger en klarare bild • tyvärr så klarar inte människan att ”hålla hur många bollar (hattar) i luften som helst” förmågan att se samband och konsekvenser mellan samtidiga skeénden är begränsad. Fundera t ex på hur många tal du kan memorera om någon räknar upp dem för dig. • kanske klarar du 7 st men ofta hamnar man på 3-4 st. • med funktioner kan man dela upp sinkällkod i del- (under-) program för att få överblick, se samband och konsekvens • varje delprogram ( funktion ) löseren avgränsad deluppgift
Funktioner nu kör vi ränteberäknings-programmet igen. De här bilderna har du sett förut! Exempel
Ett program växer fram ...förbättringar - program med funktions-moduler /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 #define ANTAL_AR 10 int main ( void ) { float kapital ; int ar ; printf("Insatt kapital? "); scanf("%f", &kapital); printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= ANTAL_AR ; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } system("PAUSE"); return 0; } många satser efter varandra gör programmet oöverskådligt - dela upp koden i funktioner
Att konstruera en funktion Funktionskonstruktion.Dela upp programmet m h a del- (under-) program.
Klipp ut! /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 #define ANTAL_AR 10 int main ( void ) { float kapital ; int ar ; printf("Insatt kapital? "); scanf("%f", &kapital); printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= ANTAL_AR ; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } system("PAUSE"); return 0; } Klipp ut!
Kvar i main … /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 #define ANTAL_AR 10 int main ( void ) { float kapital ; int ar ; printf("Insatt kapital? "); scanf("%f", &kapital); system("PAUSE"); return 0; } OK!
Klistra in! Definiera den nya funktionen! klistra in printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= ANTAL_AR ; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); }
Definiera den nya funktionen. Definiera den nya funktionen! lägg till! void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } ändra!
Funktionens delar Definiera den nya funktionen! funktionens returtyp - utdatatyp void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } funktionsprototyp,funktionshuvud funktionens formella parametrar (argument) - indata funktionens namn
Funktionens delar funktionens egen variabel, okänd utanför funktions-kroppen Definiera den nya funktionen! void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } indatavariablerna, som bara är kända i funk-tionen används i funktionen
Funktionsdeklaration och funktionsanrop /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 #define ANTAL_AR 10 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int ar ; printf("Insatt kapital? "); scanf("%f", &kapital); TabellPaSkarmen( ANTAL_AR, kapital ); return 0; } i stommen, main()- funktionen lägg till funktions-deklaration och funktions-anrop här skall funktions-definitionen in
Parameter i stället för konstant /* Beräknar kapitaltillväxt på x år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 #define ANTAL_AR 10 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int ar , antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } Ändra detta, man kan nu ange antal år vid exekveringen. här skall funktions-definitionen in
Översikt – hela programmet /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } system(”PAUSE”); return; } en översiktsbild av hela programmet stommen funktionen
Översikt, funktionsdeklaration och funktionsdefinition en översiktsbild av hela program- met /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } funktionsdeklaration, för att kompilatorn skall kunna kontrollera att man använder funktionen rätt funktionsdefinition
En hatt i taget … /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } Å va bra!Nu tar jag en hatt åt gången!
Funktionsanrop • Hur anropas en funktion? • Vad händer då en funktion anropas och exekveras?
Funktionsanropexempel /* Beräknar kapitaltillväxt på x år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); system("PAUSE"); return 0; }
Vad händer då man definierar ett minne ? /* Beräknar kapitaltillväxt på 10 år framåt eller bakåt */ #include <stdio.h> #define RANTESATS 8.5 void TabellPaSkarmen( int , float ); int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ?(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; }
tid Main’s aktiveringspost på ”stacken” Bytes Maskinkod programmet • main() exekveras int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ? "); printf("(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } Heap main’s ”egna” variabler skapas på stacken - aktiveringspost kapital=100 Stack main() antalAr=1
Hur måste TabellPaSkarmen()se ut ? void TabellPaSkarmen( int antalAr , float kapital ) { int ar ; printf("\n År Saldo\n == =====\n"); for ( ar = 1; ar <= antalAr; ar++ ) { if ( kapital > 0 ) kapital = kapital * ( 1 + RANTESATS/100 ); else kapital = kapital * 1/( 1 + RANTESATS/100 ); printf("%3d%11.2f\n", ar,kapital>0 ? kapital:-kapital); } return; } dessa variabelnamn kan vara lika men behöver inte vara det. int main ( void ) { float kapital ; int antalAr; printf("Insatt kapital och antal år ? "); printf("(-->1000 10)--> "); scanf("%f%d", &kapital, &antalAr); TabellPaSkarmen( antalAr, kapital ); return 0; } funktionen anropas, (aktuella parametrar)
tid Aktuella och formella parametrar Bytes Maskinkod programmet void TabellPaSkarmen(int antalAr , float kapital) { int ar ; • TabellPaSkarmen() exekveras Heap TabellPaSkarmen() antalAr=1 kapital=100 ar=?? de aktuella para-metrarna anpassas och kopieras till funktionens formella parametrar kapital=100 kapital=100 Stack main() antalAr=1 antalAr=1
Bytes Maskinkod programmet Heap Stack tid Funktionens aktiveringspost • TabellPaSkarmen() exekveras for ( ar = 1; ar <= antalAr; ar++ ) kapital = kapital * ( 1 + RANTESATS/100 ); satserna i funktionen utförs TabellPaSkarmmen() antalAr=1 antalAr=1 antalAr=1 kapital=100 kapital=108.5 kapital=108.5 ar=?? ar=1 ar=2 kapital=100 kapital=100 kapital=100 main() main() kapital=100 antalAr=1 antalAr=1 antalAr=1 antalAr=1
Bytes Maskinkod programmet Heap Stack tid Aktiveringsposterna tas bort • TabellPaSkarmen() dör • main() dör - exekvering slut TabellPaSkarmen() antalAr=1 kapital=108.5 ar=2 kapital=100 kapital=100 main() main() antalAr=1 antalAr=1
Värdeöverföring • Talen 1 och 100 har värdeöverförts, kopierats in i funktionen TabellPaSkarmen() • Att nu förändra kopian ändrar inte på originalet antalAr=1 TabellPaSkarmen() kapital=100 ar=?? main() kapital=100 antalAr=1
Fakultetsfunktionen – ett klassiskt exempel Värdeöverföringen, ”kopiorna”, möjliggör rekursion … 5! = 5 4 3 2 1 5! = 5 4! 4! = 4 3! 3! = 3 2! 2! = 2 1! 0! = 1 int nfak( int n ) {if (n<=0)return (1); elsereturn ( n * nfak( n-1));} anropar sig själv med n-1 slut
Rekursionn-fakultet, ett klassiskt exempel #include <stdio.h> int nfak( int ) ; int main( void ){ int fak , svar ; printf( "Ge fakultet --> " ); scanf("%d", &fak); svar = nfak(fak); printf("\nSvar: %d! = %d ", fak , svar ); system("PAUSE") return 0; } int nfak( int n ) { if (n<=0) return (1); else return ( n * nfak( n-1)); }
Vad är det som händer? Bytes primärminnet Heap Stack fak=3, svar=? fak3 main() tid
Vad är det som händer? Bytes 3 Heap 3 nfak(3) Stack n=3 fak=3, svar=? fak=3, svar=? main() main() tid
Vad är det som händer? Bytes Heap 2 Heap 2 nfak(2) n=2 nfak(3) nfak(3) Stack n=3 n=3 fak=3, svar=? fak=3, svar=? fak=3, svar=? main() main() main() tid
Vad är det som händer? Bytes Heap 1 Heap 1 nfak(1) n=1 nfak(2) nfak(2) n=2 n=2 nfak(3) nfak(3) nfak(3) Stack n=3 n=3 n=3 fak=3, svar=? fak=3, svar=? fak=3, svar=? fak=3, svar=? main() main() main() main() tid
Vad är det som händer? Bytes nfak(1) n=1 nfak(2) n=2 nfak(3) n=3 fak=3, svar=? main() tid
Vad är det som händer? Bytes 0 Heap nfak(0) n=0 nfak(1) nfak(1) n=1 n=1 nfak(2) nfak(2) n=2 n=2 nfak(3) nfak(3) n=3 n=3 fak=3, svar=? fak=3, svar=? main() main() tid
Vad är det som händer? Bytes nfak(0) n=0 1 nfak(1) nfak(1) n=1 n=1 nfak(2) nfak(2) n=2 n=2 nfak(3) nfak(3) n=3 n=3 fak=3, svar=? fak=3, svar=? main() main() tid
Vad är det som händer? Bytes 1 1 nfak(0) n=0 1 nfak(1) nfak(1) n=1 n=1 n=1 1 nfak(2) nfak(2) nfak(2) n=2 n=2 n=2 nfak(3) nfak(3) nfak(3) n=3 n=3 n=3 fak=3, svar=? fak=3, svar=? fak=3, svar=? main() main() main() tid
Vad är det som händer? Bytes 2 1 nfak(0) n=0 1 nfak(1) n=1 n=1 1 nfak(2) nfak(2) nfak(2) n=2 n=2 n=2 2 nfak(3) nfak(3) nfak(3) n=3 n=3 n=3 fak=3, svar=? fak=3, svar=? fak=3, svar=? main() main() main() tid
Vad är det som händer? Bytes 3 2 n=1 1 nfak(2) nfak(2) n=2 n=2 2 nfak(3) nfak(3) nfak(3) n=3 n=3 n=3 6 fak=3, svar=? fak=3, svar=? fak=3, svar=? main() main() main() tid
Vad är det som händer? Bytes 3 6 3 2 nfak(2) n=2 2 nfak(3) nfak(3) n=3 n=3 6 fak=3, svar=? fak=3, svar=? fak=3, svar=6 main() main() main() program-slut tid
Rekursionn-fakultet, ett klassiskt exempel #include <stdio.h> int nfak( int ) ; int main( void ) { int fak , svar ; printf( "Ge fakultet --> " ); scanf("%d", &fak); svar = nfak(fak); printf("\nSvar: %d! = %d ", fak , svar ); return 0; } int nfak( int n ) { if (n<=0) return (1); else return ( n * nfak( n-1)); } variabeln svar behövs inte nfak(fak)
Rekursiontillämpning #include <stdio.h> void SkrivBaklanges( int ); int main( void ){ printf("Skriv tecken ( avsluta med Enter )--> "); SkrivBaklanges( getchar() ); system("PAUSE"); return 0; } void SkrivBaklanges( int tecken){ if (tecken != '\n') { SkrivBaklanges( getchar() ); putchar( tecken ); } return ; } • man kan använda rekursion för att vända på dataföljder
Provkör på övningen … /* backwards.c Reprints what you type but backwards *//* recursive function */#include <stdio.h>#include <stdlib.h>void SkrivBaklanges( int);int main(void){ printf( "Skriv tecken ( avsluta med Enter ) --> "); SkrivBaklanges( getchar() ); printf("\n"); system("PAUSE");return 0;} void SkrivBaklanges( int tecken){if (tecken != '\n') SkrivBaklanges( getchar()); putchar( tecken );}