

\section{Gebruik van functies in C}
\subsection{Inleiding}
We hebben in de {\sl voorbeeld}-programmas al eens 
kennis gemaakt met het gebruik/de aanroep van 
{\sl functies} .
\begin{itemize}
\item Sommige functies werden door de C-compiler {\sl meegeleverd},
      zoals :
\begin{verbatim}
    printf(" geef de waarden van de getallen a,b,c\n");
    scanf ("%f %f %f", &a, &b, &c);

    wortel = sqrt ( a*b)      ;

    valint = pow (a, 3.) + pow (b, 3.) ;
\end{verbatim}
\end{itemize}

Aan deze voorbeelden kunt U een aantal dingen {\sl zien} :
\begin{itemize}
\item {\bf Alle} functie-aanroepen worden gevolgd door $(\;)$
      Dit is {\bf noodzakelijk} om er voor te zorgen dat de 
      compiler 'begrijpt' dat het om een functie-aanroep gaat.
\item Tussen de $(\;)$ staan de {\sl parameters} waarmee 
      de functie wordt aangeroepen. Dit aantal kan per functie 
      {\sl verschillen}. De parameterlijst kan zelfs {\sl leeg} 
      zijn.
\item Alle functies {\sl doen} (uiteraard) iets, maar er zijn 
      belangrijke {\sl verschillen} :
\begin{itemize}
\item {\sl printf} levert (in dit geval) alleen een geprinte tekst, 
      maar u kunt er ook de {\sl waarde} van variabelen mee uitprinten.
\item {\sl scanf} leest (in dit geval) drie getallen in, en zet de waarden in 
      de variabelen die U 'a, b, en c' hebt genoemd; de {\sl volgorde}
      is relevant.
\item {\sl sqrt} trekt de wortel uit het getal dat in de 
      parameterlijst staat, en stelt het resultaat ter beschikking 
      {\sl via de functie-naam}, zodat U het direct in een expressie 
      kunt gebruiken. 
\item {\sl pow} gebruikt de twee parameters voor 'machtsverheffen', en 
      stelt het resultaat ter beschikking {\sl via de functie-naam}. 
      De {\sl volgorde} van de parameters is relevant.
\item In de functie {\sl gpl\_data} worden de parameters  
      {\sl gebruikt} om een grafiek te tekenen. Hun waarde wordt 
      {\sl niet veranderd}. Ook wordt er {\sl geen resultaat 
      teruggeven}.\\
      Het {\sl aantal} en de {\sl volgorde} van de parameters is relevant 
      :U moet zich houden aan 'wat de functie verwacht'. \\
      Ook het {\sl type} van de parameters is relevant. 
\begin{itemize}
\item de eerste is een 'enkele' variabele van het type 'int'
\item de tweede en derde zijn 'arrays' van het type 'float'
\item de vierde is een 'character string'.
\end{itemize}
      Ook hier moet U zich houden aan wat de functie verwacht !
\item {\sl gpl\_show} vertoont de aangemaakte grafiek in een window.
      er is {\sl geen parameter} nodig, er is {\sl geen functieresultaat}.
\end{itemize}
\end{itemize}


\subsection{Het nut van functies}
\begin{itemize}
\item Bovenstaande voorbeelden tonen minstens een {\sl nuttig} aspect 
      van het gebruik van functies : er is {\sl 1 stuk C-code} waarmee 
      U {\sl herhaalde malen} een bepaalde taak kunt laten uitvoeren, 
      toegepast op {\sl wisselende} (sets) parameters. 
\item Een {\sl tweede} belangrijk voordeel is dat U door het gebruik van 
      functies Uw code {\sl in kleine modules} kunt inrichten, ieder 
      met een {\sl eigen taak}. Dit bevordert de overzichtelijkheid en 
      de hanteerbaarheid van uw code, en verkleint daarmee de kans op 
      'fouten'.
\end{itemize}

\subsection{Functies zonder parameter en zonder return-waarde}
Een voorbeeld-programma (file 'ex6.c') :
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

void mijnprint (void) ;      /* prototype van de functie */

int main (void)
{
   mijnprint () ;            /* aanroep van de functie   */
   return 0 ;
}
void mijnprint (void)        /* inhoud van de functie    */
{
   printf(" mijnprint is aangeroepen\n") ;
   return ;
}
\end{verbatim}



Toelichting :
\begin{itemize}
\item Wanneer U functies gebruikt in Uw programma, moet U 
      {\sl voordat} de 'echte' code begint al iets 
      vertellen over die functies, via het zgn. {\sl prototype}.
      In 
\begin{verbatim}
void mijnprint (void) ;      /* prototype van de functie */
\end{verbatim}
      'kondigt U aan' dat U (verderop) een functie gaat maken 
\begin{itemize}
\item met de {\sl naam} 'mijnprint'
\item met een {\sl lege} parameter-lijst (de 'void' rechts)
\item {\sl zonder return}-waarde (de 'void' links)
\end{itemize}
      Merk op dat de prototype declaratie wordt afgesloten met een 
      {\sl punt-komma}.
\item De {\sl aanroep} van de functie vindt plaats in 
\begin{verbatim}
   mijnprint () ;            /* aanroep van de functie   */
\end{verbatim}
      Merk op 
\begin{itemize}
\item dat deze aanroep een {\sl lege} parameterlijst heeft
\item dat {\sl geen} return-waarde wordt verwacht
\end{itemize}
      Dit {\sl klopt} dus met het 'prototype.
\item De code van de functie zelf {\sl begint} met 
\begin{verbatim}
void mijnprint (void)        /* inhoud van de functie    */
\end{verbatim}
      daarin komt weer terug : de {\sl naam}, de {\sl lege} 
      parameterlijst, en het feit dat de functie {\sl geen 
      return}-waarde heeft. \\
      Merk op dat hier {\sl geen} punt-komma in voorkomt !
\item De {\sl inhoud} van de functie wordt {\sl ingesloten} 
      tussen $\;\{\;\;\;\}$
\item De functie wordt {\sl afgesloten} met 
\begin{verbatim}
   return ;
\end{verbatim}
\end{itemize}


\subsection{Functies met parameter en zonder return-waarde}
Een voorbeeld-programma (file 'ex7.c'):
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

void mijnprint (int) ;      /* prototype van de functie */

int main (void)
{
   mijnprint (10) ;         /* aanroep van de functie   */
   return 0 ;
}
void mijnprint (int getal)  /* inhoud van de functie    */
{
   printf(" mijnprint is aangeroepen met %d\n",getal) ;
   return ;
}
\end{verbatim}


Toelichting :
\begin{itemize}
\item In het {\sl prototype}
\begin{verbatim}
void mijnprint (int) ;      /* prototype van de functie */
\end{verbatim}
      'kondigt U aan' dat U (verderop) een functie gaat maken 
\begin{itemize}
\item met de {\sl naam} 'mijnprint'
\item met {\sl een} parameter \\
      het {\sl type} van de parameter is 'int' \\
      de parameter is een {\sl enkele} variabele (geen array)
\item de functie heeft {\sl geen} return-waarde
\end{itemize}
\item De {\sl aanroep} van de functie vindt plaats in 
\begin{verbatim}
   mijnprint (10) ;            /* aanroep van de functie   */
\end{verbatim}
      Merk op 
\begin{itemize}
\item dat deze aanroep {\sl een} parameter heeft, van het type 
      zoals aangegeven in het {\sl prototype}
\item dat {\sl geen} return-waarde wordt verwacht
\end{itemize}
\item De code van de functie zelf {\sl begint} met 
\begin{verbatim}
void mijnprint (int getal)        /* inhoud van de functie    */
\end{verbatim}
\begin{itemize}
\item daarin komt weer terug : de {\sl naam},  
      en het feit dat de functie {\sl geen 
      return}-waarde heeft. 
\item bovendien wordt aangegeven dat de functie {\sl een} 
      parameter heeft, van het {\sl type} 'int', en dat het 
      geen array is.
\item bovendien wordt aangegeven dat we {\sl binnen} de 
      functie, voor de parameter de {\sl naam} 'getal' 
      zullen gebruiken.
\end{itemize}
\item De {\sl inhoud} van de functie wordt {\sl ingesloten} 
      tussen $\;\{\;\;\;\}$ \\ Merk op dat daar de variabele 
      met de naam 'getal' inderdaad wordt gebruikt.
\item De functie wordt {\sl afgesloten} met
\begin{verbatim}
   return ;
\end{verbatim}
\end{itemize}

\subsubsection{Opdracht 6}
Maak een programma die een functie fibonacci bevat: $1,1,2,3,5,8,13......$. De functie het als input parameter
het aantal stappen $nmax$ dat je in de for-loop moet doorlopen. Print uiteindelijk de verhouding
tussen het laatste en het voorlaatse getal. Dat zou de zogenaamde Gulden Snede moeten opleveren van
$(1+\sqrt{5})/2=1.618$.




\subsection{Functies met parameter en met return-waarde}
Een voorbeeld-programma (file 'ex8.c'):
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

float kwadraat (float) ;     /* prototype van de functie */

int main (void)
{
   float x = -1.0, xkwad ;

   xkwad = kwadraat (x) ;    /* aanroep van de functie   */

   printf ("het kwadraat van %f = %f \n", x, xkwad) ;

   return 0 ;
}
float kwadraat (float getal)  /* inhoud van de functie    */
{
   float x2 ;

   x2 = getal * getal ;

   return x2 ;
}
\end{verbatim}



Toelichting :
\begin{itemize}
\item In het {\sl prototype}
\begin{verbatim}
float kwadraat (float) ;     /* prototype van de functie */
\end{verbatim}
      'kondigt U aan' dat U (verderop) een functie gaat maken 
\begin{itemize}
\item Met de {\sl naam} 'kwadraat'
\item met {\sl een} parameter \\
      het {\sl type} van de parameter is 'float' \\
      de parameter is een {\sl enkele} variabele (geen array)
\item de functie heeft een return-waarde, en wel van het 
      {\sl type float}.
\end{itemize}
\item De {\sl aanroep} van de functie vindt plaats in 
\begin{verbatim}
   xkwad = kwadraat (x) ;    /* aanroep van de functie   */
\end{verbatim}
      Merk op 
\begin{itemize}
\item dat deze aanroep {\sl een} parameter heeft, van het type 
      zoals aangegeven in het {\sl prototype}
\item dat een return-waarde wordt verwacht (die vervolgens 
      wordt toegekend aan de variabele 'xkwad')
\end{itemize}
\item De code van de functie zelf {\sl begint} met 
\begin{verbatim}
float kwadraat (float getal)  /* inhoud van de functie    */
\end{verbatim}
\begin{itemize}
\item daarin komt weer terug : de {\sl naam},  
      en het feit dat de functie een 
      {\sl return}-waarde heeft van het {\sl type} 'float'. 
\item bovendien wordt aangegeven dat de functie {\sl een}
      parameter heeft, van het {\sl type} 'float', en dat het
      geen array is.
\item bovendien wordt aangegeven dat we {\sl binnen} de 
      functie, voor de parameter de {\sl naam} 'getal' 
      zullen gebruiken.
\end{itemize}
\item De {\sl inhoud} van de functie wordt {\sl ingesloten} 
      tussen $\;\{\;\;\;\}$ \\Merk op dat daar de variabele 
      met de naam 'getal' inderdaad wordt gebruikt.
\item de opdracht 
\begin{verbatim}
   return x2 ;
\end{verbatim}
      zorgt er voor dat de waarde van 'x2' als {\sl retourwaarde} 
      van de functie wordt 'teruggeven'.
\end{itemize}


\subsection{Array als parameter}
Het is ook mogelijk om een {\sl array} als parameter in een 
functie te gebruiken, zoals in het volgende voorbeeld (file 'ex9.c')
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

int mijnsom( int [], int) ;         /* prototype van de functie */

int main (void)
{
   int a[10] = {0,1,2,3,4,5,6,7,8,9} ;
   int som ;

   som = mijnsom (a, 10) ;             /* aanroep van de functie */
   printf(" de som is %d\n", som) ;

   return 0 ;
}
int mijnsom (int reeks[], int lengte )  /* inhoud van de functie */
{
   int i, telop = 0 ;

   for (i=0; i<lengte; i=i+1)
   {
      telop = telop + reeks [i] ;
   }

   return telop ;                       /* resultaat van de functie */
}
\end{verbatim}



Toelichting :
\begin{itemize}
\item In het {\sl prototype}
\begin{verbatim}
int mijnsom( int [], int) ;         /* prototype van de functie */
\end{verbatim}
      'kondigt U aan' dat U (verderop) een functie gaat maken 
\begin{itemize}
\item met de {\sl naam} 'mijnsom'
\item met {\sl twee} parameters 
\begin{itemize}
\item het {\sl type} van de eerste parameter is 'int' en het is 
      een array (aangegeven door de $\;[\;]\;$)
\item het {\sl type} van de tweede parameter is 'int' en het is 
      een 'enkelvoudige' variabele (geen array).
\end{itemize}
\item de functie heeft {\bf een enkele} return-waarde van het {\sl type} int
\end{itemize}
\item De {\sl aanroep} van de functie vindt plaats in 
\begin{verbatim}
   som = mijnsom (a, 10) ;             /* aanroep van de functie */
\end{verbatim}
      Merk op 
\begin{itemize}
\item dat deze aanroep {\sl twee} parameters heeft, van het type 
      zoals aangegeven in het {\sl prototype}
\item dat de parameter 'a' {\bf niet} wordt gevolgd door $\;[\;]\;$
\item dat een return-waarde wordt verwacht
\end{itemize}
\item De code van de functie zelf {\sl begint} met 
\begin{verbatim}
int mijnsom (int reeks[], int lengte )  /* inhoud van de functie */
\end{verbatim}
Het enige {\sl verschil} met het prototype is (weer) dat de beide parameters 
nu ook een {\sl naam} hebben gekregen, zodat ze 'binnen' de functie 
kunnen worden gebruikt.
\item De {\sl inhoud} van de functie wordt {\sl ingesloten}
      tussen $\;\{\;\;\;\}$ \\Merk op dat daar de variabelen
      met de naam 'reeks' en 'lengte' inderdaad worden gebruikt.
\item de opdracht
\begin{verbatim}
   return telop ;
\end{verbatim}
      zorgt er voor dat de waarde van 'telop' als {\sl retourwaarde}
      van de functie wordt 'teruggeven'.
\end{itemize}



\subsection{Functie resultaten in een array-parameter}
Het kan voorkomen dat het {\sl resultaat} van de berekeningen in een 
functie niet {\sl een enkel getal} is, dat U via de functie-aanroep 
kun teruggeven, maar een {\sl reeks van getallen in een array}. \\
In dat geval kunt U het resultaat 'teruggeven' {\sl via de 
parameter-lijst}, zoals in het voorbeeld hierna (file 'ex10.c').
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

void mijncop( float [], float [], int) ; /* prototype van de functie */

int main (void)
{
   float a[10] = {0.,1.,2.,3.,4.,5.,6.,7.,8.,9.} ;
   float b[10] ;
   int i ;

   mijncop ( a, b, 10 ) ;              /* aanroep van de functie */
   for(i=0; i<10; i=i+1)
   {
      printf(" i=%2d  a[i]=%5f  b[i]=%5f\n", i, a[i], b[i] ) ; 
   }

   return 0 ;
}
void mijncop (float orig[], float copie[], int l)  /* inhoud van de functie */
{
   int i ;

   for (i=0; i<l; i=i+1)
   {
      copie[i] = orig[i] ;
   }

   return ;                       
}
\end{verbatim}


Toelichting :
\begin{itemize}
\item In het {\sl prototype}
\begin{verbatim}
void mijncop( float [], float [], int) ; /* prototype van de functie */
\end{verbatim}
      'kondigt U aan' dat U (verderop) een functie gaat maken
\begin{itemize}
\item met de {\sl naam} 'mijncop'
\item met {\sl drie} parameters
\begin{itemize}
\item het {\sl type} van de eerste twee parameters is 'float' en het 
      zijn arrays (aangegeven door de $\;[\;]\;$)
\item het {\sl type} van de derde parameter is 'int' en het is
      een 'enkelvoudige' variabele (geen array).
\end{itemize}
\item de functie heeft {\bf geen} {\sl return-waarde} via de functie-naam.
\end{itemize}
\item De {\sl aanroep} van de functie vindt plaats in
\begin{verbatim}
   mijncop ( a, b, 10 ) ;              /* aanroep van de functie */
\end{verbatim}
      Merk op
\begin{itemize}
\item dat deze aanroep {\sl drie} parameters heeft, van het type
      zoals aangegeven in het {\sl prototype}
\item dat de parameters 'a' en 'b' {\bf niet} wordt gevolgd door $\;[\;]\;$
\item dat geen return-waarde wordt verwacht
\end{itemize}
\item De code van de functie zelf {\sl begint} met
\begin{verbatim}
void mijncop (float orig[], float copie[], int l)  /* inhoud van de functie */
\end{verbatim}
Het enige {\sl verschil} met het prototype is (weer) dat de parameters
nu ook een {\sl naam} hebben gekregen, zodat ze 'binnen' de functie
kunnen worden gebruikt.
\item De {\sl inhoud} van de functie wordt {\sl ingesloten}
      tussen $\;\{\;\;\;\}$
\item de opdracht
\begin{verbatim}
   return ;
\end{verbatim}
      sluit de functie af, op de manier zoals 'hoort' bij een void function.
\end{itemize}


\subsection{Functieresultaten in een (enkelvoudige) parameter}
Deze sectie over pointers en adressen van variabelen is uiterst belangrijk.
\begin{itemize}
\item U zou misschien verwachten dat het {\sl teuggeven} van een functie-
      resultaat via een {\sl enkelvoudige} parameter (geen array) op 
      eenvoudige wijze kan worden 'afgeleid' uit het voorbeeld in de vorige 
      sectie, nl. door het weglaten van de $\;[\;]\;$.
      Dit is echter {\bf niet} het geval.
\item De reden daarvan is dat de compiler in het geval van een enkelvoudige 
      parameter, bij aanroep van de functie, de {\sl waarde} van de parameter 
      'doorgeeft' , en {\sl niet} het {\sl adres} van de lokatie in het 
      geheugen, waar de waarde van de parameter wordt bewaard. \\
      Zolang in de functie {\sl alleen de waarde} wordt gebruikt, gaat het 
      goed. Maar een berekende waarde {\sl teruggeven} {\bf kan niet}, 
      althans niet op deze manier.
\item Teruggeven van een berekende waarde {\sl kan wel} op de manier, 
      zoals aangegeven in het volgende {\sl voorbeeld}. Daarbij wordt 
      gebruik gemaakt van {\sl pointers}, die vanuit de {\sl waarde} van 
      een parameter {\sl verwijzen} naar het {\sl adres} van zijn 
      locatie in het geheugen.
\end{itemize}
Zie file 'ex13.c'.
\begin{verbatim}
/* de code staat in de directory 'labwindows' */ 
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

void mijncop( float, float *) ; /* prototype van de functie  */
                                /* let op * bij 2e parameter */
int main (void)
{
   float a = 10.;
   float b =  0.;

   mijncop ( a, &b) ;            /* aanroep van de functie    */
                                 /* let op & bij 2e parameter */
   
   printf(" a=%5f  b=%5f\n", a, b) ; 

   return 0 ;
}
void mijncop (float orig, float *copie)  /* inhoud van de functie */
                                     /* let op * bij 2e parameter */
{
   *copie = orig ;                   /* let op *copie             */

   return ;                       
}
\end{verbatim}




Merk op :
\begin{itemize}
\item Bij de {\sl aanroep} van de functie, in 
\begin{verbatim}
   mijncop ( a, &b) ;            /* aanroep van de functie    */
\end{verbatim}
      zorgt de '\&b' er voor dat het {\sl adres} van de parameter wordt 
      doorgegeven, in plaats van de waarde.
\item Maar de functie moet dit natuurlijk ook 'weten', zowel via 
      het 'prototype', als via de functie-'aanhef'. Het * bij de tweede 
      parameter 'zorgt' daarvoor, in :
\begin{verbatim}
void mijncop( float, float *) ; /* prototype van de functie  */
void mijncop (float orig, float *copie)  /* inhoud van de functie */
\end{verbatim}
\item Dit * bij de parameter-naam moet ook gebruikt worden, als U een 
      waarde in de parameter {\sl invult}, zoals in 
\begin{verbatim}
   *copie = orig ;                   /* let op *copie             */
\end{verbatim}
\end{itemize}



Denk erom: je mag nooit iets
lezen/schrijven uit/naar een pointer die niet geinitialiseerd is, dus:
\begin{verbatim}
float * aap;
*aap=0;
\end{verbatim}
Dit is een 'dodelijk' statement om de pointer aap nog nergens naar wijst, terwijl je op deze plek een nul probeert te schrijven.
Wat wel kan is:
\begin{verbatim}
float * aap;
float noot;
aap=&noot;  // aap bevat nu adres van noot
*aap=0;     // op het adres van noot wordt nu een nul geschreven.
\end{verbatim}
 De float noot bevat nu de waarde 0. Immers, eerst is de pointer aap op het adres van noot gezet. En daarna is op die locatie een nul geschreven.
Het equivalent van dit omslachtig stukje code is dus gewoon: 'float noot=0;'. Niet meer en niet minder.

 



\subsubsection{Opdracht 7}
Maak nu een programma dat een functie bevat die de ABC formule bevat om een tweedegraads vergelijking
op te lossen: $a x^2 + b x + c =0$. De vijf parameters van de functie input van de functie
zijn a,b,c  en de output ans1 en ans2. Ook moet de functie integer waarde teruggeven die nul is als alles
goed is gegaan en een andere waarde als er ene probleem is opgetreden, waardoor ans1 en ans2 niet berekend zijn.
Dus iets als: \\
int ABC(float a, float b, float c, float *ans1, float* ans2)


Print ans1 en ans2 in het hoofdprogramma (na aanroep van de functie ABC) en controleer of de functie doet wat er
er wordt verwacht.




\subsection{Communicatie via globale variabelen}
Communicatie met globale variabelen is af te raden, omdat het in grote programma's tot problemen
kan leiden. Voor kleine programma's is het echter wel de snelste en gemakkelijkste methode, maar toch
is het niet aan te raden van globale variabelen gebruik te maken.
In de voorgaande secties werd de {\sl communicatie} tussen hoofdprogramma 
en functies 'geregeld' via de {\sl parameter-lijst} en eventueel de 
{\sl return-waarde} van de functie. \\
Een {\sl andere manier} van communicatie is via {\sl globale variabelen}.
\subsubsection{Lokale variabelen}
\begin{itemize}
\item  We hebben al eerder gezien dat variabelen worden gedefinieerd via een 
       {\sl type declaratie} ; daarbij wordt ook aangegeven of het een 
       {\sl enkelvoudige} variabele is, of een {\sl array}.
\item  In al onze voorbeelden (tot nu toe) vond de type-declaratie plaats 
       {\sl binnen} het hoofdprogramma of {\sl binnen} de functies,
       dwz {\sl binnen} de bijbehorende set $\;\{\;\;\;\}$
\item  Het gevolg daarvan is dat de variabelen {\bf alleen} 'betekenis' 
       hebben {\sl binnen} het hoofdprogramma of {\sl binnen} de functie, 
       waarin ze worden gedeclareerd,
       {\sl zelfs als je dezelfde 'namen'} gebruikt. 
\item  Een voorbeeld daarvan is het volgende programma (file 'ex11.c').
\end{itemize}
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

void zomaar() ;                    /* prototype van de functie */

int main (void)
{
   int iks ;

   iks = 0   ;
   zomaar () ;                     /* aanroep van de functie */
   printf(" de waarde van iks in het main program = %d\n", iks ) ; 

   return 0 ;
}
void zomaar (void)                 /* inhoud van de functie */
{
   int iks ;

   iks = 1 ;
   printf(" de waarde van iks in de functie = %d\n", iks ) ; 

   return ;                       
}
\end{verbatim}



Als U dit programma executeert, krijgt U de volgende printout :
\begin{verbatim}
 de waarde van iks in de functie = 1
 de waarde van iks in het main program = 0
\end{verbatim}
Blijkbaar is de variable 'iks' in de functie {\sl een andere} als 
in het main program. \\
In feite krijgen ze van de compiler gewoon {\sl verschillende 
locaties} in het 'geheugen' toegekend.

\subsubsection{Globale variabelen}
De situatie wordt {\sl heel anders} wanneer U de type declaratie 
{\sl niet binnen} de $\;\{\;\;\;\}$ van het main program of een 
functie doet, maar {\sl daarbuiten}, en wel 'ergens aan het begin', 
(voordat de variabele wordt 'gebruikt'), zoals in het volgende voorbeeld (file 'ex12.c')
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */

#include <stdio.h>

int iks ;                          /* GLOBALE variabele        */

void zomaar() ;                    /* prototype van de functie */

int main (void)
{                                  /* iks wordt NIET (opnieuw) gedeclareerd */
   iks = 0   ;
   zomaar () ;                     /* aanroep van de functie */
   printf(" de waarde van iks in het main program = %d\n", iks ) ; 

   return 0 ;
}
void zomaar (void)                 /* inhoud van de functie */
{                                  /* iks wordt NIET (opnieuw) gedeclareerd */
   iks = 1 ;
   printf(" de waarde van iks in de functie = %d\n", iks ) ; 

   return ;                       
}
\end{verbatim}



Als U dit programma executeert, krijgt U de volgende printout :
\begin{verbatim}
 de waarde van iks in de functie = 1
 de waarde van iks in het main program = 1
\end{verbatim}
Blijkbaar is de variable 'iks' in de functie nu {\sl dezelfde} als
in het main program. \\
In feite krijgt een globale variabele van de compiler {\sl een enkele locatie}
in het 'geheugen' toegekend; zowel het main program als de functies 
krijgen {\sl toegang} tot deze locatie.
\begin{verbatim}

\end{verbatim}
Enige {\sl voorzichtigheid} is geboden :
\begin{itemize}
\item  Als U een variabele op deze manier 'globaal' maakt, mag U 
       hem in de functie {\sl niet nog eens} declareren (anders gaat 
       het alsnog mis).
\item  De globale variable is (in zekere zin) {\sl onbeschermd} : 
       U kunt hem 'vanuit elke plek' {\sl overschrijven}. Maar : 
       zolang Uw programma niet al te groot is, is de kans hierop klein 
       (als U goed oplet), en kan het gebruik van globale variabelen 
       een handig {\sl alternatief} zijn voor communicatie tussen 
       de verschillende delen van Uw programma.
\item  Dit laatste is vooral handig als U in de functie {\sl meerdere} 
       getallen wilt laten berekenen/teruggeven, die {\sl niet} samen 
       {\sl in een array} staan. 
\begin{itemize}
\item  'Teruggeven' van deze getallen via de 
       functienaam kan niet (het zijn er meer dan een).  
\item  'Teruggeven' via de parameterlijst {\sl kan wel}, maar dan moet 
       U {\sl pointers} gebruiken.
\end{itemize}
\end{itemize}



\section{Nog enkele 'handige zaken'}
\subsection{Gebruik van   \#define}
\begin{itemize}
\item  We pakken een 'oud' voorbeeld, waarin een array met lengte {\sl 10} 
       wordt gevuld met de getallen 1 t/m {\sl 10} :
\begin{verbatim}
#include <stdio.h>
int main (void)
{
    int nummer [10] ;
    int i ;
    for ( i=0; i<10; i=i+1 )
    {
       nummer [i] = i+1 ;
       printf(" element %d van array nummer bevat %d \n", i, nummer[i]);
    }
    return 0 ;
}
\end{verbatim}
\item  Stel dat U dit programma wilt veranderen zodat een array met lengte 
       {\sl 100} wordt gevuld met de getallen 1 t/m {\sl 100}, dan moet 
       U het programma {\sl op twee plaatsen} wijzigen. Als U een plaats 
       {\sl vergeet}, dan gaat het mis. \\
       In het volgende programma wordt dat ondervangen :
\begin{verbatim}
#include <stdio.h>

#define lengte 10                 /* hier wordt 'lengte' gedefinieerd */

int main (void)
{
    int nummer [lengte] ;         /* gebruik 'lengte'                 */
    int i ;

    for ( i=0; i<lengte; i=i+1 )  /* gebruik 'lengte'                 */
    {
       nummer [i] = i+1 ;
       printf(" element %d van array nummer bevat %d \n", i, nummer[i]);
    }

    return 0 ;
}
\end{verbatim}
\item  Overigens moet U zich realiseren dat hier {\sl niet} een variabele
       wordt gedefinieerd met de naam 'lengte' en waarde '10'. Wat er wel 
       gebeurt is het volgende : \\
       de {\sl preprocessor} die uw code behandelt voordat de echte compilatie 
       begint, {\sl vervangt} in Uw code overal het de {\sl tekst} 'lengte' 
       door de {\sl tekst} '10' . 
\end{itemize}



\subsection{Het gebruik van de 'break'-opdracht}
Soms is het handig/nodig om een loop ( for of while ) {\sl tussentijds} 
af te breken. Het volgende programma {\sl test} Uw vermogen om gehele 
getallen (kleiner dan 100) te kwadrateren. Het programma {\sl stopt} 
zodra U een fout maakt (file 'ex15.c'). 
\begin{verbatim}
/* de code staat in de directory 'labwindows' */
/* onder http://www.nikhef.nl/user/h73/ccursus.html */
/* de code zit ook in de voorbeeld workspace voor labwindows */


#include <stdio.h>

int main (void)
{
    int getal, kwadraat ;

    for ( getal=0; getal<100; getal=getal + 1) 
    {
       printf(" geef het kwadraat van %d \n ", getal) ;
       scanf ("%d", &kwadraat) ;

       if ( kwadraat != getal * getal ) 
       {    
           printf (" resultaat is fout bij het kwadraat van %d \n", getal) ;
           break ; /* stop zodra er een fout is gemaakt                   */
       }
    }

    return 0 ;
}
\end{verbatim}
\begin{itemize}
\item  In de for-loop worden de getallen in opklimmende volgorde 
       aan U aangeboden. 
\item  In het if-statement wordt gekeken of Uw antwoord goed is.
\item  Zodra U een fout maakt wordt Uw prestatie geprint, en wordt 
       de for-loop {\sl verlaten} 
\end{itemize}


\subsubsection{Opdracht 8}
Herschrijf je ABC formule van de vorige opdracht zodat er alleen maar pointers in de parameterlijst staan.
Als dat gelukt is, kun je ook nog een pointer (int *) als return waarde programmeren.  (Meer voorbeelden m.b.t. pointers enzo staan
in het project 'pointersenzo'.)


Volgend jaar bij 'Numerieke Natuurkunde' bouwwen we voort op de kennis die je bij deze cursus hebt opgedaan en gaan
we ons meer richten op natuurkundige problemen die we numeriek op gaan lossen. 


\section{LabWindows specifiek}
In het laatste deel van deze cursus gaan we ons alvast verdiepen in LabWindows specifieke functies, zodat jullie bij het
volgende praktikum goed beslagen ten ijs komen.

Een voorbeeld van LabWindows zijn we tegengekomen bij het plotten van een grafiek met de functie 
 'XYGraphPopup' in Sectie~\ref{grafisch}. Deze functie zit standaard in Labwindow en we zullen in deze sectie door de stappen gaan
waarmee we deze functie hebben ingebracht in onze code.

\begin{itemize}
\item maak een nieuw project en hang daarin een nieuwe C file. Zie eventueel Sectie~\ref{project}. Begin een main programma dat nog niets doet, zoiets als in hello.c.
\item In je labwindows scherm zie je in het scherm linksonderin 'Library' staan die je kunt aanklikken en verder uitvouwen. (Dit kan ook via het menu 'Library').
Klik vervolgens op 'User Interface library' en ga verder naar 'PopUp panels$->$Graph PopUps' en dubbelklik op 'XYGraphPopUp'.
Er verschijnt een grafisch userinterface. Vul hier naar eigen inzicht redelijk namen in, bijvoorbeeld:
\begin{itemize}
\item Title-veld: 'mijn plotje'  (willkeurige naam)
\item X-Array-veld: 'xwaarden' (de naam van de array die je zal gaan gebruiken voor de $x$ waarden).
\item Y-Array-veld: 'ywaarden'
\item Number-of-Points-veld: de lengte van de array's die je gaat gebruiken.
\item X-Data-Type-veld: we werken meestal met float's, dus kies 'floating point'
\item Y-Data-Type-veld: idem.
\item Status-veld: dit is de eventuele return waarde van de functie, een integer met willekeuruge naam: 'err' ofzo. Die moet overigens nul zijn
na aanroep, anders is er een fout opgetreden.
\end{itemize}
\item Op de gewone menu-balk is een extra optie 'Code' ontstaan, klik daarop en kies 'Set Target File' en zet deze op jouw nieuwe file.
\item Vervolgens ook in menu 'Code', kies 'Insert Function Call' en nu heb je de functie in je code beschikbaar!
\item vul je X-array en Y-array maar eens en roep de functie aan.
\end{itemize}


En nu gaan we hetzelfde doen met interactief paneel, maar daarvoor gebruiken we de officiele Labwindows manual, Hoofdstuk 5 in 


 http://www.nikhef.nl/\~{ }h73/docu\_labwindows.pdf

Volg de aanwijzingen en maak een mooi interactief panel.

