Uitwerking Opgaven Programmeermethoden, najaar 2020 - opgaven 57/61 Opgave 57 (vervolg) h. Er wordt een nieuw int-vakje, met adres q, gemaakt; hier wordt 4 opgeborgen. i. Nu zweeft ergens een vakje rond waarvan "niemand" het adres meer weet. Niet zo verstandig. j. getal = *p; *p = *q; *q = getal; // verwissel de inhouden Of met int* r; erbij: r = p; p = q; q = r; // verwissel de pointers k. Diverse mogelijkheden: *p = cijfer; // hopelijk wees p ergens naar, en dat // is nu overschreven *q = cijfer; // idem Of (met nieuwe vakjes): p = new int; *p = cijfer; q = new int; *q = cijfer; Of: p = new int; *p = cijfer; q = p; // q en p wijzen nu hetzelfde (nieuwe) vakje aan Of: p = &cijfer; q = &cijfer; l. Wederom verschillende mogelijkheden: r = A; // (*) Of (geheel anders): r = new int[10]; for ( int i = 0; i < 10; i++ ) r[i] = i; Dit laatste array moet ooit vernietigd worden met delete [ ] r; Vervolgens q = r;, of weer een echt nieuw array q maken (als bij m.). m. q = new int[10]; for ( int i = 0; i < 10; i++ ) q[i] = i * i; Als de regel q = new int[10]; er NIET staat, wordt in het "oude" array geknoeid, en is dus ook het array r en bij mogelijkheid (*) ook A veranderd. Als r ditzelfde stuk geheugen (na r = q;) aanwijst, is dat dus ook veranderd. Opgave 58 a. p is het adres van een int; *p is die int, en &p is het adres van p zelf (dus het adres van het adres van de betreffende int). b. Actuele parameters: p en q; formele: r en s. c. In main worden twee vakjes aangemaakt met waarden 3 resp. 4; p en q bevatten de adressen van deze vakjes. De functieaanroep met & (call by reference) laat p en q mogelijk veranderen. Overal waar r resp. s staat mag je p resp. q lezen. Eerst gaat p ergens anders naar wijzen, daar wordt 1 neergezet, en waar q naar wees (daar zat 4 in) wordt nu 96 opgeborgen. Afgedrukt wordt eerst 3 en 4, daarna 1 en 96. Het vakje met 3 erin hangt onbereikbaar ergens rond. d. Nu met value-parameters. Er worden locale variabelen r en s aangemaakt, die om te beginnen dezelfde waarde als p resp. q krijgen, dus 3 resp. 4 aanwijzen. Dan gaat r naar een nieuwe int, 1, wijzen; dat waar s (en dus ook q) naar wees wordt 96. Afgedrukt worden 3 en 4, daarna 3 en 96. Het vakje waar r naar wijst (met 1 erin) is nu onbereikbaar. Denk eraan dat de POINTER de &- of value-parameter is, en niet datgene waar de pointer naar wijst: dat kan in beide gevallen veranderen. e. Elke new moet in feite een keer met een delete ongedaan gemaakt worden. In het geval van c zou dit bijvoorbeeld als volgt kunnen: Voeg vlak voor r = new int; in de functie toe delete r; Voeg voor het einde van main toe: delete p; delete q; In het geval van value-parameters (onderdeel d) moet in plaats van aan het begin van de functie vlak voor het einde delete r; worden toegevoegd. Opgave 59 Aangezien een char* vaak lastig met geheugenbeheer is, zeker in objecten, hebben we hier maar char naam[30]; gebruikt. Was het een char*, dan zouden we steeds met new geheugenruimte voor de namen moeten aanmaken. Het ook met strings. a. mens* persoon = new mens; // handiger dan mens persoon; mens* individu; strcpy (persoon->naam,"Wilhelmina"); // en niet ... = "Wilhelmina"; persoon->kind = NULL; b. individu = new mens; strcpy (individu->naam,"Juliana"); individu->kind = NULL; persoon->kind = individu; c. individu = new mens; strcpy (individu->naam,"Beatrix"); individu->kind = NULL; persoon->kind->kind = individu; d. individu = new mens; strcpy (individu->naam,"Willem"); individu->kind = persoon; persoon = individu; e. cout << persoon->kind->kind->naam << endl; f. class mens2 { public: char naam[30]; mens2* kind1; mens2* kind2; }; // mens2 g. class mens3 { public: char naam[30]; mens3* kind1; mens3* kind2; mens3* ouder1; mens3* ouder2; }; // mens3 Opgave 60 a. class vakje { // of een struct int info; vakje* volgende; }; // vakje void zetervoor (int getal, vakje*& ingang) { // zet vakje met getal erin vooraan in lijst ingang // let op de &: ingang gaat hier zeker veranderen ==> call by reference vakje* p; p = new vakje; p->info = getal; p->volgende = ingang; ingang = p; // nu NIET delete p; ! } // zetervoor vakje* ingang = NULL; zetervoor (5,ingang); zetervoor (9,ingang); zetervoor (4,ingang); b. void achteraan (int getal, vakje*& ingang) { // voeg vakje met getal erin achteraan lijst ingang toe vakje* p; if ( ingang == NULL ) { ingang = new vakje; ingang->info = getal; ingang->volgende = NULL; // of in plaats van deze drie statements: zetervoor (getal,ingang); } // if else { // dus ingang is zeker niet NULL p = ingang; while ( p->volgende != NULL ) p = p->volgende; // nu wijst p naar het laatste vakje uit de lijst p->volgende = new vakje; p->volgende->info = getal; p->volgende->volgende = NULL; // of: zetervoor (getal,p->volgende); } // else } // achteraan c. Toevoegen aan lege lijst, en lijst met een, twee en drie elementen. Steeds lijst laten afdrukken. Opgave 61 a. void voegtoe (wijzer& ingang, int getal) { wijzer p = new vakje; p->info = getal; if ( getal > 0 ) { p->rechts = ingang; p->onder = NULL; } // if else { p->onder = ingang; p->rechts = NULL; } // else ingang = p; } // voegtoe b. void klapom (wijzer ingang) [ wijzer p = ingang->rechts; ingang->rechts = ingang->onder; ingang->onder = p; ingang->info = -ingang->info; } // klapom c. void verwijder (wijzer& ingang) { wijzer p = ingang; if ( ingang != NULL ) { if ( ingang->info > 0 ) ingang = ingang->rechts; else ingang = ingang->onder; delete p; } // if } // verwijder d. Bij a en c moet er een & bij staan: de pointer wijzer kan (bij a zelfs zeker) veranderen. Bij b maakt het niet uit: de ingangspointer verandert toch niet. Staat er geen & bij, dan wordt er met een lokale kopie van ingang gewerkt. e. int som (wijzer ingang) { int totaal = 0; wijzer p = ingang; while ( p != NULL ) { totaal += p->info; if ( p->info > 0 ) p = p->rechts; else p = p->onder; } // while return totaal; } // som