Inleiding programmeren in C++ Life Science & Technology 2 februari Universiteit Leiden
Week 3 Inhoud –Functies Doel –Leren omgaan met variabelen en functies in C++ Materiaal –Ammeraal Hoofdstuk 4 (niet 4.3, 4.5, 4.7 en 4.8) en Hoofdstuk 8 (niet 8.5) –Dictaat Hoofdstuk 3.3, 3.4 en 3.5 (niet 3.5.3) en opgaven 15/28 –De tweede programmeeropgave Werkcollege –Implementeer opgaven 9a,b, 10, 11, 13, 20 (, 19)
Functies void tekstopscherm ( ) { cout << "Sterke tekst" << endl; // void functies hebben geen return-value } // tekstopscherm int main ( ) { tekstopscherm ( ); return 0; } // main resultaattype functienaam body (ingesprongen)
Functies – parameters dit kan bestaan naast (dit heet overloading): int inhoud (int l, int b, int h) { return l * b * h; } // inhoud parameters “return” van het resultaat double inhoud (double l, double b, double h) { return l * b * h; } // inhoud
Functies – formele en actuele parameters l, b, h en hulp: locale variabelen, hun scope is de functie inhoud l, b en h: formele parameters, en krijgen als startwaarde de waarde van de actuele parameters b, 5 en x (in de aanroep) zijn de actuele parameters; zo krijgt de formele l als startwaarde de waarde van de actuele b int inhoud (int l, int b, int h) { int hulp; hulp = l * b * h; return hulp; } // inhoud.... t = inhoud (b, 5, x);
Functies - voorbeeld /* Bepaal grootste gemeenschappelijke deler (ggd) * van gehele x en y, beide >= 0 en niet x = y = 0, * met het algoritme van Euclides */ int ggd (int x, int y) { int rest;// voor rest bij delingen while ( y != 0 ) { rest = x % y; x = y; y = rest; } // while return x; } // ggd... cout << ggd (15, 21); // dat wordt 3 b = ggd (b, 7);
Functies - call by reference /* Vereenvoudig de breuk teller/noemer zoveel mogelijk * neem aan dat teller >= 0 en noemer > 0 */ void vereenvoudig (int & teller, int & noemer) { int deler = ggd (teller, noemer); if ( deler > 1 ) { teller = teller / deler; noemer = noemer / deler; } // if } // vereenvoudig int main ( ) { int tel = 15, noem = 21; vereenvoudig (tel, noem); cout << tel << " / " << noem << endl; return 0; } // main call by reference
Call by value Er wordt alleen een waarde doorgegeven, en wel van de actuele parameter aan de formele parameter Er wordt dus een lokale kopie gemaakt (wat een beetje tijd en ruimte kost) void hoogop (int x) { x = x + 10; } void maaknul (int t) { t = 0; cout << t; } x = 7; hoogop (x); cout << x; // nog steeds 7 m = 3; hoogop (m+2); cout << m; // nog steeds 3 q = 5; maaknul (q); cout << q; // nog steeds 5 formeel actueel
Call by reference Er wordt een adres (een “pointer”) doorgegeven De actuele parameter kan nu wel degelijk veranderen De actuele parameter mag geen rare expressie zijn (zoals x + 3 of 42), denk aan de l-value in een toekenning void hoogop (int & x) { x = x + 10; } void maaknul (int & t) { t = 0; } x = 7; hoogop (x); cout << x; // nu 17 m = 3; hoogop (m+2); cout << m; // KAN NIET! q = 5; maaknul (q); cout << q; // nu 0
Volgorde van functies Functies staan na elkaar in het C++-programma. Een functie mag alleen functies aanroepen die er boven staan: void george ( ) { … } int ringo (int x) { … } double john (int y) { … } void paul (bool & b) { … } int main ( ) { … } Hier mag john gebruik maken van george, ringo en van john zelf (dat heet recursie), maar niet van paul. Eventueel kunnen “prototypes” (kopregels) worden gebruikt om hier iets aan te doen.
Priemgetallen #include using namespace std; // functie levert true als getal een priemgetal is bool priem (int getal) { int deler = 2; double wortel = sqrt (getal);// uit cmath bool geendelers = true;// optimist! while ( ( deler <= wortel ) && geendelers) { if ( ( getal % deler ) == 0)// dus geen priemgetal geendelers = false; // meteen return false; mag ook deler++; } // while return geendelers; } // priem
Parameteroverdracht int b; void kwadraat (int a) { a = pow (a, 2);// a * a, pow komt uit cmath b++; cout << "1: " << a << " en " << b << endl; } // kwadraat a = 5; b = 13; kwadraat (a); cout << "2: " << a << " en " << b << endl; (1) a = 2; b = 7; kwadraat (b); cout << "2: " << a << " en " << b << endl; (2) (3)Als (1), met heading kwadraat (int& a) (4)Als (2), met heading kwadraat (int& a) 1: 25 en 14 2: 5 en 14 1: 49 en 8 2: 2 en 8 1: 25 en 14 2: 25 en 14 1: 50 en 50 2: 2 en 50
Vier soorten variabelen 1.Call by value parameters in feite geïnitialiseerde locale variabelen 2.Call by reference parameters call by reference is te herkennen aan een & 3.Globale variabelen die niet als value of reference parameters worden meegegeven zoveel mogelijk vermijden 4.Locale variabelen niet geïnitialiseerd kladblaadjes
Scope van variabelen nogmaals int globaal;// globale variabele int functie (char kar, double & getal) {... int locaal;// locale variabele... } // functie void nogeenfunctie ( ) {... cout << functie (letter, reeelgetal) << endl;... } // nogeenfunctie int main ( ) {... } // main waarde adres
Recursie Functie roept “zichzelf” aan Denk aan de stopregel (basisstap) Elegant, maar niet automatisch efficiënt; voor liefhebbers /* Als ggd, maar nu recursief * Algoritme van Euclides, met de volgende regels *ggd (x, 0) = x *ggd (x, y) = ggd (y, x mod y) met y != 0 */ int ggdrecursief (int x, int y) { if ( y == 0 ) return x; else return ggdrecursief (y, x % y); } // ggdrecursief
Recursie (2) // berekent n int som (int n) { int i, res = 0; for ( i = 1; i <= n; i++ ) res = res + i; return res; } // som int somrecursief (int n) { if ( n == 0 ) return 0; else return (n + somrecursief (n-1)); } // somrecursief int somslim (int n) { return (n * (n + 1)) / 2; } // somslim
Introductie files eerst nog even cin en cout cin is van het type istream (inputstream) cout is van het type ostream (outputstream) Samen met de bijbehorende operatoren > gedefinieerd in Schrijven naar en lezen uit een file is te vergelijken met schrijven naar cout (het beeldscherm) en lezen van cin (toetsenbord) #include using namespace std;... char kar;... cout << ”Tekst schrijven naar beeldscherm”; cin >> kar;
Files Een inputfile is van het type ifstream Een outputfile is van het type ofstream Samen met de bijbehorende operatoren > gedefinieerd in #include using namespace std;... ifstream invoer; ofstream uitvoer; char kar; invoer.open ("oudbestand.txt"); uitvoer.open ("nieuwbestand.txt"); invoer >> kar; uitvoer << kar; invoer.close ( ); uitvoer.close ( );
Functies voor lezen en schrijven Voorbeeld met cin en cout Voorbeeld met ifstream invoer; ofstream uitvoer; Karakter char kar; cin.get (kar); kar = cin.get ( ); cout.put (kar); char kar; invoer.get (kar); kar = invoer.get ( ); uitvoer.put (kar); Woord string str; cin >> str; cout << str; string str; invoer >> str; uitvoer << str; Regel getline (cin, str); getline(cin, str, ’\n’); cout << str << endl; getline (invoer, str); getline(invoer, str,’\n’) uitvoer << str << endl; cin >>... slaat spaties en dergelijke over,.get niet!
Openen gelukt? Einde van de file bereikt? File bestaat niet, of kan niet worden geopend Einde van de file bereikt? –invoer.eof ( ) kan alleen worden gebruikt nadat er gelezen is! invoer.open ("oudbestand.txt"); if ( ! invoer ) { cout << "Invoerbestand kan niet worden geopend" << endl; return 1; } // if invoer.get (kar); while ( ! invoer.eof ( ) ) { cout.put (kar); invoer.get (kar); } // while
Voorbeeld: file kopiëren #include using namespace std; int main ( ) { ifstream invoer; ofstream uitvoer; char kar; invoer.open ("oudbestand.txt"); if ( ! invoer ) { cout << "Probleem!" << endl; return 1; } // if uitvoer.open ("nieuwbestand.txt"); kar = invoer.get ( ); while ( ! invoer.eof ( ) ) { uitvoer.put (kar); kar = invoer.get ( ); } // while invoer.close ( ); uitvoer.close ( ); return 0; } // main
Werkcollege Uit het dictaat de sommen 9 (a en b), 10, 11, 13 en 20 –bij opgave 20: zie boek p. 208 voor Los de problemen steeds op met behulp van één of meer goed gekozen functies Voeg tot slot alle functies samen in één programma, waarin de gebruiker kan kiezen –bijvoorbeeld door het nummer van de opgave in te geven, of uit een eenvoudig menu te kiezen Uit het dictaat (oude tentamen)opgave 19 –probeer te beredeneren wat er gebeurt –type het programma eventueel in om het te controleren en te achterhalen hoe het werkt