440 likes | 608 Views
Funktioner något in och något annat ut. Funktioner ger en klarare bild.
E N D
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); } 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.
Att konstruera en funktion /* 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); } return 0; } Klipp ut!Det är denna del av programmet som skapar tabellen - en avgränsad deluppgift.
Att konstruera en funktion /* 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); return 0; } OK!
Att konstruera en funktion Definiera den nya funktionen! klistra in !Denna kod klistras in sist i källkodsfilen, efter ”stommen” stomme 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); }
Att konstruera en funktion Definiera den nya funktionen!En funktion har samma uppbyggnad som main(), som ju också är en funktion. 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
Att konstruera en funktion /* 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; } lägg till funktions-deklaration och funktions-anrop här skall funktions-definitionen in
Att konstruera en funktion /* 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; } ändradetta, man kan nu ange antal år vid exekveringen. här skall funktions-definitionen in
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 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; } en översikts-bild av hela programmet
Att konstruera en funktion /* 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; } stommen, som ju också är en funktion. en översiktsbild av hela program- met funktionen
Att konstruera en funktion 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
Att konstruera en funktion /* 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!
Ett C-program byggs uppav /* 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; } • satser i sekvens • styrande satser • iteration • selektion • funktioner • flera filer (så småningom)
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 ); 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 Datorns primärminne 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 Datorns primärminne 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 Datorns primärminne • 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 Datorns primärminne • 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
Rekursionn-fakultet, ett klassiskt exempel AaBbCcDdEeFfGgHhIiJjKkLlMmNn 0! = 1 1! = 1 2! = 1 · 2 = 2 3! = 1 · 2 · 3 = 6 .......... n! = 1 · 2 · ... (n-1) · n
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)); } anropar sig själv med n-1 slut NFAK1.EXE
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) NFAK1.EXE
Rekursiontillämpning #include <stdio.h> void SkrivBaklanges( int ); int main( void ){ printf("Skriv tecken ( avsluta med Enter )--> "); SkrivBaklanges( getchar() ); 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 SKRIVBAK.EXE
Slut Övningsuppgift, se anteckningar