• No results found

Modul 3 - Modularisering

N/A
N/A
Protected

Academic year: 2022

Share "Modul 3 - Modularisering"

Copied!
16
0
0

Loading.... (view fulltext now)

Full text

(1)

Modul 3 – Modularisering

MODULARISERING 2

FUNKTIONER 3

Funktionsdefinition 4

Funktionsanrop 5

Funktionskroppen 5

Slumpa – funktionen rand() 6

Värdeanrop 6

Variablers räckvidd 8

Referensanrop 8

DELPROGRAM 10

Header-filer 10

KONTRAKTSPROGRAMMERING 11

(2)

Modularisering

Det finns flera anledningar att dela upp sitt program i mindre delar. Det blir enklare att:

• Konstruera

Det är lättare att dela upp ett problem i mindre delar och lösa dem var för sig och sedan sätta samman lösningarna. Om man försöker lösa hela problemet på en gång är det lätt att man tappar överblicken om det man jobbar med är för stort och

komplicerat.

• Koda

Det är enklare att koda en liten del åt gången av samma anledning som det är lättare att lösa ett mindre problem än ett stort problem. Blir något fel är det enklare att rätta till det när man bara skriver små delar med kod åt gången.

• Testa

När man kodar mindre delar åt gången är det också lättare att definiera testfall och lättare att utföra testerna. Varje modul i ett program kan testas för sig enligt de regler, de kontrakt, man satt upp ska gälla för den delen. Fungerar alla delar för sig är det större chans att hela programmet fungerar när man sätter ihop det. Det är mycket enklare att hitta felen om man kan testa och undersöka mindre separata delar än om man ska testa hela programmet.

• Underhålla

Ett program har en väldigt begränsad livslängd. Om ett program går att underhålla och utöka på ett enkelt sätt så kan denna livslängd förlängas en hel del. Det är mycket lättare att underhålla ett program som består av separerade och väl definierade

moduler där varje enskild modul har en specifik uppgift, än ett program som är en enda stor klump.

• Återanvända

Om man har flera små moduler som utför väl avgränsade och väl definierade uppgifter är det också större sannolikhet att man kan återanvända koden. Man ska alltid sträva efter att återanvända så mycket som möjligt, det finns ingen anledning att

”uppfinna hjulet”. (Observera att i den här kursen är syftet inte att ni ska producera mjukvara utan syftet är att ni ska lära er hur, därför kommer ni skriva kod som

garanterat finns skriven redan av människor över hela jorden. Eftersom syftet är att ni ska lära er att programmera ska ni alltså inte kopiera andras kod.)

Man kan modularisera sitt projekt på flera nivåer:

• Namnutrymme (Namespace)

• Fil

• Klass

• Funktion

I den här kursen kommer vi att titta på filer och funktioner och i viss mån på namnutrymmen.

(3)

Funktioner

Ett program kan delas in i flera funktioner där varje funktion har en separat uppgift. I de exemplen ni sett hittills har det endast funnits en enda funktion, main. Main är en speciell funktion som måste finnas med för att man ska ha någonstans att starta programmet. Från den funktionen kan man sedan anropa andra funktioner som utför vissa uppgifter.

Läs kap 3.1 och 3.2 i Deitel

Vi kan ta en titt på våra tidigare exempel ur modularitetssynvinkel.

Hela kaffeexemplet (modul 1) kan ses som en enda modul, en enda funktion som man utför men vi kan också se de separata delmomenten i kaffebryggandet som enskilda funktioner. Först ska vi bestämma antalet koppar vi ska brygga, det är en funktion. Hur vi kommer fram till hur många koppar som ska bryggas är inte intressant, bara att vi när funktionen är klar vet hur många koppar det ska vara.

Nästa steg var ju att mäta upp vatten vilket kan vara en funktion och nästa att mäta upp kaffe vilket är ytterligare en funktion. Man kan också tänka sig att det är två personer som hjälps åt att koka kaffe och då kan det vara en som mäter upp vatten och en annan som mäter upp kaffe. Vi bryr oss fortfarande inte om hur de gör det bara det blir gjort.

Om personen som mäter upp vatten häller direkt i kannan, mäter med en mugg eller med ett decilitermått spelar ju ingen roll, bara lagom mycket vatten blir uppmätt. Detsamma gäller för kaffet.

Den sista funktionen är ju att sätta på kaffebryggaren och det har vi ju också definierat som en egen funktion. För den funktionen har vi till och med talat om hur kontraktet ser ut. För att vi ska kunna utföra starten av kaffebryggaren måste ju sladden vara i.

Vi kan sätta upp kontrakt för de andra funktionerna också. För att vi ska kunna mäta upp vatten och kaffe måste det ju finnas tillräckligt av det vi ska mäta upp och vi måste också veta hur mycket vi ska ha. Om de två kraven är uppfyllda så borde det inte vara några problem att utföra funktionerna. Detta är förvillkoren till de två funktionerna.

Eftervillkoren är ju då att vatten respektive kaffe är uppmätt i lagom mängder beräknat på antal koppar som ska kokas.

Att se på funktionerna utifrån på det sätt som är beskrivet här, när man endast ser till dess funktionalitet, det vill säga vad de utför men inte hur, brukar kallas för ” blackbox” - perspektiv. Det är oftast det första läget i design-fasen. Man delar upp problemet i olika delar och bestämmer vad varje del ska lösa men man bryr sig inte om hur det ska lösas.

När man definierat alla sina delar kan man gå in och börja titta på detaljerna, vilket brukar kallas ” whitebox” -perspektiv, man ser inuti funktionerna. I början när man ska lära sig at programmera är det inte alltid så lätt att vet vad man kan göra och inte och då kan det ibland kännas svårt att definiera olika funktioner och vad deras uppgift är. Det är dock alltid en fördel om man gör ett försök att göra detta innan man börjar titta på

(4)

innehållet. Även om det inte fungerar sedan så har man i alla fall klart för sig vad det är man vill utföra och då är en stor del av arbetet gjort.

Nu ska vi börja titta lite mer på hur funktioner skrivs i C++.

Funktionsdefinition

En funktion måste deklareras innan den kan användas. En funktion har alltid ett namn, tex square. Namnet ska säga vad funktionen har för uppgift. Den här funktionen beräknar kvadraten på ett tal (dvs x * x). Funktionsnamnen följs alltid av vanliga parenteser för att visa att det är en funktion, square( ). Inuti parenteserna kan man skriva vilka parametrar som ska skickas till funktionen. (Jämför i matten f(x, y). ) Den parameter som funktionen square behöver är ju talet som den ska kvadrera, square(int y). Man måste också ange vilken typ parametern är av, här en int. En funktion kan även returnera ett resultat. Resultatet kan ju också vara av olika typer tex ett heltal, en

textsträng etc så därför måste man tala om vilken typ det ska vara. Detta görs genom att skriva typen framför funktionsnamnet, int square (int y). Här har vi alltså en funktion som heter square och som tar emot ett heltal och som returnerar ett heltal. För att vi ska vara säkra på vad funktionen gör behöver den en beskrivning också. Denna

beskrivning kan utgöras av en enkel text eller ett kontrakt med för- och eftervillkor eller bägge delarna.

Om vi funderar på kontraktet, finns det något särskilt som vi måste ta hänsyn till innan vi anropar funktionen? Det enda som används i funktionen är ju heltalet y. Finns det några särskilda värden som det inte får ha. Om vi ignorerar att talet kan bli för stort eftersom vi inte har pratat om minneshantering ännu så är svaret nej. Det vill säga, alla värden är giltiga, det går alltid att anropa den här funktionen när som helst. Detta brukar uttryckas med att sätta förvillkoret till ” true” .

//Funktion som beräknar kvadraten på ett heltal.

//förvillkor: true

//eftervillkor: har returnerat kvadraten på y int square ( int y )

Man kan också ange vad parametrarna är och vad funktionen returnerar. I just det här exemplet framgår ju det väldigt tydligt av eftervillkoret men ibland behövs det en specifikation av alla parametrar och returvärdet, då kan det se ut så här:

//Funktion som beräknar kvadraten på ett heltal.

//förvillkor: true

//eftervillkor: har returnerat kvadraten på y

//Parametrar: y – det heltal som kvadraten ska beräknas på //Returnerar: kvadraten på heltalet y

int square ( int y )

(5)

Funktionsanrop

Man kan sedan anropa funktionen square från något annat ställe i programmet, tex ifrån main. Då skriver man funktionsnamnet och inuti parenteserna skriver man det man vill skicka till funktionen, tex square(2); (OBS, glöm inte ; eftersom det är en egen sats).

Värdet 2 kommer nu att skickas in till funktionen square(int y), det vill säga y = 2. y är den formella parametern medan 2 är den aktuella parametern i det här exemplet. y beskriver vad parametern som ska skickas in i square ska heta och den heter alltid samma. Den aktuella parametern kan ändras och vara ett annat värde en annan gång. 2 är dem aktuella parametern för det är den parameter som skickas till funktionen just nu.

När square är färdig och returnerar sitt värde måste vi ju ta emot det värdet också. För att ha någonstans att ta emot det måste vi deklarera en variabel av samma typ som

funktionen returnerar, i det här fallet en int. Sedan tilldelar vi helt enkelt den variabeln det värde som funktionen returnerar. I main kan det då se ut så här:

int result;

result = square(2);

//result har nu värdet 4

Det finns givetvis funktioner som inte tar någon parameter och/eller inte har något returvärde. Detta uttrycks med void (kan översättas till ” tom” på svenska). Se kap 3.15.

Funktionskroppen

Hur ser det då ut inuti funktionen? Hela funktionskroppen innesluts i mjuka parenteser för att man ska veta var den börjar och slutar (precis som main som också är en funktion).

int square (int y) {

//Här är hela kroppen }

Innehållet i square är ganska kort. Det enda vi behöver göra är ju att räkna ut kvadraten på y och returnera resultatet. Vi kan helt enkelt skriva return y * y; Hela funktionen blir då:

int square(int y) {

return y * y;

}

Vi hade också kunnat skapa en variabel i square beräknat kvadraten och sparat i variabeln och sedan returnerat variabelns värde.

(6)

int square(int y) {

int kvad;

kvad = y * y;

return kvad;

}

Läs i boken 3.3 – 3.6

Övningar

Gör ” Övningar funktioner” del 1

Slumpa – funktionen rand()

När man vill slumpa fram tal finns det en funktion rand() som kan användas. Läs om rand() och en annan funktion srand(unsigned int) i kap 3.8 i boken. Ni kan också läsa 3.9 om ni vill se fler exempel på slumpning (enum ingår dock inte i kursen). Gör därefter övningen.

Övningar

Gör ” Övningar funktioner” del 2

Värdeanrop

Vi kan också skicka en variabels värde till funktionen.

int x = 3;

int result;

result = square(x);

//result är nu 9

När vi anropar funktionen anger vi inte vilken typ det är på parametern, det gör vi bara i funktionen när vi tar emot den. Det har ingen betydelse om den aktuella och formella parametern har samma namn eller inte. När vi skickar x till funktionen square är det egentligen värdet på x vi skickar och det skapas en kopia y som får det värdet. Om vi sedan ändrar på y i funktionen så påverkar det inte x överhuvudtaget. Så egentligen behöver vi inte skapa någon ny variabel i square, vi skulle kunna använda y.

int square(int y) {

//y har värdet 2 när den kommer in i funktionen y = y * y; //y får värdet 2 * 2

return y; //y har värdet 4 }

(7)

int main() {

int x = 2;

int result = 0;

result = square(x);

}

i main: i square

Även om de heter samma sak så blir förändras inte den ursprungliga variabeln värde eftersom det skapas en kopia.

int square(int y) {

//y har värdet 2 y = y * y; //y får värdet 2 * 2 return y; //y har värdet 4 }

int main() {

int y = 2;

int result = 0;

result = square(y);

} 2 x

2 Vi skickar värdet av x dvs y

2 till funktionen square

4 y

y = y*y

kopia

Returnerar 4 till den som anropade square

2 x

4 result

0 result

orginal

(8)

Detta kallas värdeanrop (call-by-value på engelska) eftersom det alltid är värdet vi skickar och tar emot. Man brukar också säga att funktionen har inparametrar.

Variablers räckvidd

Tänk på att variabeln kvad i exemplet med square inte går att använda någon annanstans i programmet. Dess räckvidd (scope) är begränsad till inuti funktionen, dess livslängd är ganska kort, när funktionen är klar dör variabeln. Dess värde går dock inte förlorat eftersom vi returnerar det och sparar det i variabeln result i main.

Läs om regler för räckvidd i kap 3.11 men bry dig inte om det som står om static- variabler.

Övningar

Gör ” Övningar funktioner” del 3

Referensanrop

Om vi nu vill att en funktion ska förändra originalet då? Då kan man använda referensanrop. Skillnaden mot värdeanrop är att nu skickar vi inte bara värdet på variabeln utan vi skickar en referens till variabeln.

Om vi tänker oss variabeln som en låda, en plats att ha saker i (det är ju faktiskt en plats i minnet att lägga värden i). Vi binder fast ett snöre i lådan och lägger i vårt värde. Sedan

2 y

2 Vi skickar värdet av x dvs y

2 till funktionen square

4 y

y = y*y

kopia

Returnerar 4 till den som anropade square

2 y

4 result

0 result

originalet har inte förändrats

(9)

skickar vi lådan till en annan funktion som förändrar värdet. När den är klar drar vi tillbaka lådan i snöret som vi fäst i den. Funktionen opererade på originalet till skillnad från i värdeanrop där funktionen bara har en kopia att arbeta med.

För att skilja mellan värde- och referensanrop sätter man ett & i funktionsdeklarationen.

Om vi använder vårt tidigare exempel med square men definierar om den och säger att den variabel som skickas in ska förändras till att innehålla kvadraten av det värde som den hade från början, skulle det se ut så här: square(int &y). Vi har här en utparameter y.

Nu behöver vi ju inte returnera värdet längre eftersom det finns lagrat i utparametern, därför skriver vi void framför: void square(int &y)

Anropet till funktionen ser dock likadant ut som vid värdeanrop square(x). Skillnaden är att här behöver vi inte ta emot värdet eftersom det finns lagrat i den aktuella parametern som vi skickar till funktionen. Vid referensanrop spelar det inte heller någon roll om den formella och aktuella parametern har samma namn eller inte.

void square(int &y) {

//y har värdet 2 y = y * y; //y får värdet 2 * 2 }

int main() {

int x = 2;

square(x);

//x har nu värdet 4 }

Läs mer om värde- och referensanrop i kap 3.17.

Övningar

Gör ” Övningar funktioner” del 4 2

x y

Vi skickar en referens till x till funktionen square

y

y = y*y

4

x Ändrar i orginalet

(10)

Delprogram

Header-filer

Läs 3.7

I kap 3.7 beskrivs flera olika delar av C++ standardbibliotek. Varje del ligger i en egen header-fil. Header-filer använder man oftast för att lägga sina definitioner och prototyper i. Det är väldigt praktiskt att samla alla dem på ett ställe och genom att titta i header-filen får man en snabb överblick av vad programmet har för funktionalitet.

När man skapar egna header-filer ger man dem filändelsen h istället för cpp. Header-filen inkluderas sedan i cpp-filen med preprocessorkommandot include.

Ex)

Fil: Bank.h

//inkluderingar

#include <iostream>

#include <cmath>

//konstanter

const int ACCOUNTS = 50;

//funktionsprototyper

void addMoney(int accountNum, float money);

boolean withdrawMoney(int accountNum, float money)

Fil Bank.cpp

#include “Bank.h”

//resten av programmet….

När man inkluderar standarbibliotekets header-filer använder man <> runt namnet, när man inkluderar egna header-filer använder man ” ” .

Ta ert exempel där ni slumpade fram tal i olika funktioner. Om ni har några

funktionsprototyper så ta bort dem. Lägg main överst av funktionerna och prova att kompilera. Vad säger kompilatorn och varför? Titta på kap 3.6 igen.

Skapa nu en ny fil (gärna med samma namn som er andra fil) med ändelsen h istället för cpp. I den filen lägger ni alla funktionsprototyper (inte för main). (Glöm inte ; efter varje prototyp). Här talar ni också om vilka standardbibliotek ni vill inkludera liksom vilka namnutrymmen ni ska använda (tex using std::cout). I cpp-filen har ni sedan bara en enda inkluderingsrad och det är inkluderingen av er h-fil. Prova nu att kompilera igen.

(11)

När man kompilerar cpp-filen så inkluderas även h-filen i programmet. När man har flera filer som ska kompileras tillsammans brukar man skriva en så kallad make-fil för att underlätta arbetet. Hur man skriver make-filer samt mer om flera filer och om kompilering kommer i modul 5.

Övningar

Gör ” Övningar funktioner” del 5

Kontraktsprogrammering

Vi har beskrivit kontrakt tidigare och sett varför det är bra att använda. Vi har också sett olika exempel på hur de kan användas för att dokumentera sina moduler. Här följer lite fler exempel som börjar i vardagslivet och fortsätter via mattematiken och vidare in i programmering.

Ex) Bilköp

Krav Förtjänst

Kund Betala varje månad Få en bil

Försäljare Ge kunden en bil och serva den

en viss tid Få pengar varje månad

En person (kunden) köper en bil på avbetalning hos en bilfirma. Kunden förbinder sig att betala en viss summa varje månad, i gengäld får kunden en bil. Bilfirman förbinder sig att ge kunden en bil, och serva den under viss en tidsperiod, i gengäld får firman pengar varje månad.

Om kunden inte betalar vet man inte vad som händer, firman kanske hämtar hem bilen eller ringer kronofogden. Om firman inte ger kunden någon bil eller låter bli att serva den får han Sverker på halsen.

(12)

Ex) Boka biljett

Krav Förtjänst

Kund Betala biljetten och vara på

flygplasten i tid Få åka till Hawaii Försäljare Flyga resenären till Hawaii Få pengar

En person (resenären) bokar en flygresa till Hawaii. Resenären förbinder sig att betala innan ett visst datum samt att infinna sig på flygplatsen minst en timme före avgång, i gengäld får resenären åka med planet till Hawaii. Resebyrån förbinder sig till att ta kunden till Hawaii på bestämt datum. I gengäld får resebyrån pengar av resenären. Om resenären inte betalar i tid eller inte kommer i tid så får han inte åka med planet. Om resebyrån inte flyger ner resenären får resenären pengarna tillbaka (förhoppningsvis).

Ett kontrakt kan ses från två sidor, från insidan och från utsidan.

Från ” insidan”

• Vad kräver jag vid anrop av mig

• Vad ger jag tillbaka till anroparen

Från ” utsidan”

• Vad krävs för att anropa modulen

• Vad får jag tillbaka

Ex) Division

När man utför division får nämnaren inte vara noll, en matematiker använder en funktion för att beräkna division. Vi kan beskriva vilka krav och förtjänster det finns för

matematikern och för funktionen som ska dividera.

Insidan Utsidan

Kontraktet

(13)

Krav Förtjänst

Matematiker Nämnaren får ej vara noll Får kvoten mellan täljare och nämnare

Funktion för att dividera

Dividera täljare med nämnare och returnera kvoten

Slipper kontrollera om täljaren är noll

Matematikern förbinder sig att inte anropa funktionen med en nämnare som är noll, i gengäld får han tillbaka ett korrekt resultat som är kvoten mellan täljare och nämnare.

Funktionen förbinder sig att returnera en korrekt kvot mellan täljare och nämnare, i gengäld behöver den inte kontrollera nämnaren innan den utför beräkningen. Om

matematikern anropar funktionen med en nämnare som är noll så är resultatet odefinierat, dvs det kan bli vad som helst

Detta kan också beskrivas i ett kontrakt med för- och eftervillkor, vilket vi sett exempel på tidigare.

• Förvillkor – vad som ska gälla när funktionen anropas, om det inte är uppfyllt är resultatet odefinierat

• Eftervillkor – vad som ska gälla när funktionen är klar, under förutsättning att förvillkoret var uppfyllt

Vi kan beskriva detta ur matematikerns perspektiv, dvs vad som krävs och vad han får i gengäld:

Förvillkor: nämnaren får inte vara noll

Eftervillkor: kvoten mellan täljare och nämnare har returnerats

Matematikerns perspektiv är ju utifrån funktionen och det är den information som behövs för alla de som ska använda funktionen. Om vi skulle skriva en funktion som beräknar division kan det se ut så här:

//pre: nämnare != 0

//post: kvoten mellan taljare och namnare har returnerats float dividera(float taljare, float namnare)

{

return taljare/namnare;

}

(14)

Om vi nu ska anropa den här funktionen måste kontrollera att förvillkoret är uppfyllt först.

Ex)

int main() {

float taljare, namnare;

cout<<”Skriv in täljare och nämnare: ”;

cin>>taljare>>namnare;

if(namnare != 0)

cout<<”Kvoten mellan ” <<taljare <<” och ” <<namnare <<” är ” << dividera(taljare, namnare) <<endl;

else

cout<<”Du kan inte dividera med 0!” <<endl;

return 0;

}

Körning 1

Körning 2

Ex) Bankprogram

Vi ska skapa ett enkelt bankprogram där man kan sätta in och ta ut pengar på ett konto.

Vi behöver följande beståndsdelar:

saldo – en variabel, hur mycket pengar vi har

• sattInPengar – en funktion som sätter in pengar (dvs ökar saldo)

taUtPengar – en funktion som tar ut pengar (dvs minskar saldo)

Vi tittar på vad som gäller för funktionerna för att sätta in och ta ut pengar. Vi börjar med taUtPengar. Till den funktionen skickar vi in saldot för det aktuella kontot och summan vi vill ta ut från kontot. Deklarationen ser då ut så här:

void taUtPengar(int &saldo, int ut);

Vad ska då gälla för att man ska få anropa funktionen? Man kan ju inte ta ut mer pengar än man har på kontot så förvillkoret måste ju vara att ut <= saldo. Om detta stämmer så kan funktionen garantera att pengarna är dragna från saldot. Vi kan ange vårt eftervillkor till funktionen som att saldo har minskats med ” ut” kronor. Vi kan ju inte heller ta ut en negativ summa pengar. Det skulle ju bli samma sak som att sätta in pengar och det har vi ju en annan funktion till. Det är viktigt att funktionerna utför det som de är tänkta att göra och att man förhindrar användarna av funktionerna att missbruka dem genom att använda

Skriv in täljare och nämnare: 10 5 Kvoten mellan 10 och 5 är 2

Skriv in täljare och nämnare: 10 0 Du kan inte dividera med 0!

(15)

dem till andra saker än de är tänkta till. Vi lägger till i förvillkoret att summan som man ska ta ut måste vara positiv. Om vi skriver detta i kod ser det ut så här:

//pre: 0 <= ut <= saldo //post: saldo = saldo – ut

void taUtPengar(int &saldo, int ut);

Istället för att skriva förvillkor och eftervillkor i koden brukar man ofta använda förkortningar av de engelska orden (precondition och postcondition), dvs pre och post.

Det går bra att använda vilket sätt man vill.

Innan man anropar funktionen taUtPengar måste man kolla så att förvillkoret är uppfyllt.

Ex)

int main() {

int saldo = 300, uttag;

cout<<”Hur mycket vill du ta ut? ; cin>>uttag;

if(uttag < 0)

cout<< ”Du kan inte ta ut en negativ summa!” <<endl;

else if(uttag > saldo)

cout<<”Du kan inte ta ut, du har inte tillräckligt med pengar på kontot!” <<endl;

else

taUtPengar(saldo, uttag);

return 0;

}

Nu tittar vi på funktionen sattInPengar. Vilka villkor gäller för att den ska kunna anropas? Inte heller här får vi sätta in en negativ summa, det skulle ju vara samma sak som att ta ut pengar. Finns det några begränsningar för hur mycket man får sätta in? Nej, de flesta banker brukar bara bli glada om man vill sätta in mycket pengar (även om de kan bli lite misstänksamma ibland). Eftervillkoret bli helt enkelt att man satt in pengarna och ökat saldo med angiven summa. Om vi skriver det i kod ser det ut så här:

//pre: in >= 0

//post: saldo = saldo + in

void sattInPengar(int &saldo, int in);

Även här måste vi göra en kontroll innan vi anropar funktionen men nu är det bara ett intervall vi måste kontrollera.

(16)

Ex)

int main() {

int saldo = 300, insattning;

cout<<”Hur mycket vill sätta in? ; cin>> insattning;

if(insattning < 0)

cout<< ”Du kan inte sätta in en negativ summa!” <<endl;

else

sattInPengar(saldo, insattning);

return 0;

}

Vi skriver nu kroppen i funktionerna, det vill säga själva koden som utför något.

void taUtPengar(int &saldo, int ut) {

saldo = saldo – ut;

}

void sattInPengar(int &saldo, int in);

{

saldo = saldo + in;

}

Det var väldigt enkelt att skriva koden nu när vi visste exakt vad funktionerna ska utföra och vad som gäller när den anropas. Det hade blivit mycket krångligare om vi inte hade haft våra kontrakt. Då hade vi tex behövt kolla i taUtPengar om det fanns tillräckligt med pengar och så att ut inte var negativ. Framförallt är frågan vad hade vi gjort om det inte hade gått att ta ut pengar? Hur skulle användaren av funktionen (i det här fallet main) få veta om det gick bra eller inte? Vi skulle kunna skicka tillbaka ett returvärde som talade om ifall det gick bra eller inte och om inte, varför det inte gick bra. Då måste man bestämma vad olika returvärden betyder, ett för om det gick bra och två för om det inte gick bra. Sedan måste användaren av funktionen kontrollera resultatet för att se om det gick bra eller inte. Det är både enklare och naturligare att kontrollera innan man anropar funktionen.

Hela koden för Bank-programmet finns på hemsidan. Testa gärna.

I första exemplet är alla värden av heltalstyp (int). Det betyder att man bara kan sätta in och ta ut jämna kronor. Om man ska kunna sätta in och ta ut ören också så kan vi använda flyttal (float) istället. Koden för detta program finns också på hemsidan.

Övningar

Gör ” Övningar funktioner” del 6

References

Related documents

Du kan få ekonomisk ersättning om du anställer en person som har varit utan arbete en längre tid eller är ny i Sverige. Syftet är att stimulera

När du gjort ditt val flyttar du gemet till fält 1 på kunskapsstickan.. Bildkälla

Egmont Porten Höst 2013/2014

Låt f vara en strängt monoton funktion denierad på intervallet [a, b].. Visa att f kan ha högst ett nollställe på

Om barnet har en trygg anknytning till sin mamma eller pappa kommer anknytningen till förskolläraren i största sannolikhet också vara trygg, medan barn som har en otrygg

Jag dömdes till ett års fängelse för att ha varit med i en kriminell grupp och för att ha förstört allmän egendom.. El Wali ser lite trött ut, när han svarar på frågan

Om en feriepraktikant fått en tillsägelse av handledare och händelsen upprepas ska handledaren kontakta ansvariga för feriepraktiken.. En muntlig och skriftlig varning kan

Syftet med studien är att undersöka de informella, för de inblandade ofta oreflekterade, interaktioner som äger rum i möten mellan de äldre hjälpsö- kande, deras anhöriga