Uitwerking Tweede deeltentamen Mobiel programmeren - versie 1 Vrijdag 3 februari 2017, 8.30-10.30 uur 1. Wat kan gezegd worden van het stukje programma b=!b (a) De expressie b=!b heeft altijd de waarde false (b) De expressie b=!b heeft altijd de waarde true (c) De opdracht b=!b; verandert de waarde van b in zijn tegenovergestelde (d) De opdracht b=!b; maakt de waarde van b gelijk aan false Toelichting op het antwoord: De operator! is not, dus blijkbaar is b een bool variabele. Met de opdracht b =!b ; wordt b veranderd in not b, zijn tegenovergestelde. De operator!= betekent ongelijk, dus met de uitkomst van expressie b!=b is altijd false (immers, niets is ongelijk aan zichzelf). Maar hier stonden de symbooltjes in een andere volgorde. 2. Met using aan het begin van de broncode geef je aan (a) dat je een bepaalde namespace wilt gebruiken (b) dat je een bepaalde klasse wilt gebruiken (c) dat je een bepaalde methode wilt gebruiken (d) dat je een bepaalde interface wilt gebruiken Toelichting op het antwoord: Denk bijvoorbeeld aan using System;. Je krijgt dan de namespace System. Daarin zit de klasse Console en daar weer in zit de methode ReadLine, maar die zie je achter using niet staan. 3. Als je vanuit een app een andere app wilt lanceren, en daarbij ook nog extra informatie wilt meegeven, moet je (a) De methode SetResult van die andere app aanroepen (b) Een Intent gebruiken waarvan je PutExtra hebt aangeroepen (c) Die app lanceren met StartActivityForResult in plaats van StartActivity (d) De constructor-methode van die andere app een extra parameter geven Toelichting op het antwoord: StartActivityForResult is nodig als je wilt dat de andere app wat terugzegt. Dat zal die andere app dan doen met behulp van SetResult. De constructor-methode kun je niet gebruiken omdat apps niet gestart worden door direct een object aan te maken, maar indirect via een Intent. Extra informatie doorgeven gebeurt dan door aanroep van PutExtra. 4. De expressie x&&y heeft als waarde (a) als x gelijk is aan true dan x, en anders y (b) als x gelijk is aan true dan y, en anders x (c) als x gelijk is aan y dan true, en anders false (d) als x gelijk is aan null dan y, en anders x Toelichting op het antwoord: (a) is de or-operator, (c) is de ==-operator, (d) is de??- operator 1
5. Een string s die uit cijfer-tekens bestaat kun je omzetten naar de int die daardoor wordt gerepresenteerd door (a) Aanroep van de methode string.indexof(s) (b) Aanroep van de methode int.parse(s) (c) Gebruik van de cast-notatie (int)s (d) Gebruik van de notatie voor een interpolated string: $"s" Toelichting op het antwoord: Met de cast-notatie kun je wel van float of double naar int converteren, maar niet van string. Met de notatie voor een interpolated string kun je converteren van int naar string, dat is de andere kant op. Methode IndexOf levert wel een int op, maar dat is een positienummer, niet de geconverteerde waarde. 6. De lengte van de string "n///\\\n" is (a) 6 (b) 7 (c) 8 (d) 10 Toelichting op het antwoord: De combinaties \\ en \n zijn speciale codes voor respectievelijk een backslash en een newline; deze representeren één symbool. De overige vier symbolen staan voor zichzelf. De quotes tellen natuurlijk ook niet mee. Totaal dus 6 karakters. 7. Het is handiger om een char[] te gebruiken in plaats van een string als je (a) De declaratie wilt combineren met een initialisatie om een bepaald woord op te slaan (b) Bijzondere lettertekens wilt opslaan, bijvoorbeeld Griekse of Russische (c) Later individuele letters wilt opvragen (d) Later individuele letters wilt veranderen Toelichting op het antwoord: Initialisatie is juist gemakkelijker met een string. Zowel string als characters kunnen alle Unicode-karakters opslaan. Letters opvragen kan in een string en array even gemakkelijk. Individuele letters veranderen is in een string onmogelijk, dus daarvoor heb je een array nodig. 8. Als je met een foreach-opdracht een array a langsloopt, en je declareert in de header van de opdracht een variabele t, dan kun je in de body het element dat aan de beurt is opvragen (a) met de expressie a[t] (b) met de expressie a(t) (c) met de expressie t (d) met de expressie a.get(t) Toelichting op het antwoord: Denk aan een voorbeeld: foreach (Point p in punten)...p... In deze header declareer je variabele p, en in de body heeft dat de waarde van het punt dat aan de beurt is. Je schrijft dus niet punten[p] in de body! Het is natuurlijk een beetje gemeen dat de variabele hier t genoemd werd. Dat doet aan een tellertje denken, maar antwoord (a) hoort bij een situatie waar je niet een foreach maar een for gebruikt: for (int t=0; t<a.length; t++)...a[t]... 9. Als je de strings in een lijst van strings zichtbaar wilt maken in een ListView, dan moet je 2
(a) methode OnDraw herdefiniëren in een subklasse van ListView, en daarin met foreach alle strings in de lijst tekenen. (b) de lijst meegeven aan een ArrayAdapter, die je gebruikt als property van de listview (c) de lijst gebruiken als waarde van CheckedItemPositions van de listview (d) met foreach elke string in de lijst meegeven aan SetItemChecked van de listview Toelichting op het antwoord: Met CheckedItemPositions kun je opvragen welke items aangevinkt zijn. Met SetItemChecked kun je het programma een item laten aanvinken. Een ListView hoef je niet zelf te tekenen, dus OnDraw heeft hier niet mee te maken. 10. Het resultaattype van de methode PutExtra is Intent, omdat (a) het handig is dat je het resultaat meteen kunt meegeven als parameter van StartActivity (b) het handig is dat je het resultaat meteen kunt meegeven als parameter van nog een aanroep van PutExtra (c) het handig is dat je het resultaat meteen onder handen kunt nemen met GetStringExtra (d) het handig is dat je het resultaat meteen kunt toekennen aan de Intent property van een Activity 11. Wat gebeurt er direct bij uitvoering van de volgende opdracht: new DatePickerDialog(this,(o,e)=>d=e.Date,2017,2,3).Show(); (a) Variabele d wordt een door de gebruiker uitgekozen datum (b) Variabele d wordt de datum van vandaag (c) De gebruiker krijgt de datum van vandaag te zien (d) De gebruiker kan bevestigen dat de Date-property van variabele e de datum van vandaag zal worden Toelichting op het antwoord: Dit brengt de dialoog in beeld, met daarop de datum van het tentamen. Variabele d krijgt pas zijn waarde als de gebruiker op OK heeft gedrukt, dus dat is niet meteen. 12. Iemand schrijft een methode om te kunnen bepalen of een string (die als parameter wordt meegegeven) een bepaalde waarde (die ook als parameter wordt meegegeven) bevat: bool Bevat(string s, char x) for (int t=0; t < s.length; t++) if (s[t] == x ) return true; return false; Wat is er fout in deze methode? (a) In de test moeten geen aanhalingstekens staan in x (b) In de test moeten dubbele aanhalingstekens staan, dus "x" in plaats van x (c) Voor de opdracht return false; moet nog else staan (d) De body van de for-opdracht moet tussen accolades staan omdat hij uit meerdere opdrachten bestaat 3
Toelichting op het antwoord: Met die aanhalingstekens test je altijd op de 24e letter van het alfabet, niet op de inhoud van de variabele x. Dubbele kwoots is al helemaal onzin, want dat duidt op een string in plaats van een karakter. De opdracht return false moet pas worden uitgevoerd als alle letters van de string tevergeefs zijn uitgevoerd. Hij hoort dus niet bij de for-opdracht, en moet dus niet met accolades in de body gezet worden. Om dezelfde reden moet er ook niet else staan: dan zou hij de eerste ronde er altijd uitvliegen. (Deze opgave lijkt op opgave 12 uit deeltentamen 2, maar het programma is net anders. Leer nooit meerkeuzevragen uit je hoofd, maar probeer het te begrijpen!) 13. Iemand schrijft een methode om een getal x tot een niet-negatieve macht e te verheffen: int Macht(int x, int e) int res = 1; for (int t=0; t<=e; t++) res *= x; return res; Welk ongewenst effect heeft deze methode? (a) de herhaling gaat één stap te lang door (b) het werkt niet als x gelijk is aan 0 (c) het werkt niet als x gelijk is aan 1 (d) de uitkomst is altijd 1 Toelichting op het antwoord: De test had moeten zijn t<e, of de initialisatie int t=1. Als x gelijk is aan 0 of 1 werkt het juist net wel goed: de uitkomst is dan 0 of 1, zelfs als je een stap te lang doorgaat. (Deze opgave lijkt op opgave 13 uit het proeftentamen, maar het programma is net anders. Leer nooit meerkeuzevragen uit je hoofd, maar probeer het te begrijpen!) 14. Iemand wil de waarde van een float-variabele x met wat toelichting in een string opnemen, en schrijft daarom: "de afstand is: x" Dit heeft niet het gewenste effect. De fout kan op verschillende manieren worden gecorrigeerd. Wat is niet de goede manier om de fout te corrigeren? (a) plustekens rond de x neerzetten, en daaromheen weer aanhalingstekens (b) een dollarteken voor de string neerzetten, en accolades openen en sluiten om de x heen toevoegen (c) een plusteken achter de string neerzetten, en de x helemaal naar het eind verplaatsen (d) direct achter de x nog.tostring() toevoegen Toelichting op het antwoord: (a), (b) en (c) zijn correcte manieren om de waarde van de variabele met de string te combineren "de afstand is: " + x + "" $"de afstand is: x" "de afstand is: " + x (d) is dus de gevraagde foute correctie: hiermee zou de tekst ToString zelf in de string terecht komen. 4
15. In de header van een klasse kan achter de naam van de klasse een dubbele punt staan, en daarachter nog iets. Welk van de volgende uitspraken is niet correct? (a) Achter de dubbele punt kan de naam van een interface staan, waarvan je de methoden moet implementeren (b) Achter de dubbele punt kan de naam van een interface staan, waarvan je de public variabelen mag gebruiken (c) Achter de dubbele punt kan de naam van een klasse staan, waarvan je de protected methoden mag aanroepen (d) Achter de dubbele punt kan de naam van een klasse staan, waarvan je de virtual methoden mag implementeren Toelichting op het antwoord: Een interface heeft geen variabelen, alleen methodeheaders die je moet implementeren. Twee open vragen (2 15 = 30 punten) 16. Dit is het syntaxdiagram van het begrip type: type struct naam sbyte byte float bool short ushort double char int uint decimal long ulong string object class naam [ ], (a) Wat is het verschil tussen de bovenste 14 types enerzijds, en de onderste 3 types anderzijds? (b) Welke exception kan er optreden bij gebruik van de onderste 3 types, en wanneer gebeurt dat? (c) Welke bijzondere rol heeft het type object? (d) Hoe worden de types genoemd die je krijgt als je de vierkante haakjes gebruikt, en wat wordt daarmee beschreven? (e) Geef een voorbeeld van een declaratie-met-initialisatie waarin een type zoals bedoeld bij (d) wordt gebruikt. Antwoord: Variabelen van de bovenste 14 types bevatten waarden, die van de onderste 3 bevatten verwijzingen. Bij het gebruik van verwijzingen dreigt een null reference exception; dit gebeurt als je van een variabele met de waarde null toch een member probeert op te vragen. Het type object is het bovenste type in de hierarchie van subklassen: het is een superklasse van elk ander type. Met vierkante haakjes maak je ene array, en dat beschrijft objecten met daarin een rij genummerde variabelen. Het gevraagde voorbeeld kan bijoorbeeld zijn: 5
int [] a = new int[10]; string [] b = "aap", "noot", "mies" ; 17. Beantwoord voor een drietal bijzonder soort methoden steeds drie vragen, waarbij het er om gaat hoe elk soort zich onderscheidt van gewone methoden: (a) Constructormethoden zijn een bijzonder soort methoden. Hoe kun je aan de header zien dat een methode een constructormethode is? Hoe wordt een constructormethode aangeroepen? Wat is de speciale rol van constructormethoden? (b) Static methoden zijn een bijzonder soort methoden. Hoe kun je aan de header zien dat een methode een static methode is? Hoe wordt een static methode aangeroepen? Wat is de speciale rol van static methoden? (c) Event handlers zijn een bijzonder soort methoden. Hoe kun je aan de header zien dat een methode een event handler is? Hoe wordt een event handler aangeroepen? Wat is de speciale rol van event handlers? Antwoord: Contructormethoden hebben dezelfde naam als de klasse, en geen resultaattype. Je roept ze aan via een new-expressie. Ze zijn bedoeld om nieuw aangemaakte objecten alvast van een beginwaarde te voorzien. Static methoden herken je aan het woord static in de header. Je roept ze aan met de naam van de klasse voor de punt. Anders dan gewone methoden hebben ze geen object onder handen. Event handlers herken je aan hun twee parameters, van het type object en EventArgs. Ze worden niet vanuit het programma aangeroepen, maar door het operating systeem. Daarmee kan het programma reageren op akties van de gebruiker. Eén programmeervraag (25 punten) In deze opgaven mag je de using-regels, en het public/private zijn van methoden en variabelen weglaten. 18. De klasse Stad bevat de gegevens van een stad: de naam, het punt waar (het centrum van) de stad ligt (in kilometers, volgens het nationale kilometer-grid van de Topografische Dienst). Een voorbeeld van de manier om een Stad-object aan te maken is new Stad("Utrecht", 136.8f, 455.9f) Je mag er van uitgaan dat de naam uit één woord bestaat, dus Den Haag is in deze versie van het programma nog niet mogelijk. (a) Schrijf deze klasse Stad, en maak daarbij de volgende methodes een constructormethode, die kan worden aangeroepen zoals in het voorbeeld een methode die de afstand berekent van de stad tot een als parameter meegegeven punt een methode om de gegevens van de stad in een string weer te geven een methode om de string van de vorige methode weer om te zetten in een stadobject (naar keuze een extra constructormethode, of de andere gangbare manier om dit te doen) (b) Bekijk de volgende klasse: class StedenView : View public List<Stad> steden = new List<Stad>(); 6
public StedenView(Context ctx) : base(ctx) steden.add( new Stad("Utrecht, 136.8f, 455.9f) ); // en nog vele andere steden op dezelfde manier... this.touch += RaakAan; public void OnDraw(Canvas c) // TODO public void RaakAan(object o, TouchEventArgs tea) // TODO Schrijf de bodies van OnDraw en RaakAan op zo n manier dat Alle steden op het scherm getekend worden, als een rondje op de juiste plaats met de naam van de stad ernaast. Je mag de kilometers van het grid laten corresponderen met pixel-coördinaten op het scherm. Als de gebruiker het scherm aanraakt, de naam van de stad die daar het meest dichtbij ligt zichtbaar wordt in een pop-up kadertje, dat na een paar seconden weer verdwijnt. Antwoord: public class Stad public string naam; public float x, y; public Stad(string nm, float a, float b) naam = nm; x = a; y = b; public float Afstand(float a, float b) return Math.Sqrt((x-a)*(x-a)+(y-b)*(y-b)); public override string ToString() return $"x y naam"; public Stad(string s) string[] velden = s.split(); x = float.parse(velden[0]); y = float.parse(velden[1]); naam = velden[2]; // in de body van OnDraw: Paint verf = new Paint(); foreach(stad s in steden) c.drawcircle( s.x, s.y, 50, verf ); c.drawtext( s.naam, s.x+60, s.y, verf); // in de body van RaakAan: 7
string tekst = ""; float min = 10000; foreach(stad s in steden) float dist = s.afstand(tea.event.getx(), tea.event.gety() if ( dist < min ) min = dist; tekst = s.naam; Toast.MakeText(c2, tekst, Android.Widget.ToastLength.Short).Show(); waarbij c2 een extra verwijzing is van de context die in de constructormethode beschikbaar was. (Dit was een onbedoelde complicatie, en bij deze parameter wordt in het tentamen niets foutgerekend). 8