Werken met Functies cvo/ Progr Hans opstaele



Dovnload 61.02 Kb.
Datum24.07.2016
Grootte61.02 Kb.

Werken met Functies

CVO/ Progr Hans OPSTAELE




De werking van functies

Een functie bestaat altijd uit drie delen:

1. De functienaam (hoofdletter-gevoelig)

2. Parameter(s) [ optioneel ]

3. De return-waarde [ optioneel ]
Deze drie eigenschappen vormen een functie-prototype.


functie prototype


functienaam

parameter

type van de return-waarde


void toon()

{

printf(“in functie toon”);



}

toon

géén

géén

double pi()

{

return 3.141592;



}


pi

géén

double

void zetA(int val)

{

a=val;



}


zetA

val (type=integer)

géén

double geefV(int index)

{

return v[index];



}


geefV

index (type=integer)

double



Functies aanroepen…

Als je een functie aanroept, moet de functie-prototype voor de compiler gekend zijn. De compiler werkt altijd van het begin van het document naar het einde: dit wil zeggen dat de functie moet bekend gemaakt worden vóór ze gebruikt wordt:


Correct is:
double opp_cirkel(double r)

//functie definieren voor gebruik ervan in main.

{ return 3.1415*r*r ;

}

int main()



{ double opp ;

opp=opp_cirkel( 2 ) ;

return 0;

}
Correct is:


//functieprototype definieren voor gebruik ervan in main.

double opp_cirkel(double r);


int main()

{ double opp ;

opp=opp_cirkel( 2 ) ;

return 0;

}

double opp_cirkel(double r)



{ return 3.1415*r*r ;

}

NIET CORRECT:


int main()

{ double opp ;

// PROBEREN FUNCTIE TE GEBRUIKEN ZONDER PROTOTYPE ?!!

opp=opp_cirkel( 2 ) ;

return 0;

}

double opp_cirkel(double r)



{ return 3.1415*r*r ;

}

Parameters


Bij een functieoproep wordt een parameterwaarde over-gecopieerd in een variabele binnen de aangeroepen functie. Dit is CALL-BY-VALUE (het omgekeerde noemt CALL-BY-REFERENCE).




De waarde (12) wordt gekopieerd naar de eerste parameter ‘b’ van functie zetA(…). Deze parameter wordt een locale variabele in de functie zetA( … ).
Een identiek scenario als de functie wordt opgeroepen met een variabele ipv een waarde. Hieronder wordt de functie opgeroepen met de variabele ‘x’, die de waarde 123 bevat:

Array’s in functies…

Een array als parameter, geef je mee als een pointer. In de functie zelf, kan je dan gewoon ermee verder werken.


Merk dus op dat je een array altijd doorgeeft als ‘call-by-reference
en nooit als call-by-value.
Voorbeeld 1:
void reverse(char *str)

{ int n=strlen(str) / 2;

for (int i=0; i

}
int main()

{

char s[100]=”hallo wereld”;



reverse( s );

cout << s << endl;

return 0;

}

Voorbeeld 2


#include

..
class Werknemer {

char s[100]; //memberdata

public:


void zetNaam(char *n) { strcpy(s,n); } //parameter is array

void Toon () { cout << “De naam is “ << s; }

};
int main()

{

char naam[100];



Werknemer iemand;
cout << “Geef me een naam: ”;

cin >> naam;

iemand.zetNaam( naam );
return 0;

}

Arrays als return-waarde

Arrays als return waarde (zoals hieronder getoond) zijn minder gemakkelijk en soms zelfs controversieel, want de echte goede werkwijze is nogal omslachtig...
Er zijn twee grote DON’Ts :


  1. Wat je namelijk niet zomaar mag doen is een array die een lokale variabele is in een functie zomaar meegeven..
    char *zegHallo()
    { char s[100]=”hallo”;
    return s;
    }
    Dit is ronduit gevaarlijk omdat de buffer s een lokale variabele is en dus vernietigd wordt, bij de return-opdract. Nochtans zal de compiler dit aanvaarden en als je geluk/ongeluk hebt zal je programma zelfs gewoon werken. Daar de stack niet onmiddellijk wordt overschreven.

  2. Geheugen aanmaken in de functie en verwachten dat de oproepen die de-alloceert.
    Het is een afspraak dat ofwel de oproeper ofwel opgeroepene (caller) volledig instaat voor de allocatie én deallocatie van geheugen.

    Te vermijden: char *func() { char *s=new char[100]; strcpy(s,”hallo”); return s; }


    (de oproeper moet hier het geheugen de-alloceren).

Ik toon hier een vereenvoudigd voorbeeld en daarnaast een veilig methode, maar die nogal omslachtig is...

Voorbeeld1

char *zegHallo(char *buf, int n)


//de functie krijgt de buffer van de oproeper

//als de buffer te klein is, dan wordt de string afgekapt

{

strncpy( buf, “hallo” , n);


buf[n-1]=’\0’; //force terminating zero
return buf;

}
void main()


{
....
char s[100];
zegHallo( buf, 100 ); //geef buffer en zeg wat de max. lengte van de string is

}

Voorbeeld 2:


char *zegHallo(char *buf, int &n)
//de functie zeg aan de oproeper hoelang de buffer moet zijn

{

#define MSG “hallo”



if (buf==NULL) {

*n = strlen(MSG)+1;

return NULL;

}

else {



strncpy( buf, MSG , *n);
buf[*n-1]=’\0’; //force terminating zero
}
return buf;

}
void main()


{
.... //de oproeper moet ALTIJD TWEEMAAL DE FUNCTUNTIE OPEREOEPEN!

int len;
zegHallo( NULL, &len ); //Haal de lengte op.

char *buf=new char[ len ];

if (buf ) zegHallo( buf, &len); //geef nu buffer mee om er in te schrijven

...

delete []buf;



}

Opmerkingen:


1. Een array (in dit geval de character array “naam”) wordt in de parameter-lijst opgenomen als “char *”.

2. Een array kan niet op eenvoudige wijze gecopieerd wordt (zoals dit met een double, integer ed het geval was). Voor een character – array kunt u gebruik maken van de functie strcpy (‘string copy’). Met moet doorvoor wel boven aan het programma #include schrijven om naar de juiste code-bibliotheek te verwijzen.




Als de parameter een struct (of een klasse) is…

Er is in C++ geen onderscheidt tussen een structuur en een basisdatatype bij het meegeven als een parameter. Ook is het teruggeven van een struct identiek, maar merk op dat een struct meestal meer geheugen in beslag neemt dan een simpel basisdatatype en dus een kostbare operatie is!


Voorbeeld:
struct 3DPos {

int x,y,z;

};
void InitPos1( 3DPos p) //call by value

{

p.z=p.y=p.x=0; //heeft geen effect want ‘by value’



}
void InitPos2( 3DPos &p) //by reference

{

p.z=p.y=p.x=0; //heeft geen effect want ‘by value’



}
3DPos InitPos3() //als return-waarde

{ 3DPos p;

p.z=p.y=p.x=0; //heeft geen effect want ‘by value’

return p;

}

void main()



{

3DPos pos;

InitPos1( pos ) ; //FOUTIEF!!

InitPos2(pos) ; //OK

pos = InitPos 3() ; //maak een copy van pos :

return 0;

}

OPDRACHT 1: Morse Code


Maak een programma die een ingegeven letter omzet in morse code. Maak gebruik van de volgende array:
const char *morse[]={

".-", "-...", "-.-.", "-..", "." , ".-.." , "--." ,

"...." , ".." , ".---", "-.-", ".-..", "--", "-.",

"---", ".--.", "--.-",".-.","...","-","..-","...-",".--","-..-",

"-.--", "-.--","--.-", NULL

/* NULL is gelijk aan 0L*/

};

Voorbeeld uitvoer:

Geef letter: c

Morse code: -.-.

Opdracht 2: Morse Code (2)


Laat de gebruiker een woord ingeven. Schrijf elke letter van het woord uit in morse code. Maak gebruik van een functie om de morse-code per letter op het scherm te schrijven.

Bijvoorbeeld:

char *geefMorse( char letter )
{

//zoek de morse code in de tabel op..

return morse[ index ];
}

int main()


{
//LEES de zin in.

//VOOR ALLE letters van de zin


for (... ; ... ; ...) {
char *morse;
morse = geefMorse( ... );
cout << morse << endl;
}
...
}

Uitvoer :

Geef woord: Jan

Morse Code:
.---
.-
-.

Noot: Door de window-library te gebruiken kan je geluidjes laten horen dmv. de Beep-functie.
Bvb. Beep(440,1000);

De frequencie is 440 Hz

De duur is 1000 ms = 1 seconde

Opdracht 3: Modularisering


Het volgende programma maakt gebruik van de volgende zes functies:

celsius_of

print_preliminary_message

print_message_echoing_input


absolute_value_of

input_table_specifications

print_table


Voeg de ontbrekende functies toe zodat de uitvoer hieronder overeenkomt met het programma. Test uw programma voor verschillende invoer waarden.

 

/* This program prints out a conversion table of temperatures, after



prompting the user for upper and lower bounds of the table in Fahrenheit, and

the temperature difference between table entries. */

 

#include



using namespace std;

/* START OF MAIN PROGRAM */

int main()

{


int lower = 0; /* the lowest Fahrenheit entry in the table */

int upper = 0; /* the highest Fahrenheit entry in the table */

int step = 1; /* difference in Fahrenheit between entries */

 

/* print a message explaining what the program does: */



print_preliminary_message();

/* prompt the user for table specifications in Fahrenheit: */

input_table_specifications(lower, upper, step);

/* print appropriate message including an echo of the input: */

print_message_echoing_input(lower, upper, step);

/* Print the table (including the column headings): */

print_table(lower, upper, step);

 

return 0;



}

/* END OF MAIN PROGRAM */

 

/* FUNCTION TO CONVERT FAHRENHEIT TO CELSIUS */



double celsius_of(int fahr)

{

return (double(5)/9) * (fahr - 32);



}

/* END OF FUNCTION */

 

/* FUNCTION TO CONVERT FAHRENHEIT TO ABSOLUTE VALUE */



double absolute_value_of(int fahr)

{

return ((double(5)/9) * (fahr - 32)) + 273.15;



}

/* END OF FUNCTION */

Uitvoer naar het scherm:

This program prints out a conversion table of temperatures.

Enter the minimum (whole number) temperature

you want in the table, in Fahrenheit: 0

Enter the maximum temperature you want in the table: 100

Enter the temperature difference you want between table entries: 20

Tempertature conversion table from 0 Fahrenheit

to 100 Fahrenheit, in steps of 20 Fahrenheit:

 

Fahrenheit Celsius Absolute Value



0 -17.78 255.37

20 -6.67 266.48

40 4.44 277.59

60 15.56 288.71

80 26.67 299.82

100 37.78 310.93

 

 

Opdracht 4: Statistiek


 

Werk op een gelijkaardige manier als de vorige opdracht, maar maak nu een programma die het gemiddelde en standaard deviatie van een reeks getallen berekent.

 

Std.dev (als a = gemiddelde):

sqrt( (x1-a)2 + (x2-a)2 + … (xn-a)2 ) //sqrt is vierkantswortel

 

De functies sqrt( ..) en machtverheffing pow( base, exponent ) zijn bestaande functies in C++: includeer hiervoor bovenaan het programma.



 

#include

 

 

How many numbers do you wish to enter: 3



Enter first value: 5

Enter second value: 7

Enter third value: 9

Average: 7. Standard deviation: 1.63299.



 

 

 



De database wordt beschermd door het auteursrecht ©opleid.info 2017
stuur bericht

    Hoofdpagina