Informaticasite van het Lauwers College te Buitenpost                 © R.J. van der Beek
 

Hoofdstuk 6 Programmeren in Pascal

6.2. Tien sommen, strings, ASC-codes, arrays

  6.2.1 Tien sommetjes

Je kunt je programma's mooier maken door met kleur te werken.
De opdracht TEXTCOLOR(4); zorgt er voor dat de tekstkleur rood wordt.
En de opdracht TEXTBACKGROUND(14); heeft tot gevolg dat de achtergrondkleur geel wordt.

In IriePascal werk je met kleurnummers, en welke kleur bij welk nummer hoort zie je in de volgende tabel.

nummer kleur     nummer kleur
0zwart     8donkergrijs
1blauw     9lichtblauw
2groen     10lichtgroen
3cyaan     11lichtcyaan
4rood     12lichtrood
5magenta     13lichtmagenta
6bruin     14geel
7lichtgrijs     15wit

Verder is er een opdracht waarmee je de cursor naar elke gewenste plek van het scherm kunt sturen:
De opdracht gotoxy(5,10); heeft tot gevolg dat de cursor naar positie 5 van de 10-de regel springt.
(een MSDOS-scherm bestaat uit 25 regels van 80 posities)

Er is ook nog een opdracht waarmee je er voor zorgt da er maar een gedeelte van het scherm wordt gebruikt:
De opdracht WINDOW(10,3,70,20) ; heeft tot gevolg dat vanaf dat moment alleen het rechthoekige gedeelte van het scherm wordt gebruikt dat loopt van het punt (10,3) tot het punt (70,20). Het eerste punt is dus de linker-bovenhoek, en het tweede punt is het punt rechtsonder.

In het volgende programma worden een aantal van die opdrachten gebruikt.
Tik het over, laat het lopen en lees de uitleg eronder door.

PROGRAM rekenen;
VAR g1,g2,antwoord,aantalgoed,i: INTEGER;  
                  
BEGIN                                                      
   TEXTBACKGROUND(14); TEXTCOLOR(0); CLRSCR;       
   RANDOMIZE;
   aantalgoed:=0;                              
   FOR i:=1 TO 10 DO                                      
   BEGIN 
      TEXTBACKGROUND(0);      TEXTCOLOR(15);          
      g1:=RANDOM(100);        g2:=RANDOM(100);                   
      WRITE(g1:3,'+',g2:3,' = ');   READLN(antwoord);             
      IF (antwoord=g1+g2) THEN 
      BEGIN 
         GOTOXY(15,i);        TEXTBACKGROUND(15);     
         TEXTCOLOR(0);        WRITELN('Goed');           
         aantalgoed:=aantalgoed+1;                   
      END                                            
      ELSE 
      BEGIN
         GOTOXY(15,i);        TEXTBACKGROUND(14);    
         TEXTCOLOR(4);        WRITELN('Fout');             
      END;                                           
   END;                                                   
   WRITELN;                                               
   WRITELN('Je had er ',aantalgoed:2,' goed');
END.

Uitleg:

Er komen tien optelsommetjes.
Het aantal goede antwoorden wordt vastgelegd in de variabele aantalgoed.
  • Eerst heb je de initialisatie : aantalgoed:=0;
  • FOR i:=1 TO 10 DO ... zorgt ervoor dat het hele verhaal dat eronder staat 10 keer gebeurt.
    Je kunt goed zien welk stuk wordt herhaald: alles tussen de BEGIN en END die bij elkaar horen is ingesprongen, en de bijelkaar horende BEGIN en END staan recht onder elkaar.
  • WRITE(g1:3,'+',g2:3,' = '); zorgt er voor dat er een sommetje op het scherm verschijnt.
    Het begin van die opdracht: WRITE(g1:3); heeft tot gevolg dat het getal g1 wordt afgedrukt, en daarvoor worden drie tekens gebruikt. Als het getal bijvoorbeeld 17 is dan wordt er één spatie voor gedrukt, en als het getal bijvoorbeeld 8 is dan worden er twee spaties voor gedrukt.
    Als je de opdracht zonder :3 intikt, dus WRITE(g1);, dan worden er acht tekens voor het getal gebruikt (dus als het getal bijvoorbeeld 17 is dan worden er zes spaties voor gedrukt)

    (Als je een kommagetal hebt kun je ook bepalen hoeveel tekens er worden gebruikt. Als je de opdracht: WRITE(r:6:2); invoert dan wordt het getal r afgedrukt, en daarvoor worden zes tekens gebruikt, waarvan twee achter de komma)
  • IF (antwoord=g1+g2) THEN 
    BEGIN 
       GOTOXY(15,i);
       TEXTBACKGROUND(15);     
       TEXTCOLOR(0);    
       WRITELN('Goed');           
       aantalgoed:=aantalgoed+1;                   
    END
    Dit betekent het volgende:
    Als het ingetypte getal goed is (dus als g1+g2=antwoord) dan gebeurt er wat tussen de volgende BEGIN en END staat.
  • GOTOXY(15,i) staat er bij om er voor te zorgen dat het woordje "goed" achter het sommetje komt.
    Als GOTOXY(15,i) er niet bij zou staan dan zou het woordje "goed" op de volgende regel komen, omdat na READLN altijd naar de volgende regel wordt gesprongen.
  • aantalgoed:=aantalgoed+1; zorgt er voor dat de variabele aantalgoed met 1 verhoogd wordt.
  • De rest is hopelijk wel duidelijk.

  6.2.2 Een programma met string-opdrachten

Er zijn ook variabelen, die een woord kunnen bevatten; die moet je declareren als STRING.
(Of als het maar één letter is dan kun je het ook declareren als CHAR; een variabele van het type CHAR kan dus maar één teken bevatten)
Als je een variabele van het type STRING gebruikt, dan mag het maximaal 80 tekens bevatten.
Je kunt een variabele ook declareren als bijv. STRING[20], dan mag het beslist niet meer dan 20 tekens bevatten.

Het type STRING wordt gebruikt in het volgende programma.
Probeer het maar eens uit, en probeer te begrijpen wat er gebeurt.

PROGRAM som_jaofnee;                                              
                                                                  
VAR g1, g2, antwoord:INTEGER; 
    naam, jaofnee:STRING;                      
                                                                  
BEGIN 
    CLRSCR;
    WRITE('Hoe heet je ? '); 
    READLN(naam);                                 
    REPEAT
       g1:=RANDOM(10) + 20;
       g2:=RANDOM(10) + 20;                   
       WRITE(g1,'+',g2,'=');
       READLN(antwoord);             
       IF (antwoord=g1+g2) THEN 
          WRITELN('Goedzo')
       ELSE 
          WRITELN('Fout');
       WRITELN(naam,' wil je nog een sommetje (ja of nee) ');
       READLN(jaofnee);             
    UNTIL (jaofnee='nee');                      
            
END.

Uitleg:

De opdrachten na REPEAT zorgen er voor dat er een sommetje verschijnt.
En daarna wordt gevraagd of je nog een sommetje wilt.
Als je die vraag met 'ja' beantwoordt verschijnt er een nieuw sommetje.
Dan wordt het programmagedeelte tussen REPEAT en UNTIL herhaald.
Dat gaat net zolang door tot de variabele jaofnee de waarde 'nee' krijgt, dus tot de vraag met 'nee' wordt beantwoord.

Meer string-opdrachten
Er zijn speciale opdrachten, die betrekking hebben op het type STRING.
Als je een variabele w van het type STRING hebt, en we nemen als voorbeeld w='Jan van der Hoek' dan geldt:
  • length(w): de lengte van het woord, in het voorbeeld is dat 16
  • w[5]: Het 5-de teken van de variabele, in het voorbeeld is dat de letter v
  • copy(w,7,5): Een gedeelte van de variabele w, en wel vanaf de 7-de letter en dan de 5 tekens daarna.
    In het voorbeeld is dat n der
  • naam3:=naam1 + naam2;: De woorden van naam1 en naam2 worden achter elkaar gezet, en dat woord wordt toegekend aan naam3.
    Voorbeeld: Als naam1='Piet' en naam2='je' dan geldt: naam3='Pietje'
Een paar van deze string-opdrachten komen voor in het volgende programma.
Probeer het uit en lees de uitleg er onder door.

PROGRAM ees_tellen;                                              
                                                                  
VAR i,aantal_ees:INTEGER; 
    zin:STRING;                      
                                                                  
BEGIN 
    CLRSCR;
    WRITELN('Typ een regel van hoogstens 70 tekens in.'); 
    aantal_ees:=0;
    READLN(zin);                                 
    FOR i:=1 TO LENGTH(zin) DO                                  
        IF zin[i]='e' then aantal_ees:=aantal_ees+1;            
    WRITELN('In deze regel zitten ',aantal_ees,' ees.');              
END.

Uitleg:

Je weet dat je een variabele, die een woord (of zin) kan bevatten, moet declareren als STRING.
  • De opdracht READLN(zin); heeft tot gevolg dat er wordt gewacht tot er iets wordt ingetikt, en wat er is ingetypt wordt vastgelegd in de variabele zin
  • Nu is het de bedoeling dat er wordt geteld hoevaak de letter e er in voorkomt.
    En dat aantal wordt vastgelegd in de variabele aantal_ees
  • De opdracht aantal_ees:=0; is de initialisatie: in het begin is het aantal getelde ees natuurlijk nul.
  • De opdracht FOR i:=1 TO LENGTH(zin) DO ... heeft tot gevolg dat de opdracht erna net zovaak wordt herhaald als er tekens in de zin zijn.
  • De opdracht IF zin[i]='e' then aantal_ees:=aantal_ees+1; heeft tot gevolg dat als i de waarde 1 heeft gecontroleerd wordt of de eerste letter een e is. En als dat het geval is dan wordt de variabele aantal_ees met één vermeerderd.
    Als i de waarde 2 heeft wordt gecontroleerd of de tweede letter een e is. En als dat het geval is dan wordt ook nu de variabele aantal_ees met één vermeerderd.
    Zo gaat dat door, tot alle letters geweest zijn.
  • Tenslotte wordt dat aantal afgedrukt.

  6.2.3 ASC-codes

In het inwendige van de computer worden alle tekens, dus ook letters, voorgesteld door getallen.
Het teken A bijv. door het getal 65.
En dat getal wordt de ASCII-code van A genoemd.
Er zijn 256 codes voor 256 verschillende tekens.
De eerste 128 tekens (behalve de eerste 31) zijn de codes voor de normale tekens: de tekens die op het toetsenbord voorkomen. Dus de kleine letters, de hoofdletters, de leestekens, enz.
Ook de entertoets heeft een code (13) en ook de Escape-toets (27).
De eerste 31 codes horen bij de zogenaamde "stuur-tekens".

De laatste 128 zijn voor speciale tekens, die niet op het toetsenbord voorkomen.
Bijv. de griekse letters: a (code 224), b (code 225), enz.
Ook é (code 130), ë (code 137), enz. horen daarbij.
En dan nog ═ (code 205), ║ (code 186), ╗ (code 187) enz.

Een aantal Pascal-woorden, die je hierbij kunt gebruiken, zijn de volgende:
CHR(code) en ORD(teken).

Je kunt die bijvoorbeeld in de volgende opdrachten gebruiken:

WRITE CHR(65); De A verschijnt !
WRITE ORD('A'); Er verschijnt 65

Als je alle tekens wilt zien, dan kan dat m.b.v. het volgende programma:


PROGRAM tekens;

VAR i:INTEGER;

BEGIN
      CLRSCR;
      FOR i:=32 to 255 DO WRITE(i:6,':',CHR(i));
END.


En dan krijg je het volgende te zien:



Denk er om: bij 32 beginnen, want de eerste 31 kunnen niet worden afgedrukt !
Wat gebeurt er dan wel bij die eerste 31 ?
Bij WRITE(chr(13)); gaat de cursor een regel omlaag.
Bij WRITE(chr(7)); klinkt er een piepje !
Bij WRITE(chr(29)); gaat de cursor een plaats naar links, enz.

  6.2.4 Karakters, READKEY.

Je hebt speciale geheugenplaatsen, waarin maar één teken bewaard kan worden.
Die moet gedeclareerd worden als CHAR.
Dat doe je bijvoorbeeld als volgt: VAR teken:CHAR;
Denk er wel om, dat er met de variabele teken dan maar één teken tegelijk onthouden kan worden, dus niet een heel woord !
Dat teken kun je opvragen m.b.v. de opdracht READLN(teken).
Dan wacht de computer net zo lang tot er een teken is ingedrukt, en de entertoets, en dan wordt dat teken toegekend aan de variabele teken.

Het kan ook met de opdracht: teken:=READKEY;
Dan wacht de computer ook net zo lang tot er een toets is ingedrukt, en het teken dat bij die toets hoort wordt in de variabele teken opgeslagen, maar dan hoef je de entertoets niet in te drukken; en het teken verschijnt ook niet op het scherm.

Bij het gebruik van READLN wordt er altijd gewacht tot de entertoets is ingedrukt, en wat je intypt verschijnt ook op het scherm.

In het volgende programma wordt gebruik gemaakt van READKEY en van een variabele van het type CHAR.
Probeer het uit.


PROGRAM asccodes;

VAR teken:CHAR;

BEGIN
      CLRSCR;
      WRITELN('Elke keer als je een toets indrukt wordt de ASC-code gegeven');
      WRITELN('Wil je stoppen, druk dan op Esc');
      REPEAT
            teken:=READKEY;
            WRITE(teken,' '); WRITELN(ord(teken));
      UNTIL (ord(teken)=27);
END.


En dan krijg je bijvoorbeeld het volgende te zien:



  6.2.5 Boolese variabelen

Probeer het volgende programma uit. Lees ook de uitleg er onder door.

PROGRAM palindroom;                                              
                                                                  
VAR i,lw:INTEGER; 
    woord:STRING; 
    pal:BOOLEAN;                     
                                                                  
BEGIN 
    CLRSCR;
    Pal:=true;
    WRITELN('Typ een palindroom (dus achterstevoren hetzelfde)'); 
    READLN(woord); 
    lw:=LENGTH(woord);                                
    FOR i:=1 TO lw DO                                  
        IF woord[i]<>woord[lw+1-i] then pal:=false;            
    WRITELN('Het woord ', woord, ' is een palindroom is ', pal);              
END.

Uitleg:

In Pascal heb je variabelen die maar twee 'waarden' kunnen hebben: ze kunnen alleen de waarde true (=waar) en en de waarde false (=niet-waar) hebben. Die moeten worden gedeclareerd als BOOLEAN.
Hier is de variabele pal zo'n "boolese variabele".
  • De opdracht READLN(woord); heeft tot gevolg dat er wordt gewacht tot er iets wordt ingetikt, en wat er is ingetypt wordt vastgelegd in de variabele woord

    Nu is het de bedoeling er voor te zorgen dat als het ingetypte woord een palindroom is dat de variabele pal de waarde true krijgt, en anders false.
    (Een palindroom is bijv. het woord dood. Als je het omdraait blijft het hetzelfde)
  • De tweede opdracht in het programma is pal:=true
    Dat betekent dat er voorlopig wordt aangenomen dat het ingetypte woord inderdaad een palindroom is.
  • En dan volgt de controle.
  • Als de lengte van het woord bijv. 6 is, dan worden eerst de 1-ste en 6-de letter vergeleken.
    Als die niet gelijk zijn dan kan het geen palindroom meer zijn, en dan geldt dus: pal := false
    (woord[i]<>woord[lw+1-i]) betekent : de i-de letter en de lw+1-i-de letter zijn niet gelijk)
  • Dan worden de 2-de en 5-de letter vergeleken.
    Dan de 3-de en 4-de. Ook nog de 4-de en 3-de, dan de 5-de en 2-de en als laatste de 6-de en 1-ste
    Er wordt dus meer gecontroleerd dan nodig is.
  • Als alle letters gecontroleerd zijn wordt tenslotte afgedrukt of het wel of geen palindroom is.

  6.2.6 Arrays

Als de computer bijv. 20 cijfers van een leerling moet onthouden, dan is het lastig om daar allemaal verschillende variabele-namen voor te bedenken en te gebruiken.
In de wiskunde gebruik je dan vaak de notatie x1,x2,x3, enz. (dat noem je geïndiceerde variabelen).
In Pascal gebruik je dan de notatie x[1], x[2], x[3], enz.
Je noemt dat wel een rij variabelen, of in het engels: een array.
Als je dat wilt gebruiken, dan moet je dat van tevoren opgeven, dus declareren, en dat gaat bijv. zó:   
VAR x : ARRAY [1..20] OF REAL;

Probeer het volgende programma uit.
Er wordt 6000 keer met een dobbelsteen gegooid, en afgedrukt hoe vaak er een 1, 2, enz. is gegooid.
Lees ook de uitleg eronder door.

PROGRAM rijen;
VAR i, getal : INTEGER;
    aantal : ARRAY [1..6] of INTEGER;
BEGIN 
   FOR i:=1 TO 6 DO aantal[i]:=0;
   FOR i:= 1 TO 6000 DO
   BEGIN 
      getal := RANDOM(6) + 1;
      aantal[getal] := aantal[getal]+1;
   END;
   CLRSCR;
   FOR i:=1 TO 6 DO  WRITELN('Aantal keer ',i,' was ',aantal[i]);
END.

Uitleg:
FOR i:=1 TO 6 DO aantal[i]:=0; is de initialisatie
In het begin zijn de aantallen nog 0

getal := RANDOM(6) + 1; heeft tot gevolg dat de variabele getal een waarde krijgt die 1, 2, 3, 4, 5 of 6 kan zijn.
Immers RANDOM(6) levert een getal onder de 6, dus 0, 1, 2, 3, 4 of 5
Als je daar 1 bij optelt krijg je 1, 2, 3, 4, 5 of 6

De opdracht aantal[getal] := aantal[getal] + 1; doet het volgende:
Als er een 1 is gegooid, dan heeft de variabele getal de waarde 1, en dan wordt de opdracht aantal[1] := aantal[1]+1, dus het juiste aantal wordt 1 verhoogd.
Als er een 2 is gegooid, dan heeft de variabele getal de waarde 2, en dan wordt de opdracht aantal[2] := aantal[2]+1, en weer wordt het juiste aantal 1 verhoogd.


Een programma met namen van personen en cijfers
Er worden vijf namen gevraagd, met een cijfer.
En daarna worden die namen, met de cijfers, nog eens afgedrukt.

Probeer het uit, en probeer te begrijpen wat er gebeurt.

PROGRAM namen;
VAR i : INTEGER;
    naam : ARRAY [1..5] of STRING;
    cijfer: ARRAY [1..5] of REAL;
BEGIN 
   CLRSCR;
   FOR i:=1 TO 5 DO  
   BEGIN
       WRITE('Geef naam ', i:1, ' ');
       READLN(naam[i]);
       WRITE('Welk cijfer heeft ', naam[i],' ? ');
       READLN(cijfer[i]);
   END;
   
   WRITELN;
   WRITELN('Hier volgen nog eens de namen met de cijfers:');
   
   FOR i:=1 TO 5 DO  
   BEGIN
       WRITELN(naam[i], ' : ', cijfer[i]:4:1);
   END;
   
END.

Opgaven.
Maak nu opgave 13 en 14 van de opgaven van hoofdstuk 6 (Pascal)