Inleiding programmeren in C++ Life Science & Technology 2 februari 2004 http://www.liacs.nl/home/kosters/lst Universiteit Leiden.

Download Report

Transcript Inleiding programmeren in C++ Life Science & Technology 2 februari 2004 http://www.liacs.nl/home/kosters/lst Universiteit Leiden.

Inleiding programmeren in C++
Life Science & Technology
2 februari 2004
http://www.liacs.nl/home/kosters/lst
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
resultaattype
body (ingesprongen)
functienaam
void tekstopscherm ( ) {
cout << "Sterke tekst" << endl;
// void functies hebben geen return-value
} // tekstopscherm
int main ( ) {
tekstopscherm ( );
}
return 0;
// main
Functies – parameters
“return” van
het resultaat
parameters
int inhoud (int l, int b, int h) {
return l * b * h;
} // inhoud
• dit kan bestaan naast (dit heet overloading):
double inhoud (double l, double b, double h) {
return l * b * h;
} // inhoud
Functies – formele en actuele parameters
int inhoud (int l, int b, int h) {
int hulp;
hulp = l * b * h;
return hulp;
} // inhoud
....
t = inhoud (b, 5, x);
• 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
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);
b = ggd (b, 7);
// dat wordt 3
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)
formeel
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);
// nog steeds 5
cout << q;
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);
// nu 0
cout << q;
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 <iostream>
#include <cmath>
using namespace std;
// functie levert true als getal een priemgetal is
bool priem (int getal) {
int deler = 2;
double wortel =
bool geendelers
while ( ( deler
if ( (
}
sqrt (getal);
= true;
<= wortel ) && geendelers)
getal % deler ) == 0)
geendelers = false;
// meteen
return false;
deler++;
} // while
return geendelers;
// priem
// uit cmath
// optimist!
{
// dus geen priemgetal
mag ook
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
(1)
a = 5; b = 13; kwadraat (a);
cout << "2: " << a << " en " << b << endl;
1: 25 en 14
2: 5 en 14
(2)
a = 2; b = 7; kwadraat (b);
cout << "2: " << a << " en " << b << endl;
1: 49 en 8
2: 2 en 8
(3)
(4)
Als (1), met heading kwadraat (int& a)
1: 25 en 14
2: 25 en 14
Als (2), met heading kwadraat (int& a)
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 functie (char kar, double & getal) {
...
int locaal;
...
} // functie
// locale variabele
adres
// globale variabele
waarde
int globaal;
void nogeenfunctie ( ) {
...
cout << functie (letter, reeelgetal) << endl;
...
} // nogeenfunctie
int main ( ) {
...
} // main
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 1 + 2 + 3 + ... + 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 << en >>
gedefinieerd in <iostream>
#include <iostream>
using namespace std;
...
char kar;
...
cout << ”Tekst schrijven naar beeldscherm”;
cin >> kar;
• Schrijven naar en lezen uit een file is te vergelijken met
schrijven naar cout (het beeldscherm) en lezen van cin
(toetsenbord)
Files
• Een inputfile is van het type ifstream
• Een outputfile is van het type ofstream
• Samen met de bijbehorende operatoren << en >>
gedefinieerd in <fstream>
#include <fstream>
using namespace std;
invoer.open ("oudbestand.txt");
uitvoer.open ("nieuwbestand.txt");
...
invoer >> kar;
uitvoer << kar;
ifstream invoer;
ofstream uitvoer;
char kar;
invoer.close ( );
uitvoer.close ( );
Functies voor lezen en schrijven
Voorbeeld met
cin en cout
Voorbeeld met
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 (invoer, str);
getline(cin, str, ’\n’); getline(invoer, str,’\n’)
cout << str << endl;
uitvoer << str << endl;
ifstream invoer;
ofstream uitvoer;
cin >> ... slaat spaties en dergelijke over, .get niet!
Openen gelukt?
Einde van de file bereikt?
• File bestaat niet, of kan niet worden geopend
invoer.open ("oudbestand.txt");
if ( ! invoer ) {
cout << "Invoerbestand kan niet worden geopend" << endl;
return 1;
} // if
• Einde van de file bereikt?
– invoer.eof ( ) kan alleen worden gebruikt nadat er gelezen is!
invoer.get (kar);
while ( ! invoer.eof ( ) ) {
cout.put (kar);
invoer.get (kar);
} // while
Voorbeeld: file kopiëren
#include <iostream>
#include <fstream>
using namespace std;
uitvoer.open ("nieuwbestand.txt");
int main ( ) {
ifstream invoer;
ofstream uitvoer;
char kar;
while ( ! invoer.eof ( ) ) {
uitvoer.put (kar);
kar = invoer.get ( );
} // while
invoer.open ("oudbestand.txt");
if ( ! invoer ) {
cout << "Probleem!" << endl;
return 1;
} // if
kar = invoer.get ( );
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 <cmath>
• 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