Inhalt
Compiler
Programmieren
Datentypen,
Variablen,
Standardfunktionen
Logik
Verzweigung,
Strukturierung
Schleifen
Felder (Arrays)
Verteiler: CASE
Zeichenketten
(Strings)
Textdateien
Module
(Prozeduren,
Funktionen)
Anhang
(Operatoren,
abgeleitete
Funktionen)
|
|
Strings
Der Typ STRING ist zwar schon angesprochen worden; er beinhaltet aber eine
Menge von Eigenschaften und soll deswegen an dieser Stelle gesondert betrachtet
werden.
Zunächst die Einbindung des Typs STRING in die Typen von PASCAL.
Was ein String ist und wie er im Adressraum der Maschine grundsätzlich
abgelegt wird, ist schon besprochen worden. Allerdings fehlt noch die Verbindung
zu PASCAL. Im ursprünglichen Standard von Nikolaus Wirth wurde der
Name "string" zwar schon eingeführt, da auch zu diesem Zeitpunkt schon
klar war, daß man ohne diesen Typ nicht auskommt; er belegte aber
keine eigene Typdefinition. Ein String wurde definiert als:
"Sequences of characters enclosed by quote marks...",
also Zeichenfolgen in Hochkommata. Zurückgeführt wurde diese
Konstruktion auf eine spezielle Form eines Feldes, nämlich das PACKED
ARRAY. Der Zusatz PACKED bedeutet einfach, daß die Elemente am Ende
eines Feldes, die nicht gebraucht werden, im Adressraum der Maschine auch
keinen Platz belegen. Ist zum Beispiel ein Feld mit 10 Elementen vordefiniert,
wobei nur die ersten 3 Felder belegt sind, bedeutet dies, daß die
restlichen 7 unbenutzten Feldelemente im Adressraum der Maschine auch nicht
eingerichtet werden. Man spart dadurch natürlich Platz. Dementsprechend
war der Typ String definiert als:
TYPE string = PACKED ARRAY [1..n] OF char;
wobei n die festzulegende, maximale Länge eines Strings darstellt.
Um einen String auf den Bildschirm zu bringen, braucht man dann die Hilfe
einer Schleife. Irgendwo steht dann die Anzahl der tatsächlich belegten
Feldelemente, nennen wir sie x:
FOR i := 1 TO x DO
write (s [i]);
writeln;
Der Sondertyp des "gepackten" Feldes spielte bei Microcomputern keine Rolle
mehr, da man wegen der geringen Speicherkapazität älterer Modelle
sowieso automatisch "packte", also komprimierte, wo dies möglich war.
So ist das Wort PACKED zwar in allen Compilern noch zugelassen, hat aber
meist keine Wirkung mehr. In TurboPASCAL wird immer "gepackt".
Der Typ STRING ist in TurboPASCAL so definiert:
TYPE string = ARRAY [0..n] OF char;
Dabei steht im Element 0 die aktuelle Länge des Strings. Das Wort
STRING ist, im Gegensatz zu allen anderen Typnamen, ein reserviertes Wort
und wird deshalb in diesem Kurs, soweit es den Typnamen betrifft, durchgehend
groß geschrieben.
Der Typ STRING
Eine Variable vom Typ STRING wird folgendermaßen definiert:
VAR <variable>{,<variable>} : STRING [<länge>];
Beispiel:
VAR name : STRING [30];
Man kann der Form der Deklaration die Herkunft vom Array noch gut ansehen.
In der eckigen Klammer hinter dem Wort STRING ist die maximale Länge
des Strings angegeben.
TurboPASCAL: Die maximale Länge darf 255 nicht überschreiten.
Ab Version 5.0: Läßt man die Längenangabe weg, wird die
Länge auf 255 festgesetzt.
Da der Typ STRING eigentlich ein Array ist, kann man auf die einzelnen
Zeichen aus dem String wie bei einem Array zugreifen. Es ist zwar nicht
die feine Wirth'sche Art, aber es ist oft handlicher, als die Stringfunktionen
zu benutzen, die dasselbe machen, aber wesentlich
längere Ausdrücke ergeben. Angenommen, die Variable aus dem
gerade besprochenen Beispiel hätte einen Inhalt:
name := 'Donaudampfschiff';
Wollen wir nun einen Buchstaben (also ein Feldelement) herauspicken, sagen
wir das zweite "a" (7. Buchstabe), dann kann man das so formulieren (in
einer Zuweisung an eine Variable "c" vom Typ char):
c := name [7];
Achten Sie aber darauf, daß es unter Umständen Compiler gibt,
die das nicht zulassen! In TurboPASCAL geht es jedenfalls.
Eine andere Besonderheit bei dieser Methode tritt bei der Benutzung
eines Stringfeldes auf. Auch der Typ STRING läßt die Benutzung
eines Feldes zu. Vergleichen wir zwei Felder, ein "eindimensionales" STRING-Feld
und ein zweidimensionales char-Feld (In Wahrheit sind natürlich beide
zweidimensional!). Die Kommentarzeilen enthalten den Hinweis auf die Funktion
und Reihenfolge der Dimensionen.
Beispiel:
VAR seite1 : ARRAY [1..25] OF STRING [80]; (*** zeilen, spalten ***)
seite2 : ARRAY [1..80,1..25] OF char; (*** spalten,zeilen ***)
Wie wird nun ein Feldelement aus den entsprechenden Feldern selektiert?
Betrachten wir die Koordinaten 50. Spalte und 17. Zeile :
write (seite1 [17] [50]);
write (seite2 [50,17]);
Die Reihenfolge beim Feld "seite2" ist deswegen so gewählt, weil sie
der üblichen Reihenfolge von Koordinaten entspricht (zuerst horizontale,
dann vertikale Position). Sie kann bei Bedarf und Geschmack leicht ausgetauscht
werden.
Wichtig bei der Selektion des Feldelements ist die Tatsache, daß
das Feld "seite1" getrennte Koordinatenangaben besitzt, da das Feld formal
nur eindimensional ist. Um in dem String (Feldelement) "seite1 [17]" den
50. Buchstaben zu selektieren, muß das formal durch die angehängten
Feldklammern ausgedrückt werden.
Solche STRING-Felder sind bequem bei der Bearbeitung von Texten auf
dem Bildschirm; es sind allerdings die Schwierigkeiten zu beachten bei
der Benutzung.
Wer für "saubere" Programmierung ist, sollte bei Bedarf dann auf
die entsprechenden (und im nächsten Abschnitt besprochene) Standardtextfunktion
"copy" zurückgreifen, wo vorhanden.
Es gibt auch einen Operator für diesen Typ: Die "Addition" von
Strings, auch Konkatenation genannt. Damit werden verschiedene Strings
hintereinander gehängt und zu einem String verschmolzen:
Beispiel:
'Hans' + ' ' + 'Dampf'
ergibt den String
'Hans Dampf'.
Standardtextfunktionen und -prozeduren (TurboPASCAL)
Abweichend von der bisherigen Tendenz sollen jetzt einige notwendige Funktionen
und Prozeduren besprochen werden, die im Wirth'schen Standard fehlen, da
sie mehr oder weniger leicht nachträglich einzubauen sind. Bequemerweise
sind sie in den meisten Dialekten, so zum Beispiel in TurboPASCAL, schon
implementiert.
Zunächst die Funktionen (Zuweisung in den Beispielen erfolgt an
eine STRING-Variable "resultat" bzw. an eine integer- Variable "x"):
Zusammensetzen von Strings: concat
Allgemeine Form: concat (<string>,<string>{,<string>})
Erläuterung: Es können beliebig viele Strings konkateniert
werden. Sie werden in der Reihenfolge ihres Auftretens zusammengesetzt.
Eingabetyp/Ausgabetyp: STRING/STRING
Beispiele:
resultat := concat ('Dampf','schiff')
ergibt: 'Dampfschiff'
writeln (concat ('A','B','C');
ergibt: 'ABC'
Extraktion einer Zeichenkette aus einer anderen: copy
Allgemeine Form: copy (<string>,<position>,<länge>);
Erläuterung: In <position> gibt ein integer-Ausdruck die Anfangsposition
des zu extrahierenden Strings an, in <länge> steht die Anzahl der
Zeichen, die ab <position> extrahiert werden sollen.
Eingabetyp/Ausgabetyp: STRING/STRING
Beispiele:
resultat := copy ('Knochen',2,4);
ergibt: 'noch'
writeln (copy ('Ensamble',2,3));
ergibt: 'nsa'
Achtung: Wenn man versucht, mit Hilfe von copy ein Zeichen
aus einem String zu extrahieren, bekommt man einen String der Länge
1, nicht eine char-Konstante! Diese beiden Typen sind nicht zuweisungskompatibel.
Berechnung der Stringlänge: length
Allgemeine Form: length (<string>)
Erläuterung:Zählt die Zeichen eines Strings und weist die
errechnete Zahl einer integer- Variablen zu.
Eingabetyp/Ausgabetyp: STRING/integer
Beispiele:
resultat := 'Donaudampfschiff';
x := length (resultat);
ergibt: integer-Wert 16 in "x"
writeln (length (resultat));
ergibt: 16 auf dem Bildschirm
Suche nach String in einem anderen String: pos
Allgemeine Form: pos (<string1>,<string2>)
Erläuterung: sucht <string1> in <string2>. Bei Erfolg wird
die Position des ersten Buchstabens von <string1> in <string2> als
integer-Wert angegeben, bei Mißerfolg wird eine 0 zurückgegeben.
Eingabetyp/Ausgabetyp: STRING/integer
Beispiele:
x := pos ('ist','Jurist');
ergibt: 4 in "x"
x := pos ('wissen','Jurist');
ergibt: 0 in "x"
writeln (pos ('lala','Oghelala'));
ergibt: 5 in "x"
Bleiben noch die Prozeduren:
Löschen eines Strings in einem anderen: delete
Allgemeine Form: delete (<string>,<position>,<länge>);
Erläuterung: Löscht eine Zeichenkette ab <position> der
Länge <länge> aus <string>. <position> und <länge>
sind integer-Ausdrücke, <string> ist vom Typ STRING. Ist <position>
größer als die Gesamtlänge von <string>, wird nichts
gelöscht; überschreitet <länge> + <position> die Gesamtlänge
von <string>, werden nur die innerhalb von <string> liegenden Zeichen
gelöscht. Ist <position> größer als 255 oder kleiner
als 0, wird eine Laufzeitfehlermeldung ausgegeben. Das Ergebnis steht in
<string>.
Beispiele:
delete ('Sparschwein',8,1)
ergibt: 'Sparschein'
delete ('Programmierer',9,5);
ergibt: 'Programm'
Einfügen eines Strings in einen anderen: insert
Allgemeine Form: insert (<string>,<string>,<position>);
Erläuterung: Fügt den ersten <string> in den zweiten <string>
an der Stelle <position> ein. Die <string>s sind vom Typ STRING,
<position> ist ein integer-Ausdruck. Ist <position> größer
als die Länge des zweiten <strings>, so wird der erste an den zweiten
angehängt. überschreitet das Ergebnis die definierte Maximallänge
des Zielstrings, so wird am Ende entsprechend abgeschnitten. Ist <position>
größer als 255 oderkleiner als 0, erfolgt eine Laufzeitfehlermeldung.
Das Ergebnis steht im ersten <string>.
Beispiele:
resultat := 'Donauschiff';
insert ('dampf',resultat,6);
ergibt: 'Donaudampfschiff' in "resultat"
Umwandlung numerische Variable/String: str
Allgemeine Form: str (<numerischer ausdruck>,<string>);
Erläuterung: Wandelt einen integer- oder real-Ausdruck in einen
String um. Im Gegensatz zu einem numerischen Ausdruck kann mit einem String
nicht mehr gerechnet werden; es sind jedoch weitgehende Manipulationen
im Format möglich. Der <numerische ausdruck> kann wie in einer
write-Prozedur schon vorformatiert übergeben werden.
Beispiele:
x := 3.141592;
str (x:2:4,resultat);
ergibt: ' 3.1415' in "resultat"
x := 23;
str (x:5,resultat);
ergibt: ' 23' in "resultat"
Umwandlung String/numersiche Konstante: val
Allgemeine Form: val (<string>,<numvar>,<code>);
Erläuterung: Der <string> wird nach Zeichen untersucht, die
eine sinnvolle numerische Konstante ergeben. Der gesamte <string> muß
den Regeln über den Aufbau einer numerischen Konstante entsprechen,
da sonst keine Umwandlung erfolgt. <numvar> ist eine integer- oder real-Variable,
<code> ist eine integer-Variable. Hat die Umwandlung geklappt, steht
in <numvar> die numerische Konstante, in <code> eine 0. Konnte die
Umwandlung nicht erfolgen, so steht in <code> die Position des ersten
Zeichens in <string>, das nicht paßte, der Inhalt von <numvar>
ist undefiniert.
("wort" ist vom Typ STRING, "betrag" vom Typ real, "error" vom Typ integer):
Beispiele:
wort := '2.7182';
val (wort,betrag,code);
ergibt:
betrag = 2.7182
code = 0
wort := '2.3E7';
val (wort,betrag,code);
ergibt:
betrag = 23000000
code = 0
wort := ' 23 ist eine Zahl';
val (wort,betrag,code);
ergibt:
betrag = (undefiniert)
code = 1
Unterschied char - STRING
Wie wir schon besprochen haben, darf man einer Variablen vom Typ STRING
den sogenannten Leerstring zuweisen; das ist der "Nullstring" mit der Länge
Null. Nun könnte man meinen, da STRING und char sehr nahe miteinander
verwandt sind, ist es auch möglich, einer Variablen vom Typ char den
Leerstring zuzuweisen, was ja auch sehr bequem wäre. Doch das geht
leider nicht. Um zu verstehen, warum das so ist, sollen hier die beiden
Methoden der Abspeicherung gezeigt werden. Wir gehen von einem String der
Länge 1 und einer char- Variablen aus:
PROGRAM test;
VAR c : char;
s : STRING [1];
BEGIN
c := 'A';
s := 'A';
END.
Typen char, STRING
Da eine char-Variable nur aus einem Byte des Maschinenadressraumes besteht,
muß (!) sie immer einen definierten Inhalt haben. Beim String wird
das erste Byte im Maschinenadressraum nicht als zum String gehörig
interpretiert, sondern als Information über den Status; deswegen ist
hier der Leerstring möglich. Der Variablen "c" im Beispiel darf also
nicht der Leerstring zugewiesen werden, da es ja auch kein Zeichen im Zeichensatz
des Computers gibt, das kein Zeichen ist.
|