Uitwerkingen opgaven Programmeermethoden, najaar 2020 - opgaven 14/22 Opgave 14 int main ( ) { const char afsluiter = ';'; // afsluitend karakter char karakter; // het ingelezen lettertje int expressie = 0, // waarde van de expressie getal, // waarde van het getal teken; // teken van het getal cout << "Geef expressie .. "; karakter = cin.get ( ); while ( karakter != afsluiter ) { if ( karakter == '-' ) teken = -1; else // een + blijkbaar teken = 1; karakter = cin.get ( ); // eerste cijfer van getal getal = 0; while ( ( '0' <= karakter ) && ( karakter <= '9' ) ) { getal = 10 * getal + karakter - '0'; karakter = cin.get ( ); } // while expressie = expressie + teken * getal; // of expressie += ... } // while cout << "Expressie evalueert naar " << expressie << endl; return 0; } // main Opgave 15 double sommetje (int n) { int teller, // teller van teller-de term noemer = 1; // en de noemer daarvan double som = 0; // de (deel)som for ( teller = 1; teller <= n; teller++ ) { noemer *= 2; som += (double) teller/noemer; // denk aan de "typecast" } // for return som; } // sommetje int main ( ) { int n; // aantal termen cout << "Geef aantal termen .. "; cin >> n; cout << "De som is: " << sommetje (n) << endl; return 0; } // main Het is verstandiger -zie Numerieke wiskunde- om met de laatste (kleinste) term te beginnen: het afronden pakt dan beter uit. Helaas moet dan eerst 2 tot de n-de worden uitgerekend ... Opgave 16 Het linker programma levert 2, 2 en daarna 2. Het rechter programma levert 105, 105 en daarna 105. Zonder & wordt dit -1, 2 en 1, respectievelijk 105, 10 en 10. Opgave 17 Eigenlijk maakt de functie alleen zijn tweede variabele 6. a. Afgedrukt worden: 1, 6 en 3. b. En nu: 6, 2 en 3. c. En nu: 1, 2 en 6. d. Op de plek van een var-parameter (call by reference) mag geen getal staan: hier moet een l-value, zeg maar een variabele, staan. Een foutmelding dus, en wel een die bij het compileren ontdekt wordt: een "compile-time-error". e. Afgedrukt worden: 6, 2 en 3. Opgave 18 a. 3, 96, 19, 97, 6, 16 b. int G (int a, int b) { return (a-2)*(a+b+2) + 1; } // G c. Stel dat eerst f (a,b) wordt geevalueerd. Uitkomst 76, en a (oftewel x) is nu 4. Dan f (a,a), geeft 9, en a (dus ook x) is nu 3. Dat levert: 3, 85, 19, 86, 85, 19. Met eerst f (a,a) wordt dit: 3, 73, 19, 74, 73, 19. Het antwoord hangt af van de volgorde van optelling, die in C++ niet vastligt. Opgave 19 a. Eerste peter (p,q) geeft 8, de tweede 16. TWEE doorgangen door de for-loop. 4 27 4 35 2 6 b. Nu geeft peter (p,q) weer 8, en laagt q met 1 af; dus maar EEN doorgang door de for-loop. 3 11 3 17 11 3 Overigens levert cout << ellen (a,b) << a << b << endl; nog de oude waardes van a en b, dus 2 en 6. Dat komt omdat bij cout (in ieder gaval onder g++) van rechts naar links ge-evalueerd wordt. De uitvoer 3 11 3 17 11 3 wordt geleverd door: cout << ellen (a,b); cout << a << b << endl; c. Eerste p = p+...: p wordt 10 of 11 De tweede: p wordt 26 of 24, OF 27 of 25: de beide optellingen zouden in principe anders kunnen verlopen! Na afloop: a is 24 of 25 of 26 of 27. Het antwoord hangt dus af van de volgorde van optelling, die in C++ niet vastligt. Opgave 20 Overigens zit in cmath ook de functie pow. Nodig zijn de functies exp en log uit cmath: double macht (double x, double y) { // bereken x**y = e**log(x**y) = e**(y*log(x)), waarbij ** // machtsverheffen betekent return exp (y * log(x)); } // macht int macht (double x, int y) { // overloading! int k; // tellertje double z = 1; // voor x**k for ( k = 1; k <= y; k++ ) z *= x; return z; } // macht Opgave 21 F is een functie met een neveneffect (side effect): de meegegeven variabele verandert. De waarde van de expressie x + F(x) hangt er van af of eerst de linkeroperand of eerst de rechteroperand uitgerekend wordt - en in C++ is die volgorde niet voorgeschreven. Als eerst x bepaald wordt en daarna de waarde van F(x), dan wordt de waarde 18, anders 22. Hetzelfde geldt voor de expressie F(x) + x. De waarde van zo'n expressie is dus AFHANKELIJK van de gebruikte compiler. Conclusie: gebruik dit soort functies niet op deze manier. Als & weggelaten wordt, dan verandert de GLOBALE variabele x niet (alleen de LOCALE x verandert). Dan is de uitkomst altijd 18. En na afloop is de GLOBALE x nog steeds 7. Opgave 22 void drukaf (char letter) { if ( letter == 'a' ) { // of met een switch-statement cout << "****" << endl << "* *" << endl << "****" << endl << "* *" << endl << "* *" << endl; } // if else if ( letter == 'b' ) // etcetera ... } // letter