NSD (Nassi-Schneidermann

advertisement
Programma's
Inleiding
De CPU
Computers kunnen alleen uitvoeren wat een programmeur in een programma heeft
vastgelegd. Een computerprogramma bestaat uit instructies. Deze worden door de
CPU uitgevoerd. CPU is Engels voor Central Processing Unit. In het Nederlands
gebruiken we CVE: Centrale VerwerkingsEenheid.
In een advertentie voor een computer is de CPU de Pentium of de Athlon.
Geheugen, registers en variabelen
Een computer kan gegevens onthouden. Als de computer uitstaat blijven de gegevens
bewaard in het niet-vluchtig geheugen. In een moderne computer zijn dat harddisk,
DVD´s, SSD´s en USB-sticks.
Ook het programma zelf staat op zo'n medium.
Als de computer start wordt het besturingssysteem in het werkgeheugen geladen.
Voorbeelden van besturingssystemen zijn Windows, Linux, Apple.
Het werkgeheugen bestaat uit reepjes waarop geheugenchips zitten. Deze chips
onthouden de gegevens alleen zolang ze onder elektrische spanning staan. Als je de
computer uitzet is alle informatie weg.
Daarom wordt dit soort geheugen vluchtig genoemd.
Het besturingssysteem verricht allerlei taken. Het kan bijvoorbeeld een programma in
het werkgeheugen laden.
Programma's werken met gegevens. Voor een programma zijn dit altijd binaire
gegevens, al kunnen ze voor de mens een duidelijkere betekenis hebben.
De bekende ASCII-tabel is daarvan een belangrijk voorbeeld.
Elke binaire waarde van 8 bits (1 byte) is gekoppeld aan een teken.
Een andere bekende betekenis van een binaire code zijn getallen. De enen en nullen
staan dan voor de enen en nullen in een binair getal.
Een CPU kan met die getallen rekenen. Ook kunnen waarden met elkaar vergeleken
worden. Bij vergelijken moet je denken aan 'gelijk zijn', maar ook groter en kleiner
zijn.
Als een programma gegevens bewerkt gaat dat het snelste als er ergens in de CPU
aanwezig zijn. Dat is veel sneller dan het inlezen vanuit het werkgeheugen, en heel
erg veel sneller dan lezen van een harddisk.
De CPU bewaart gegevens in registers. In een moderne CPU kunnen er 64bits n een
register bewaard worden. Meer dan de helft van de CPU's die verkocht worden
hebben echter nog steeds registers van 8 bits.
1
In een computerprogramma beschrijven we plekken waarin iets bewaard wordt met
variabelen. Variabelen hebben een type (een soort). Zo zijn er variabelen waarin
getallen bewaard kunnen worden, maar ook variabelen waarin tekenreeksen bewaard
kunnen worden.
Soort gegevens
Type
Gehele getallen
Integer
Kommagetallen
Float, single, double, extended
Tekenreeksen
String
Elke variabele heeft bovendien een naam. Dat kan een eenvoudige naam zijn zoals bij
wiskunde (A,B,X), maar ook een duidelijkere omschrijving van wat in de variabele
bewaard wordt (Temperatuur, Gewicht).
Volgorde van uitvoering
Een programma bestaat uit opdrachten voor de CPU. Met een mooi woord worden die
opdrachte instrcuties genoemd.
De instructies worden meestal opeenvolgend uitgevoerd.
Als een programma uit de drie opdrachten bestaat worden deze in dezelfde volgorde
uitgevoerd.
Opdracht 1
Opdracht 2
Opdracht 3
Springen
Om instructie over te kunnen slaan zijn twee speciale opdrachten nodig:


spronginstructie: om het programma op te dragen om op een andere plek
verder te gaan.
voorwaardelijke spronginstructie: om onder een bepaalde voorwaarde op een
andere plek verder te gaan. Als niet aan de voorwaarde voldaan is gaat het
programma met de volgende instructie verder.
2
1. Elementaire instructies
Een CPU kent tegenwoordig heel veel opdrachten waarmee een programma zo snel
mogelijk uitgevoerd kan worden.
Voor deze lessen gaan we echter uit van een heel erg eenvoudige CPU die slechts 6
soorten instructies kent. Omdat dit een soort basisopdrachten zijn noemen we ze met
een elementaire instructies.






Bewerkingen met variabelen
Spronginstructie
Voorwaardelijk spronginstructie
Halt
Lees
Schrijf
De elementaire instructies gaan we nu in detail bekijken.
1.1.1 Bewerkingen met variabelen
In een programma kunnen getallen en teksten (strings) bewaard worden in een plek
die we een variabele noemen.1
De naam van een variabele kan een letter zijn (A, B, C) of een tekenreeks. Bij echte
programma's is het vaak beter om een duidelijke naam te gebruiken (zoals
Temperatuur of Leeftijd).
Voorbeeld 1.1
De volgende opdracht zet de waarde 6 in de variabele A
A=6
Voorbeeld 1.2
De volgende opdracht kopieert de inhoud van B naar A
A=B
Voorbeeld 1.3
De volgende opdracht telt A en B op en zet het resultaat in C.
C=A+B
Bij de meeste programmeertalen kun je ook andere ‘dingen’ in variabelen bewaren,
bijvoorbeeld datums of tijdstippen. Voorlopig werken we alleen met getallen en tekenreeeks. De
getallen kunnen dan gehele getallen of kommagetallen zijn.
1
3
Voorbeeld 1.4
De volgende opdracht verminderd de waarde van A met 1
A=A-1
Je vindt het misschien vreemd dat in één opdracht (A=A-1) twee keer dezelfde
variabele voorkomt. Rechts van het is-teken staat wat de berekening is (A-1). Links
staat waar de uitkomst bewaard wordt (in dit geval in dezelfde variabele: A).
Dus als de waarde van A vooraf gelijk aan 6 is, dan is de waarde van A na de
opdracht A=A-1 gelijk aan 5.
De volgende berekeningen kun je met getallen maken:
Opdracht
Optellen
Aftrekken
Vermenigvuligen
Delen
Teken
+
*
/
Voorbeeld
A=B+C
A=B-C
A=B*C
A=B/C
Je kent deze tekens waarschijnlijk al van een Graphische rekenmachine zoals die op
middelbare scholen gebruikt wordt.
Voorbeeld 1.5
In de tabel hieronder kun je drie eenvoudige bewerkingen met variabelen
vinden. Deze worden van boven naar beneden uitgevoerd.
Na elke opdracht staat vermeld wat de waarde van de variabelen A, B en C is,
nadat de instructie uitgevoerd is.
regel
1
2
3
opdracht
A=2
B=5
C=A+B
A
2
2
2
B
?
5
5
C
?
?
7
Met A=2 zorg je er voor dat het getal 2 in variabele A bewaard wordt.
Met C=A+B worden de getallen in de variabelen A en B bij elkaar geteld. De
uitkomst wordt in variabele C gezet.
De variabele waarin de uitkomst terecht komt staat altijd links van het gelijk-teken.
Rechts van het gelijk-teken staat een constant getal of een berekening.
Non-voorbeeld 1.1
De volgende opdracht is geen geldige bewerking met een variabele:
A+2
Er wordt wel iets met de variabele A gedaan (er wordt 2 bij opgeteld), maar het
resultaat wordt nergens bewaard. Een geldig voorbeeld is B=A+2.
4
Opdracht 1.1
Bekijk het volgende eenvoudige programma. Wat moet er op de plaats van X
staan?
regel
1
2
3
opdracht
A=1
B=3
C=A+B
A
1
1
1
B
?
3
3
C
?
?
X
Opdracht 1.2
Bekijk het volgende eenvoudige programma. Vul het schema verder in. Wat
doet dit programma met de inhoud van de variabelen A en B? Zou dit ook
zonder de hulp van variabele C kunnen?
regel
1
2
3
4
5
opdracht
A=2
B=3
C=A
A=B
B=C
A
2
2
B
?
3
C
?
?
De bovenstaande methode werkt niet alleen voor getallen, maar ook voor teksten.
Zonder hulpvariabele (alleen getallen)
Er is een slimme manier die geen hulpvariabele nodig heeft. Deze methode werkt
alleen met getallen.
Opdracht 1.3
Bekijk het volgende programma. Vul het schema verder in. Controleer dat A en
B inderdaad verwisseld worden.
regel
1
2
3
4
5
opdracht
A=2
B=3
A=A+B
B=A-B
A=A-B
A
2
2
B
?
3
C
?
?
Deze methode werkt niet met teksten, omdat je daar geen optellingen of aftrekkingen
mee kunt berekenen.
5
1.1.2 Formules
In een berekening kunnen ook haakjes voorkomen. Daarbij gelden dezelfde regels als
bij wiskunde.
De volgende twee berekeningen zijn dus verschillend:
D=G*G+1*G+2
D=G*(G+1)*(G+2)
De eerste kun je ook schrijven als D=G*G+G+2. Bij de tweede kun je ook haakjes
wegwerken. Het wordt dan: D=G*G*G+3*G*G+2*G
Schrijfwijze van formules
Formules die je op papier schrijft met pen of potlood kun je meestal niet op dezelfde
manier in een computerprogramma schrijven.
Na deze uitleg moet je beter in staat zijn om een formule om te schrijven naar de
schrijfwijze, zoals dat in een programmeertaal nodig is.
Eerst wat eenvoudige voorbeelden:
Wiskunde
y= a⋅ x b
y= x
y=
2
x
D= b2− 4⋅ a⋅ c
Basic
Pascal
y=a*x+b
y:=a*x+b
y=Math.Power(x,2)
Y:=x*x
y=sqrt(x)
Y:=sqrt(x)
D=b^2-4*a*c
D:=b*b-4*a*c
De eenvoudigste oplossing is om een kwadraat te schrijven is x*x.
Moeilijkere voorbeelden:
6
wiskunde
a b
y=
c
a
y=
Basic
Pascal
y=(a+b)/c
y:=(a+b)/c
y=a/(b+c)
y=a/(b+c)
y=(a+b)/(c+d)
Y:=(a+b)/(c+d)
D=sqrt(a+b)/(2*c)
D:=sqrt(a+b)/(2*c)
b c
a b
c d
y=
a b
2⋅ c
D=
Je ziet dat je de formule in de teller of noemer tussen haakjes moet zetten. Soms dat
dat niet nodig, maar het kan geen kwaad als je het veiligheidshalve altijd doet.
y=
a⋅ b
c kan zonder haakjes rond de teller geschreven worden : y=a*b/c
y=
a
a
y= ⋅ c
wordt
y=a/(b*c).
Maar
y=a/b*c
is
onjuist,
want
dat
betekend
b⋅ c
b
Het omschrijven van een formule heet met een mooi woord lineariseren.
Opdracht 3
Probeer nu de volgende formules om te schrijven (te lineariseren).
a
b
c
6⋅ x 4
3
2⋅ a b
y=
x
2
y= a bx c
y=
− b− b2− 4⋅ a⋅ c
2⋅ a
2⋅ a b
y=
x
x=
d
e
f
g
y= x 3 2x2 3x− 1
x 1 x 2
y=
x− 3
7
1.2 Sprongen
Er bestaan ook sprong-instructies, de processor gaat dan verder met een opdracht
ergens anders in het geheugen.
Met JUMP 3 wordt bedoeld dat de computer met de opdracht op regel 3 verder gaat.
Bekijk de volgende opdrachten. Op regel 4 staat niets vermeld bij de variabelen omdat
deze regel niet uitgevoerd wordt.
regel
1
2
3
4
5
opdracht
A=1
B=3
JUMP 5
A=6
C=A+B
A
1
1
1
B
?
3
3
C
?
?
?
1
3
4
8
1.3 De voorwaardelijke sprong: Alleen springen als...
Soms moet het programma een keuze maken, afhankelijk van een voorwaarde gaat de
computer dan met de volgende instructie verder, of hij springt naar een andere plek in
het programma. Dit heet een voorwaardelijke spronginstructie.
Voorbeeld 1
Een voorbeeld van een voorwaardelijke spronginstructie is:
IF A>2 JUMP 3
Het programma springt naar regel 3 als A groter dan 2 is.
In plaats van A>2 kunnen ook de andere voorwaarden voorkomen:
A=3, B<3, A=B, etc.
In de onderstaande tabel is de schrijfwijze voor vergelijkingen opgesomd, in de
linkerkolom staat de notatie zoals je die in de wiskunde gebruikt. Rechts daarnaast
staat die voor verschillende programmeertalen.
Er zijn ook programmeertalen waar andere codes voor vergelijkingen gebruikt worden
(bijvoorbeeld in COBOL, FORTRAN of C).
Wiskunde
Basic/Pascal/Delphi
C/Java
=
=
==
<
<
<
>
>
>
≠
<>
!=
≤
<=
<=
≥
>=
>=
Voorbeeld 2
Bekijk het onderstaande programma. Bij de derde opdracht ziet de CPU dat B
gelijk aan 0 is. Hij gaat dus verder met regel 5.
Nogmaals: als een opdracht niets aan de inhoud van de variabelen veranderd,
mag je de inhoud van de variabelen openlaten. Daarom is in dit voorbeeld niets
ingevuld bij de regels drie en vier.
regel
1
2
3
4
5
opdracht
A=1
B=0
IF B=0 JUMP 5
A=6
C=A+B
A
1
1
B
?
0
C
?
?
1
0
1
9
opdracht 4
Bekijk het onderstaande programma. Verander de voorwaarde in regel 3 zo, dat
regel 4 wel uitgevoerd wordt.
(Je moet dus B=0 veranderen in een andere voorwaarde).
regel
1
2
3
4
5
opdracht
A=1
B=0
IF B=0 JUMP 5
A=6
C=A+B
A
1
1
B
?
0
C
?
?
1
0
1
Door spronginstructies en voorwaardelijke spronginstructies te combineren, kun
bewerkingen met variabelen herhalen.
In het voorbeeld hieronder kun je zien dat eerste A=3 en B=0 uitgevoerd worden.
Daarna wordt B=B+1 en A=A-1 uitgevoerd totdat A nul is. Dan pas wordt B=2*B
uitgevoerd. De asterisk (*) staat voor vermenigvuldigen.
regel
1
2
3
4
5
6
opdracht
A=3
B=0
B=B+1
A=A-1
IF A>0 JUMP 3
B=2*B
opdracht 4
Tel hoe vaak elke regel in het onderstaande programma uitgevoerd.
regel
1
2
3
4
5
6
opdracht
A=3
B=0
B=B+1
A=A-1
IF A>0 JUMP 3
B=2*B
10
Het heeft bij een (voorwaardelijke) spronginstructie niet zoveel zin om te springen
naar de regel die meteen na de spronginstructie staat. Je komt daar vanzelf, ook als je
niet springt.
opdracht 5
Naar welke regel gaat het onderstaande programma na regel 1 als A=0? En als
A<>0?
1
2
IF A=0 JUMP 2
B=6
Als … dan … anders ….
Het gebeurd vaak dat een programma iets moet doen als een voorwaarde waar is en
iets anders als de voorwaarde niet waar is.
Voorbeeld 1
Als A=6 dan A=A-1 anders B=B+1
Opdracht 6
Schrijf het voorbeeld om naar elementaire instructies.
Je kunt dit in twee losse waarden splitsen:
Als A=6 dan A=A-1
én
Als A<>6 dan B=B+1
opdracht 7
Schijf ook de twee losse voorwaarden om naar elementaire instructies.
11
1.4. Halt
We introduceren nog een instructie die we kunnen gebruiken om het programma
beëindigen: Halt. Na deze instructie verzet het programma geen stap meer!
Alle programma’s hierboven kunnen dus met 1 extra regel worden uitgebreid!
opdracht 6
Zet de onderstaande beschrijving van een programma om naar elementaire
instructies.
Oefenen met elementaire instructies
Geef elkaar in tweetallen opdrachten van de volgende vorm:
regel 1: bewaar 6 in de variabele A
regel 2: bewaar 3 in de variabele B
regel 3: bewaar het product van A en B in de variabele C
regel 4: tel 1 bij A op
regel 5: haal 1 van B af
regel 6: als A kleiner dan 10 is, ga naar regel 3
regel 7: beëindig het programma
Schrijf bij deze opdrachten een programma met elementaire instructies
12
1.5. Lees
Met de opdracht Lees kan een programma invoer van het toetsenbord inlezen.
Deze wordt dan in een variabele bewaard.
Voorbeeld 1
De volgende opdracht bewaard de invoer in variabele A
Lees(A)
1.6. Schrijf
Met de opdracht Schrijf kan een programma een tekst of de invoer van een variabel
op het scherm schrijven.
Voorbeeld 1
De volgende opdracht schrijft de inhoud van variabele A op het scherm.
Schrijf(A)
Voorbeeld 2
De volgende opdracht schrijft de tekst tussen haakjes op het scherm.
Schrijf(“hallo wereld”)
13
2. Stappendiagrammen
Bekijken het volgende programma:
regel
1
2
3
4
5
6
opdracht
A=3
B=0
B=B+1
A=A-1
IF A>0 JUMP 3
B=2*B
Als je kolommen voor de variabelen toevoegt heb je het probleem dat sommige regels
meer dan één keer doorlopen worden.
regel
1
2
3
4
5
6
opdracht
A=3
B=0
B=B+1
A=A-1
IF A>0 JUMP 3
B=2*B
A
3
3
3
2
B
?
0
1
1
Dat wordt een knoeiboel!
Je kunt het verloop van het bovenstaande programma (en de inhoud van de
variabelen) beter weergeven met een schema zoals dat hieronder staat aangegeven.
stap
1
2
3
4
5
6
7
8
9
10
11
12
regel
1
2
3
4
5
3
4
5
3
4
5
6
A
3
3
3
2
B
?
0
1
1
2
1
2
2
1
0
3
3
0
6
We noemen dit een stappendiagram, omdat per stap aangegeven staat welke
veranderingen het programma in de variabelen aanbrengt én hoe de computer door de
programmaregels loopt.
De inhoud van de variabelen is de waarde na het uitvoeren van de instructie.
14
opdracht 7
Waarom kunnen we de tabel na stap 12 niet meer voortzetten?
Waarom is bij regel 5, 8 en 11 niets bij de variabelen ingevuld?
Er volgen nu twee oefeningen in het maken van stappendiagrammen.
opdracht 8
Maak het stappendiagram van het onderstaande programma.
regel
1
2
3
4
5.
6
opdracht
A=2
B=0
A=A-1
B=B+1
IF A>0 JUMP 3
HALT
opdracht 9
Maak het stappendiagram van het bovenstaande programma.
In de vierde regel staat een wat complexere opdracht. Let er op dat
vermenigvuldigen voor optellen gaat. Je vermenigvuldigt dus eerst A en B,
daarna tel je er C bij op. Het resultaat zet je in C.
regel
1
2
3
4
5
6
7
8
opdracht
C=0
A=2
B=3
C=C+A*B
A=A-1
B=B+1
IF A>0 JUMP 4
HALT
15
3. Lussen programmeren
In dit onderdeel leer je hoe je in Delphi en NSBASIC een eenvoudig programma kunt
maken om met lussen te oefenen.
Delphi
Start het programma.
Kies in het menu File > Other...
Klik in het venster op Console Application
16
In het middendeel van het venster staat nu de volgende code:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
begin
{ TODO -oUser -cConsole Main : Insert code here }
end.
Regels die tussen accolades staan zijn zogenaamde commentaarregels ze dienen
ervoor om uit te leggen wat de regels erna doen.
De regel die begint met {TODO...} moet je nu vervangen door je eigen code.
Bijvoorbeeld:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
begin
{hier begint de lus}
For Teller := 10 to 12 do
{ schrijf de waarde van Teller op het scherm}
writeln(Teller);
end.
Je gebruikt in deze code de variabele Teller. Delphi wil echter nadrukkelijk weten wat
jij als variabelen nodig hebt.
Je geeft dat op de volgende manier op:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
{Maak ruimte voor de variabele Teller}
var
Teller : Integer;
begin
{hier begint de lus}
For Teller := 10 to 12 do
{ schrijf de waarde van Teller op het scherm}
writeln(Teller);
17
end.
Start het programma door in het menu Run > Run te kiezen.
Het programma wordt eerst in elkaar gezet. Dat heet met een moeilijk woord
compileren.
Van de code die je geschreven hebt (de broncode) wordt een uitvoerbaar programma
gemaakt.
Dat programma wordt in het zwarte venster getoond dat je even ziet verschijnen. Het
venster als het programma klaars is.
We lossen dat op door de programmaregel readln; toe te voegen waardoor het
programma wacht tot je iets ingetypt hebt:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Teller : Integer;
begin
{hier begint de lus}
For Teller := 10 to 12 do
{ schrijf de waarde van Teller op het scherm}
writeln(Teller);
{wacht tot de gebruiker op Enter drukt}
readln;
end.
Je kunt nu zien wat je programma op het scherm schrijft.
Je moet op Enter drukken om het programma af te sluiten.
18
NSBASIC
In NSBASIC ga je als volgt te werkt:
 Start het programma
 Kies in het startvenster voor Project File
Klik nu links in het Tool Palette op Button.
Klik daarna op het ontwerpvenster. Hierop wordt nu een knop geplaatst.
19
Dubbelklik op de knop. Er wordt nu een codevenster geopend.
Het kan zijn dat er in plaats van Object1004() een object met een ander getal
staat: dat is geen probleem.
Voer in het venster de volgende code in:
'declareer de variabele Teller (gehele getallen)
Dim teller as Integer
'hier begint de lus
'de variabele Teller loopt van 10 to 12
For Teller=10 to 12
'laat de huidige waarde van Teller zien
'in een popup venster
MsgBox Str(teller)
'einde van de lus
Next
De regels met met een enkel aanhalingsteken beginnen zijn zogenaamde
commentaarregels. Ze dienen er alleen voor om uit te leggen wat er in de volgende
regels gebeurd.
Met de regel Dim Teller as integer wordt een variabele aangemaakt.
20
Het op het scherm tonen van de getallen die in de lus doorlopen worden, gebeurt in dit
voorbeeld met een MessageBox (MsgBox).
Het nadeel is dat je steeds op de knop moet klikken om verder te gaan.
Met een List (klik op list in de toolbox) gaat dat handiger.
- Zet een list in je programma.
- Vervang de regel met MsgBox() door:
List1005.add( str(teller))
Het kan zijn dat de List jouw programma een ander nummer heeft dan 1005. Pas het
nummer in dat geval aan.
Je hoeft nu niet meer telkens op Ok te klikken!
Je weet nu voldoende om lussen zelf te kunnen programmeren.
21
4. NSD (Nassi-Shneidermann-diagrammen)
De structuur van een programma(deel) kun je in Nassi-Shneider-Diagrammen
vastleggen.
Er zijn vier verschillende onderdelen:
-
Start
Instructie
Keuze
Herhaling/Lus (While, For, Repeat-Until)
In de bijlage staat uitgelegd hoe je met een speciaal programma een mooi NSD kunt
tekenen. Op een toets moet je natuurlijk ook op papier een NSD kunnen tekenen.
Start
Het eerste symbool staat hieronder. In het vak staat de naam van het programma of de
routine.
Instructie
Daarna volgen 1 of meer instructies.
Keuze
Een keuze is ook een instructie, maar die ziet er natuurlijk anders uit. In dit geval
wordt met een normale instructie een getal ingelezen. Met de functie odd(N) (odd is
Engels voor oneven) wordt gekeken of het getal N oneven is. Afhankelijk van het
resultaat wordt iets op het scherm geschreven.2
Je ziet hier dat het ‘antwoord’ van de vraag Y (Yes) of N (No) kan zijn. Bij echte
programmeertalen is het vaak beter om je af te vragen of de voorwaarde Waar (True) of Onwaar
(False).
2
22
Soms wil je alleen in het linker- of het rechterdeel opdrachten uitvoeren. In dat geval
blijft dus één van de kolommen leeg.
Herhalingen/Lussen
Er zijn drie soorten herhalingen/lussen: While, For en Repeat-until. Die gaan we nu
achtereenvolgens bekijken.
while
While betekend in het Nederland 'zolang' .
Zolang Dorst {
DrinkWater
}
Bij de WHILE-lus wordt eerst gekeken of aan de voorwaarde voldaan is (in dit geval
teller>0). Als dat zo is worden de opdrachten binnen de lus uitgevoerd.
Het kan dus zo zijn dat de opdrachten binnen de lus nooit uitgevoerd.
23
24
In een NSD ziet de while eruit als een omgekeerde letter L.
opdracht 10
Welke getallen worden in het diagram hierboven achtereenvolgens op het
scherm geschreven?
Hieronder staat in echte programmeertalen beschreven hoe je een While-lus
programmeert. We nemen aan dat er een andere stukje programma is – dat Schrijf
heet – waarmee je een getal of een tekst op het scherm kunt schrijven.
NS-Basic
Delphi/Pascal
Small Basic
Teller=10
Teller:=10;
Do while teller>0 while teller>0 do begin
Schrijf(teller)
Schrijf(Teller);
Teller=teller-1
teller:=teller-1;
Loop
end;
Teller=10
While Teller>0
TextWindow.Writeline(Teller)
Teller=Teller-1
EndWhile
Opdracht 11
Programmeer deze twee lussen in Delphi en NS-Basic.
Denk eraan dat je:
 een variabele declareert
 de schrijf-opdracht vervangt door Writeln (Delphi) of MsgBox (NS-Basic)
 In Delphi heb je een Readln nodig om het programma iets te laten schrijven.
– Het getal moet in een tekenreeks (integer → String) omgezet wordt met
Str(Basic)
Terzijde 1: Heb je de details gezien? In Basic schrijf je =. In Pascal :=. In Pascal
eindigt bijna elke regel met een puntkomma, in Basic is dat niet nodig.
Terzijde 2: In Delphi is een Begin/End nodig om aan te geven wat in de lus zit. Als je
dat niet doet wordt alleen Schrijf(Teller) gelust.
teller:=teller-1 wordt dan pas uitgevoerd als de lus afgebroken wordt!
Terzijde 3:Begrijp je waarom het verschil maakt als je
25
teller:=teller-1;
Schrijf(Teller);
In plaats van
Schrijf(Teller);
teller:=teller-1;
schrijft?
terzijde 4: Je kunt in een schrijf-opdracht ook een berekening schrijven:
Schrijf(A*B+2)
Je kunt de uitkomst van die berekening ook eerst in een variabele bewaren.
D=A*B+2
Schrijf(D)
Het voordeel van de eerste methode is dat je geen extra variabele nodig hebt. Het
voordeel van de tweede methode is dat de uitkomst na de schrijf-opdracht opnieuw
gebruikt kan worden, omdat ze in de variabele D opgeslagen is.
Terzijde 5: wat gebeurd er als je de opdracht Teller=Teller-1 weglaat?
Bijkijk het onderstaande NSD en beantwoord dan de volgende vragen.
Opdracht 12
De eerste regel is nu 'teller=10'. Verander deze regel zo dat de lus nooit
uitgevoerd wordt.
26
Opdracht 13
Schrijf dit programma in elementaire instructies.
Ga er daarbij vanuit dat Schrijf() een elementaire opdracht is.
Opdracht 14
Welke getallen schrijft het programma als je de opdrachten Schrijf(teller) en
Teller=Teller-1 verwisseld?
Opdracht 15
Maak een NSD met een while dat de kwadraten van 1, 2, 3 en 4 berekent.
Opdracht 16
Schrijf een programma in Basic of Delphi dat de kwadreten van 1,2, 3 en 4
berekent.
27
for
Bij de FOR-lus kun je met een start- en eindgetal aangegeven voor welke waarden de
lus doorlopen wordt.
For betekent in het Nederlands ' Voor'.
Voor Getal is 1 tot en met 4
{
Schrijf het getal
}
In een NSD ziet een for-lus eruit als een omgevallen letter U.
Je ziet dat er niet Teller=Teller+1 staat. Dat doet de For automatisch.
Opdracht 18
Welke getallen worden in het diagram hierboven achtereenvolgens op het
scherm geschreven?
Opdracht 19
Schrijf ook dit programma in elementaire instructies.
Ga er daarbij vanuit dat Schrijf() een elementaire opdracht is.
Je ziet dat de getallen nu van klein naar groot geschreven worden.
In een echte programmeertaal ziet dat er als volgt uit:
Basic
for teller = 1 to 10
schrijf(Teller)
next
Pascal/Delphi
for teller:=1 to 10 do
Schrijf(Teller);
28
Als je in Pascal/Delphi meer dan 1 opdracht in de lus wilt uitvoeren moet je de
opdrachten tussen begin en end zetten:
Schrijf('De eerste kwadraten zijn:');
for teller:=1 to 10 do Begin
Getal:=Teller*Teller;
Schrijf(Getal);
End;
Opdracht 20
Maak een NSD met de for-lus dat de kwadraten van de getallen 1, 2, 3 en 4 op
het scherm schrijft.
Opdracht 21
Schrijf een programma in Basic of Delphi dat de kwadraten van de getallen 1
t/m 4 berekent.
Kun je bij een for-lus ook terugtellen?
In het NSD kun je dat eenvoudig oplossen door de voorwaarde te veranderen in
Teller=10 to 1.
In echte programmeertalen is er vaak nog een extra aanpassing nodig.
In Basic schrijf je step -1 achter de opdracht:
Basic
for teller = 10 to 1 step -1
schrijf(Teller)
next
In Pascal/Delphi schrijf je downto in plaats van to:
Pascal/Delphi
for teller:=10 downto 1 do
Schrijf(Teller);
29
Until (wordt ook wel ‘repeat-until’ genoemd)
Bij de REPEAT-opdracht worden de opdrachten binnen de lus altijd minimaal 1 keer
uitgevoerd. De controle of de lus nog een keer doorlopen moet worden vindt pas na de
eerste doorloop plaats
Repeat betekent in het Nederlands Herhaal:
Herhaal
DrinkWater
Totdat Geen Dorst
In een NSD ziet een Repeat eruit als een letter L.
.
In Basic maak je een Repea op de volgende manier:
Basic
Teller=10
Do Until teller=0
Schrijf(teller)
Teller=teller-1
Loop
In Delphi maak je een Repeat op de volgende manier:
Delphi/Pascal
Teller:=10;
repeat
Schrijf(Teller);
teller:=teller-1;
until teller=0;
30
Het valt op dat in Basic de Until opdracht voor het blok staat dat uitgevoerd wordt,
maar in werkelijkheid vindt de controle pas achteraf plaats. Delphi is in dat opzicht
duidelijker.
opdracht 22
Welke getallen worden in het diagram hierboven achtereenvolgens op het
scherm geschreven?
Hoe kun je de getallen in omgekeerde volgorde laten schrijven? Maak het NSD.
Opdracht 23
Schrijf dit programma in elementaire instructies.
Ga er daarbij vanuit dat Schrijf() een elementaire opdracht is.
Opdracht 24 (Ghihad)
Schrijf het NSD als Delphi/Pascal en Basic programma.
Opdracht 25
Maak een NSD van een programma dat de kwadraten van de getallen 1, 2, 3 en
4 op het scherm schrijft met een repeat.
Opdracht 26
Schrijf het programma van de vorige opgave in Basic of Delphi.
Opdracht 27
WHILE versus UNTIL
Het zal je misschien opgevallen zijn dat de voorwaarde bij While en Until het
omgekeerde van elkaar zijn.
Kun je uitleggen waarom dat zo is?
Terzijde 6: Een Repeat-until heeft niets te maken met de repeat-opdracht die je in
Logo tegen bent gekomen.
Een REPEAT uit LOGO is eigenlijk een soort FOR-lus. Je bepaalt namelijk vooraf
hoe vaak de lus doorlopen wordt.
In Basic of Delphi kun je de waarde van de for-variabele opvragen tijdens het
doorlopen van de lus. In LOGO kan dat niet.
Bij een WHILE of een REPEAT-UNTIL kan in de lus bepaald worden of de lus
afgebroken moet worden.
31
Je kunt de ene lus vaak in een andere vertalen. Hieronder staat een voorbeeld. Bekijk
dit voorbeeld kritisch!
Voorbeeld
while
Teller:=4;
while teller>0 do begin
teller:=teller-1;
getal:=sqrt(teller);
schrijf(getal);
end;
for
repeat
For teller:=3 downto 0 do begin Teller:=4;
getal:=sqrt(teller);
repeat
schrijf(getal);
teller:=teller-1;
end;
getal:=sqrt(teller);
schrijf(getal);
until teller=0;
Je ziet dat bij een While en een for een begin en een end om de lus heen staat. Het
is veilig om dat steeds te doen. Bij een repeat-lus is dat niet nodig. De begin/end zit
als het ware in de repeat/until ingebouwd.
Omdat je in dit geval omlaag telt heb je een for-downto-lus. Als je omhoog telt
heb je een for-to-lus.
Je ziet dat bij een while en repeat de waarde van de teller veranderd in de regel
teller:=teller-1;. Bij een for is dat niet nodig. Het verlagen van de teller zit
in downto ingebouwd.
opdracht 19
Schrijf de volgende herhaling als een For en als een Repeat-Until in Delphi:
x:=0;
while x<5 Do Begin
y:=x*x;
Schrijf(y) ;
x:=x+1;
End;
In veel gevallen wel een voorkeur voor 1 van deze drie soorten lussen.
Als je een hele reeks gehele getallen 1-voor-1 wilt doorlopen kies je een FORloop.
Als het blok zeker 1 keer doorlopen moet worden kies je een UNTIL-loop.
Als je vooraf wil bepalen of de lus wel/niet doorlopen moet worden kies je een
WHILE-loop.
32
Extra voorbeeld 1
Hier volgt nog een extra voorbeeld over lussen.
Stel, je wilt alle getallen van StartGetal tot EindGetal bij elkaar tellen. Als het
StartGetal 3 is en het Eindgetal 5, tel je dus de getallen 3, 4 en 5 bij elkaar.
Je kunt dat op de volgende manier doen:
-
-
Lees het startGetal in
Lees het Eindgetal in
Maak een variabele Som nul, hiermee ga je later de getallen bij elkaar tellen
Doorloop nu een lus waarmee je de getallen van StartGetal tot en met
Eindgetal bij Som telt. In Som staat dus steeds de som van de getallen die je
tot dusver bij elkaar geteld hebt.
Op het eind toon je de totale Som.
Het valt op dat je de variabele Getal niet hoeft op te hogen met 1: dat gebeurt
automatisch in de for-opdracht.
Je kunt deze lus ook met een While schijven:
De variabele Teller heeft dezelfde functie als de variabele getal in het programma met
de FOR-lus. Aan het begin van de lus wordt gecontroleerd of Teller<=EindGetal is.
33
Aan het eind van de lus wordt Teller met 1 opgehoogd.
Nu maken we hetzelfde programma nog eens met een Repeat-Until-lus.
Opdracht 25
Verwerk één van deze NSD´s tot een programma in elementaire instructies,
Basic of Delphi/Pascal.
Terzijde 1
Merk op dat de variabele die bepaalt of de lus afgebroken wordt (in dit geval is dat de
variabele teller) voorafgaand aan de lus een waarde moet hebben gekregen.
34
Extra voorbeeld 2
We zijn er bij dit programma van uitgegaan dat de gebruiker voor het startGetal een
kleiner getal invoerde als voor het eindGetal.
Als beide getallen gelijk zijn werkt het programma ook nog, maar als het eindGetal
kleiner is dan het startGetal werkt het programma niet meer.
Opdracht 20
Kun je uitleggen waarom?
We kunnen natuurlijk een controle inbouwen: als EindGetal<StartGetal worden de
twee getallen verwisseld.
We deze controle in het NSD opnemen. Als voorbeeld staat hier het NSD van de
While.
Verwisselen in het nsd opgenomen
35
Extra voorbeeld 3
Er komen natuurlijk ook andere lussen in programma’s voor, waarbij niet steeds 1 bij
een teller geteld wordt.
Een voorbeeld is het 3*n+1 probleem. Meer hierover kun je vinden op:
http://acm.uva.es/p/v1/100.html
De berekening bij dit probleem gaat als volgt:
-
neem een getal n
we stoppen als n=1
als n oneven is berekenen we n=3*n+1, anders n=n/2
Verwerk dit algoritme als oefening in een NSD. De uitwerking staat aan het einde van
de opdrachten.
Opdracht 30
Verwerk het nsd tot een programma in elementaire instructies, Basic of
Delphi/Pascal.
36
Opdracht 21
Bij de volgende opgaven moet je steeds een programma in BASIC en in
PASCAL/Delphi kunnen schrijven dat de gegeven getallen in de juiste
volgorde op het scherm schrijft. Je moet een lus gebruiken (anders krijg je een
wel erg simpel programma als Schrijf(2); Schrijf(3); Schrijf(4); etc.).
Je zou het kunnen proberen met elke van de drie lussen kunnen en ook nog
eens in beide talen. Er zijn dus bij elke opgave maximaal 3x2=6 uitwerkingen
mogelijk. Varieer een beetje met de lussen dus je gebruikt, zodat je niet alleen
een expert in while-lussen wordt. Op een toets moet je elk lus kunnen
schrijven.
a
b
c
d
e
f
Schrijf een programma dat de gehele getallen 2 tot en met 9 op het
scherm schrijft.
Schrijf een programma dat de gehele getallen 7 tot en met 4 op het
scherm schrijft.
Schrijf een programma dat de getallen 3, 5, 7 en 9 op het scherm
schrijft.
Schrijf een programma dat de getallen 14, 11, 8, 5 en 2 op het scherm
schrijft.
Schrijf een programma dat alle even getallen van 2 t/m 10000 op het
scherm schrijft.
Schrijf een programma dat alle drievouden van 999 t/m 3 op het
scherm schrijft.
Onderzoek met welke lussen het wel gaat en schrijf dat programma.
g
h
i
Schrijf een programma dat de kwadraten (1, 4, 9 en 16….) kleiner dan
100 op het scherm zet.
Hint: je kunt geen for gebruiken.
De rij van Fibonacci begint met 1 en 1. De getallen daarna zijn de som
van de twee voorafgaande getallen. Schrijf een programma dat alle
Fibonaccigetallen kleiner dan 100 op het scherm schrijft.
(hint: gebruikt twee variabelen om de twee laatste getallen te bewaren.
Verder heb je een variabele nodig om de som te onthouden).
Hint: je kunt geen for gebruiken.
Schrijf een programma dat de eerste 100 Fibonaccigetallen op het
scherm schrijft (hint: je hebt nog een extra variabele nodig: je moet het
aantal getallen dat je op het scherm geschreven hebt bijhouden).
Hint: je kunt geen for gebruiken.
37
opdracht 23
Een wielrenner trekt afhankelijk van de temperatuur een bepaald tenue aan.
Hij draagt altijd een korte broek, sokken, een bril, fietsschoenen en een helm.
Als de temperatuur 25 graden of hoger is, draagt hij verder een shirt met korte
mouwen. Beneden 25 graden draagt hij onder zijn shirt met korte mouwen een
termo-shirt. Bij 15 graden of lager draagt hij over dit alles een jasje met lange
mouwen. Als de temperatuur onder de 10 graden zakt trekt hij een extra lange
broek aan. Als het niet droog en/of kouder dan 5 graden is, trekt hij bovendien
nog overschoenen aan.
De korte broek heeft helpen3 die over het termo-schirt heen moeten, maar onder
het shirt met de korte mouwen of het jasje gedragen worden.
Het termo-shirt wordt onder het shirt met korte mouwen gedragen.
Het jasje wordt over het shirt gedragen.
De lange broek wordt over de korte broek gedragen.
Shirt's kunnen niet meer aangetrokken worden als de helm of bril al opgezet is.
Schoenen worden na de broeken aangetrokken, overschoenen na de schoenen.
Verwerk deze gegevens in een NSD en bewaar dit onder de naam fietsen.nsd
(Het programma NSD is al meer dan 10 jaar oud en kan niet met bestandsnamen
van meer dan 8 tekens omgaan).
Het valt je wellicht tegen dat er zoveel beschreven wordt in deze opdracht.
Vooral de laatste voorschriften/omschrijvingen kunnen natuurlijk weggelaten
worden als je uit gaat van ‘gezond verstand’. Het probleem is natuurlijk dat
‘gezond verstand’ geen exacte omschrijving is van hoe de wielrenner zijn tenue
draagt.
Het is in de informatica (maar ook bij andere wetenschappen) vaak pure
noodzaak om exact en volledig te zijn.
Ga er bij de volgende opdrachten vanuit dat je:
De wortel kun je berekenen met de opdracht sqrt (van het Engelse square root
dat vierkantswortel betekent). Bijvoorbeeld: a=sqrt(4)
Van een kommagetal kun je een geheel getal maken door alles achter de komma
weg te laten met de opdracht Int(). Bijvoorbeeld A=Int(2.3)=2. Je kunt die
natuurlijk ook met variabelen doen: A=Int(B)
En willekeurig kommagetal kun je laten kiezen met de opdracht Rand(). Dit
komt van het Engelse woord random wat willekeurig betekend).
Let op de haakjes achter Rand!
We gaan er vanuit dat er geen beperkingen voor dat getal zijn. Het kan dus 3,2343
zijn, maar ook –23.45678, nul of precies twee.4
3
Helpen zijn dingen die aan een broek vastzitten en over de schouders gedragen worden om te
voorkomen dat de broek zich in een ongewenste richting beweegt.
4
Bij ‘echte’ programmeertalen zet de opdracht A=Rand() in A een kommagetal tussen
0 en 1, bijvoorbeeld A=0.03022003. Als je met rand een willekeurige getal tussen 0 en 10 wilt maken
moet je met 10 vermenigvuldigen A=Int(10*Rand()). Als je met rand een willekeurige geheel getal
tussen wilt maken moet je Int() gebruiken. Bijvoorbeeld A=Int(10*Rand())
38
opdracht 24
Maak een NSD waarin je een programma beschrijft dat twee getallen inleest en
het product van die twee getallen op het scherm schrijft.
Bewaar dit NSD onder de naam product.nsd.
opdracht 25
Maak een NSD waarin je een programma beschrijft dat de wortel van een
ingelezen getal berekend en op het scherm schrijft.
Bewaar dit NSD onder de naam wortel.nsd.
Opdracht 26
Maak een NSD van een programma dat van een ingelezen getal bepaalt of het
gelijk is aan een eerder door het programma gekozen willekeurig geheel getal.
Bewaar dit NSD onder de naam gokken.nsd.
Opdracht 27
Maak een NSD waarin je een programma beschrijft waarmee iemand zijn
leeftijd kan invoeren. Als de ingevoerde leeftijd lager is dan dan jouw eigen
leeftijd, schrijft jouw programma “je bent jonger”. Als de ingevoerde leeftijd
hoger is schrijf het “Je bent ouder”, anders “we zijn even oud”.
Bewaar dit NSD onder de naam leeftijd.nsd.
opdracht 28
Maak een NSD voor het berekenen van de oplossingen van een kwadratische
vergelijking door middel van de abc-formule. De kwadratische vergelijking is
2
van de vorm ax bxc0.
Lees eerst a, b en c in. Bereken daarna de discriminant D.
Afhankelijk van de waarde van D zijn er 0, 1 of 2 snijpunten.
Bewaar je NSD onder de naam abc.nsd.
Opdracht 30
Maak een NSD voor een programma dat alle kwadraten tussen twee ingelezen
getallen op het scherm schrijft. De twee grenswaarden tellen mee.
Voorbeeld: als de ingelezen getallen 1 en 10 zijn, worden de getallen 1, 4 en 9
op het scherm geschreven omdat dit de enige kwadraten zijn, die niet kleiner
dan 1 of groter dan 10 zijn.
Bewaar je NSD onder de naam kwadraat.nsd.
Opdracht 32 (moeilijk!)
Maak een NSD van een programma dat van een ingelezen getal bepaald of het
een priemgetal is. Een priemgetal is een getal dat alleen deelbaar is door 1 en
zichzelf.
39
Hint 1: Onthoud in een variabele IsPriem of het getal priem is, of niet.
Het getal is priem als IsPriem=1.
Het getal is niet priem als isPriem=0
Hint 2: Als een getal D een deler van G is moet de uitkomst van de deling een
geheel getal zijn. Een getal is een geheel getal als X-int(X)=0. Bijvoorbeeld:
X=2.3, 2.3-int(2.3)=2.3-2=0.3
Bewaar je NSD onder de naam priem.nsd.
Opgave 33
Het Windows programma kladblok heeft in het menu Bestand onder andere de
functies Nieuw, Openen, Opslaan en Opslaan Als...
Maak een NSD voor deze functies. Houd rekening met de volgende keuzes (als die er
toe doen):
– Is er tekst ingevoerd?
– Is de tekst gewijzigd?
– Is er al eerder een bestandsnaam opgegeven?
– Bestaat er als een bestand onder dezelfde naam?
Opdracht 34
Werk (één van de) volgende algoritmen uit met een NSD.
conversies
decimaal → binair
binair → decimaal
decimaal → hexadecimaal
hexadecimaal → decimaal
binair → hexadecimaal
hexadecimaal → binair
compressie
Frequentietabel opstellen bij een zin
Huffman-boom opstellen
LZW comprimeren
LZW decomprimeren
Hint:
40
Bij het stroomdiagram voor opstellen van een Huffman-boom heb je wellicht hulp van
de volgende stappen:
– tabel met waarden
– neem de laagste twee waarden A en B
– haal A en B uit de tabel
– bereken C=A+B
– zet C in plaats van A en B in de tabel
– sorteer de tabel
– ga hiermee door zolang er meer dan 1 getal in de lijst staat.
Opdracht 35
Een lus schrijft willekeurig de getallen. De waarde is minimaal 1 en maximaal 20.
Als het getal 10 is moet de lus afgebroken worden.
– Maak een NSD voor deze lus
– Schrijf de programmacode voor deze lus is Delphi en Basic
Opgave 35
Maak een NSD voor het tekenen van een zeshoek.
Opgave 35
Maak een NSD voor het tekenen van een willekeurige veelhoek.
De gebruiker voert in hoeveel hoeken er getekend moeten worden.
Als het aantal groter dan twee is wordt de veelhoek getekend. Als het aantal hoeken
twee (of minder) is, wordt er een foutmelding op het scherm geschreven.
41
Strings
Een string is een tekenreeks. Voorbeelden zijn: “A”, “Brood”.
Ook cijfers of andere tekens kun je in een string opnemen: “[email protected]”,
“4HA”, “123”.
Je ziet dus dat 123 als getal is op te slaan (je kunt er dan mee rekenen), maar ook als
tekenreeks. In het laatste geval zijn het dus drie tekens '1', '2' en '3' die je achterelkaar
plakt.
Je kunt strings ook achteraf achterelkaar plekken met de opdracht +. Bij strings
betekent + dus niet optellen, maar achterelkaar plakken.
Zet het teken 'A' in de string S
S=”A”
Zet het woord “Brood” in de string S
S=”Brood”
Zet 'niets' in S (je noemt dit een lege string)
S=””
Plak twee strings achterelkaar
S=”Hallo ” + “wereld”
Je kunt strings ook met elkaar vergelijken. In Basic en Delphi ziet dat er als volgt uit:
Basic
If s=”A” Then
Schrijf(“De eerste letter van het alfabet”)
Delphi
If s='A' Then
Schrijf('De eerste letter van het alfabet');
Het belangrijkste verschil is dat in Basic een dubbel aanhalingsteken gebruikt wordt
en in Pascal/Delphi een enkel aanhalingsteken.
Je kunt ook controleren of een string voor of na een andere string in het woordenboek
zou komen te staan.
Basic
S=”Aap”
If S<”Brood” Then
Schrijf(“Aap staat voor Brood in het woordenboek”)
Else
Schrijf(“In dit geval wordt deze regel niet uitgevoerd”)
Endif
Delphi
S='Aap' ;
If S<' Brood' Then
Schfijf('App staat voor Brood in het woordenboek')
Else
42
Schrijf(In dit geval wordt deze regel niet uitgevoerd');
A<B
A staat voor B in het woordenboek
A=B
A en B gelijk
A>B
A staat na B in het woordenboek
Je kunt twee variabelen vergelijken:
Basic
C=”Y”
A=”H”+C
B=”Z”+C
If A<B Then Schrijf(A+”staat voor ”+B+” in het woordenboek)
Delphi
C:='Y';
A:='H'+C;
B:='Z'+C;
If A<B Then Writeln(A+' staat voor ' +B+' in het woordenboek');
Zie de noot onderaan deze bladzijde5
Opdracht 37
In je boek staat op bladzijde 46 een stroomdiagram voor de conversie van een
getal van het decimale naar de binaire talstelsel. Maak een NSD dat hetzelfde
algoritme beschrijft als het stroomdiagram.
Hint 1: Gebruik de functie Odd().
Hint 2: Je moet iets voor een bestaande sting plakken.
Bewaar je NSD onder de naam binair.nsd
Soms schrijven we strings (Bijvoorbeeld Schrijf(“Hallo”)) en soms getallen (Schijf(123). In
echte programmeertalen is er een duidelijk verschil. Het getal 123 moet namelijk eerst worden omgezet
in de string “123”. Dat gebeurt in Basic met de functie Str (Je schrijft dan Schrijf(Str(123)) en in
Delphi met IntToStr (Schrijf(IntToStr(123)). We gaan er voorlopig vanuit dat de opdracht Schrijf
gewoon alles kan schrijven wat we tussen de haakjes zetten.
5
43
Bijlage 1: Waar is de spronginstructie gebleven?
Bij de elementaire opdrachten ben je de sponginstructie tegengekomen. In NSD
gebruiken we die opdracht eigenlijk niet (bij het JAVA-programma om NSD's te
maken heb je gezien dat ze wel bestaat). Hoe zit dat?
Op de eerste plaats zijn er in gestructureerde programma’s geen regelnummers. Je
schrijf de code wel onder elkaar om de code leesbaar te houden. Zo een regel kun je
ook wel een nummer geven, maar dat is hooguit nodig om over die regel iets te
kunnen communiceren (bekijk regel 1234 nog eens goed). Voor het programma zelf
zijn regelnummers overbodig.
De spronginstructie bestaat als elementaire instructie echt in de processor. In moderne
programmeertalen wordt deze opdracht echter zoveel mogelijk vermeden. Zonder
spronginstructie kun je een programma veel overzichtelijker houden.
Een spronginstructie wordt ook wel een GOTO genoemd.
De wereldberoemde Nederlandse informaticus Edsger Dijksta schreef in de jaren 60
een beroemd artikel over het GOTO-statement: Go To statement considered harmful.
In Pascal/Delphi zit de GOTO nog steeds, al zul je hem zeer zelden nodig hebben als
je netjes programmeert.
Een korte geschiedenis van Sheidermann kun je op internet vinden:
http://www.cs.umd.edu/hcil/members/bshneiderman/nsd/
44
Bijlage 1: NSD’s zelf maken
Windows
Op de website vind je het programma NSD. Pak het zip-bestand in een mapje uit en
start het programma (nsd.exe).
Maak een nieuw NSD aan met de meeste linkse knop in de werkbalk.
We gaan een programma maken dat opeenvolgende getallen bij elkaar telt. Je bent het
eerder tegengekomen als extra voorbeeld bij de lussen. Je moet het NSD nu zelf
maken.
Geef het programma de naam SOM.
Je NSD ziet er dan zo uit.
45
We gaan nu een statement toevoegen. Klik op de bovenste knop in de lijst met NSDelementen en sleep met de muis tot de plek onder Som rood oplicht.
Geef de volgende beschrijving van de eerste instructie.
Opdracht 22
Maak nu zelf het NSD op de onderstaande manier na. Bewaar je NSD onder de
naam Som.nsd en zet het bij de uitwerking van deze opdracht op je logboek.
46
Java
Online is er ook een mooi programma waarmee je NSD’s kunt maken:
http://structorizer.fisch.lu/index.php?include=applet
De meest icoontjes worden pas actief als je met de muis in het gele gebied klikt.
Met het onderstaande icoontje in de bovenste regel kun je een instructie toevoegen.
Er opent zich dan een venster waarin je in het bovenste vak de instructie moet
invoegen.
47
In de tweede rij met icoontje zie je twee sets met symbolen. Links staan er met het
pijltje omhoog, recht met het pijltje omhoog. Het pijltje geeft aan of je voor (pijl
omhoog) of na (pijl omlaag) invoegt.
Probeer nu het onderstaande NSD te maken.
LET OP: De JAVA-Versie is geavanceerder dan het Windows-programma. Er vinden
allerlei controles plaats. Bijvoorbeeld:
-
De naam van het programma moet met hoofdletters geschreven worden
De naam van variabelen moet met hoofdletters geschreven worden
Waar wij een is-teken schrijven (A=3), moet je bij dit programma eigenlijk <=
(kleiner-dan-teken en een is-teken) schrijven zodat er een pijltje naar links
verschijnt.
Bij de menu optie Preferences>Language kun je de taal instellen. Bij
Preferences>Parser kun je instellen hoe je je de instructies wilt noemen. Deze
instellingen passen goed bij onze manier van werken.
48
Behalve de instructie, de IF, de WHILE, de REPEAT en de FOR zijn er ook nog
andere blokken te gebruiken. Je kunt de uitleg in het menu vinden.
De CASE is een keuze met meer dan 2 alternatieven.
De ENDLESS Loop is een lus die nooit eindigt.
Met een CALL start je een andere programma(deel)
En een JUMP is een Sprong.
49
Bijlage 3:Antwoorden
opdracht 1
4
opdracht 2
regel
1
2
3
4
5
opdracht
A=2
B=3
C=A
A=B
B=C
A
2
2
2
3
3
B
?
3
3
3
2
C
?
?
2
2
2
Dit programma verwisseld de inhoud van A en B.
opdracht 3
Bijvoorbeeld B<>0, B>0, B<0, B=1
Onjuist is bijvoorbeeld: B<=2, B>=2
opdracht 4
Drie keer (nl. voor A=3, A=2 en A=1, daarna is A=0 en wordt de lus afgebroken).
opdracht 5
In beide gevallen naar regel 2. De spronginstructie is dus totaal overbodig.
opdracht 6
regel
1
2
3
4
5
6
opdracht
A=3
B=0
B=B+1
A=A-1
IF A>0 JUMP 3
B=2*B
aantal maal
1
1
3
3
4
1
opdracht 7
We zijn bij de laatste instructie aangeland. Het programma is dus klaar.
50
opdracht 8
stap
1
2
3
4
5
6
7
8
9
regel
1
2
3
4
5
3
4
5
6
A
2
2
1
1
B
?
0
0
1
0
0
1
2
opdracht 9
opdracht 10
10,9,8,7,6,5,4,3,2,1
opdracht 10a
NSBasic
Dim Teller as integer
Teller=10
Do while teller>0
MsgBox(Str(teller))
Teller=teller-1
Loop
Delphi
Var Teller:integer;
Begin
Teller:=10;
while teller>0 do begin
Writeln(IntToStr(Teller));
teller:=teller-1;
end;
opdracht 11
Teller=0
51
opdracht 12
In dit stappendiagram gebruiken we IF teller<=0 om te bepalen of we moeten
stoppen.
1
2
3
4
5
6
Teller=10
IF Teller<=0 JUMP 4
Halt
Schrijf(Teller)
Teller=Teller-1
JUMP 2
Je kunt de opdracht Schrijf() niet meteen op regel 3 schrijven. In het onderstaande
voorbeeld is dat wel gedaan.
1
2
3
4
5
6
Teller=10
IF Teller<=0 JUMP 6
Schrijf(Teller)
Teller=Teller-1
JUMP 2
HALT
Als je de lus wel meteen na IF Teller … wilt laten beginnen moet je IF Teller<=0
gebruiken.
1
2
3
4
5
6
Teller=10
ALS Teller=0 JUMP 6
Schrijf(Teller)
Teller=Teller-1
JUMP 2
Halt
Het onderstaande programma is niet helemaal goed:
1 A=10
2 Schrijf(A)
3 A=A-1
4 IF A>0 JUMP 2
52
5 Schrijf("Einde")
Als je met A=10 gebruikt doet het programma precies hetzelfde, maar de controle
vind pas achteraf plaats. Dit is dus geen While, maar een Repeat-Until.
opdracht 13
1,2,3,4,5,6,7,8,9,10
opdracht 14
opdracht 15
1
2
3
4
5
Teller=1
Schrijf(Teller)
Teller=Teller+1
IF Teller<=10 JUMP 2
Halt
opdracht 16
10,9,8,7,6,5,4,3,2,1
opdracht 17
1
2
3
4
5
Teller=10
Schrijf(Teller)
Teller=Teller-1
ALS Teller>0 JUMP 2
Schrijf(“Einde”)
53
Opdracht 17 Ghihad
omschrijven naar Delphi
Var Teller : integer;
Begin
Teller:=10;
Repeat
Writeln(IntToStr(Teller));
//Schrijf(Teller);
Teller:=Teller-1;
Until Teller=0;
Writeln('Einde');
// Schrijf("Einde")
End;
Omschrijven naar Basic
Dim Teller as integer
Teller=10
Do Until Teller=0
MsgBox(str(Teller))
' schrijf(Teller)
' list1005.add(str(Teller))
Teller=Teller-1
Loop
Msgbox("Einde")
opdracht 18
Bij een while bepaalt de voorwaarde of je de lus (nog) een keer gaat uitvoeren. Bij
een repeat bepaalt de voorwaarde of je het herhalen van de lus gaat afbreken.
Of anders geformuleerd:
Bij de while bepaalt de voorwaarde of het programma met de lus doorgaat, bij de
repeat-until bepaalt de voorwaarde of het programma met de lus stopt.
54
opdracht 19
while
for
repeat-until
x:=0;
while x<5 Do Begin
y:=x*x;
Schrijf(y);
x:=x+1;
End;
For x:=0 to 4 do begin
y:=x*x;
schrijf(y);
end;
x:=0;
Repeat
y:=x*x;
schrijf(y);
x:=x+1;
until x>4; //>=5 is ook goed
Let erop dat de voorwaarde bij while (x<5) en until (x>4) het omgekeerde van elkaar
zijn.
Als je dit programma echt programmeert, moet je de variabelen nog declareren:
Basic
Dim X as Integer
DIM Y as Integer
Delphi
Var X:integer;
Y:integer;
extra voorbeeld 1
Hieronder staat de uitwerking van Leon in elementaire instructies:
met controle achteraf en een extra variabele als teller. Dit programma is een
uitwerking als repeat-until, omdat de controle achteraf plaatsvindt.
Repeat
1
2
3
4
5
6
7
jump 5
8
lees(a)
lees(b)
c=0
teller=a
c=c+teller
teller=teller+1
if teller<=b
halt
55
while, dus controle vooraf (zonder extra variabele). De variabele a wordt gebruikt om
het startgetal in te lezen en wordt daarna als teller gebruikt.
Als While
1
2
3
4
5
6
7
8
lees(a)
lees(b)
c=0
if a>b jump 8
c=c+a
a=a+1
jump 4
halt
while, controle achteraf, met extra variabele teller. Deze uitwerking lijkt het meeste
op het nsd.
1
2
3
4
5
6
7
8
9
lees(a)
lees(b)
c=0
teller=a
if teller>b jump 9
c=c+teller
teller=teller+1
jump 5
halt
Hieronder staat de uitwerking van while door Joost als Delphi-programma.
program extra;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
startgetal:
eindgetal :
som
:
teller
:
Integer;
Integer;
Integer;
Integer;
begin
Readln(startgetal);
Readln(eindgetal);
som := 0;
teller := startgetal;
while teller<=eindgetal do begin
som:=som+teller;
teller:=teller+1;
end;
56
writeln(som);
readln;
end.
Extra voorbeeld 2
{todo}
extra voorbeeld 3: 3*n+1
Deze opdracht is alleen met een while-lus te maken.
Bij een for-lus moet je weten hoe vaak de lus doorlopen moet worden en dat weet je
hier niet. Bij een repeat wordt de lus altijd één keer uitgevoerd, en dat is in dit geval
niet altijd zo (iemand kan n=1 invoeren: het programma is dan meteen klaar).
Hieronder staat de uitwerking als Delphi programma. Je hebt de opdracht odd() nodig
om te controleren of het getal oneven is.
Var n : integer;
begin
readln(n)
while n<>1 do begin
if odd(n) then
n:=3*n+1
else
n:=n/2;
end;
writeln(n);
readln;
End;
57
Hieronder staat het programma in NS-Basic.
Dim n as integer
' lees n in uit een field
n=val(field1005.text)
do while n<>
if odd(n) then
n=3*n+1
else
n=n/2
endif
' schrijf n in de lijst
list1006.add(str(n))
loop
list1006.add(str(n))
Tenslotte nog het programma in elementaire instucties. Dat is ingewikkeld omdat er
geen elementaire instructie is die bepaald of het getal oneven is.
We kunnen dat op drie manieren oplossen.
1) We nemen aan dat die instructie wel bestaat (je maakt je er dan een beetje vanaf):
1
2
3
4
5
6
7
8
9
10
lees(n)
if n=1 jump 10
if odd(n) jump 6
n=n/2
jump 7
n=3*n+1
schrijf(n)
jump 2
schrijf(n)
halt
2) we maken de instructie in een extra nsd zelf aan
In dit voorbeeld zetten we 0 in de variabele Odd als n oneven 0 en 1 als n even is.
In de controle van regel 3 moete dan staan: IF ODD(N)=1 JUMP 6
58
In elementaire instructies kun je die alsvolgt schrijven:
1
2
3
4
5
6
7
A=N/2
R=N-A*2
IF R=0 JUMP 6
O=1
JUMP 7
O=0
HALT
Je programma bestaat nu uit twee delen: het deel dat we onder 1) uitgewerkt hebben
plus het deel van dit onderdeel.
3) We voegen extra code toe die controleert of het getal even of oneven is.
In de lus wordt eerst de rest na deling door twee berekend. Waarschijnlijk herken je
het NSD van de tweede oplossing hier wel in.
59
1
2
3
4
5
6
7
8
9
10
Lees(N)
IF N=1 JUMP 10
A=N/2
R=A-N/2
IF R=1 JUMP 9
N=N/2
JUMP 9
N=3*N+1
JUMP 2
HALT
opdracht 20
De lus wordt maar 1x doorlopen, omdat Teller meteen al groter dan Eindgetal is.
opdracht 21
opdracht 22
nsd bijvoegen
opdracht 23
60
opdracht 24
opdracht 25
opdracht 26
De meeste beknopte oplossing is deze:
61
Als je alleen gehele getallen wilt hebben moet je voor Lees(A) de volgende regel
toevoegen: R=Int(R).
Omdat Rand() werkelijk alle mogelijke getallen maakt is het natuurlijk niet goed
mogelijk om het getal te raden. Daarom bouwen we een lus in dit ervoor zorgt dat
alleen gehele getallen groter dan 0 en kleiner of gelijk aan 20 (dus 1..20) gekozen
worden:
opdracht 27
Joost heeft een uitgebreide variant gemaakt waarbij zelfs tot op de dag bekeken wordt
wie jonger/ouder is.
62
opdracht 28
63
Opgave 30
Hieronder staan drie mogelijke oplossingen
Bij het linker diagram:
Lees de start- en eindwaarde in.
Bewerken van al deze getallen de wortel, zet die in Y.
Als Y=Int(Y) is Y een geheel getal (Je mag ook zeggen Y-Int(Y)=0).
In dat geval schrijven we het getal op het scherm.
Bij het middelste diagram:
Van het start- en eindgetal wordt de wortel berekend. Hiervan wordt de gehele waarde
genomen.
Dus als de getallen 1 en 10 zijn wordt 1 en 3.1 berekenend. Dat wordt 1 en 3.
Van deze drie getallen wordt het kwadraat berekend: 1, 4 en 9.
Bij het rechter diagram:
Er zit een probleempje in dit NSD: als het startgetal 2 is, is de wortel 1.4 en dat wordt
1 als je de gehele waarde hier van neemt. De berekening begint dus bij 1, terwijl het 2
moet zijn.
In het derde NSD is dat opgelost. Bij het eindgetal doet zich dat probleem overigens
niet voor!
64
Opdracht 31
opdracht 32
of (dit programma kijk meteen ook of Getal>2 is!)
65
En tenslotte nog de variant van Joost
66
{todo}
Break/exit for om een for af te breken
Small basic
dev-C
lite-C
programma maken om te oefenen met stappendiagrammen
67
Download