8 Schleifen

Zur Programmsteuerung sind neben Verzweigungen (vgl. Abschnitt 4. Die If-Then-Verzweigung) sogenannte Programmschleifen notwendig. Mit ihnen ist es möglich, einen Programmschritt mehrere Male zu durchlaufen.

1. Die While - Schleife

Im oben dargestellten Struktogramm kommt zum Ausdruck, dass die Anweisungen 1, 2, 3... wiederholt ausgeführt werden, und zwar so lange, wie die Bedingung erfüllt ist, die in der Kopfzeile gestellt wird. Man bezeichnet diese Schleife daher auch als "kopfgesteuerte" Schleife.

While not eof(datei) do begin
readln(name);
...
end;

2. Die Repeat - Until - Schleife

Im obigen Struktogramm wird die "fußgesteuerte" Schleife dargestellt: Die Anweisungen werden solange ausgeführt, solange die Bedingung erfüllt wird. Beachte, dass die fußgesteuerte Schleife mindestens einmal durchlaufen wird, während die Anweisungen in der kopfgesteuerte Schleife gar nicht ausgeführt werden, wenn die Bedingung falsch ist!

Repeat
Outtext(....)
...
Until Menu1.Item.Checked

3. Die For - Schleife ("Zählschleife")

Die For-Schleife bewirkt, dass die Anweisungen nach dosolange wiederholt ausgeführt werden, bis die Laufvariable den Endwert erreicht hat.

For laufer:=0 to 255 do begin
eingabe:=memo1.lines[laufer];
...
end;

Die Laufvariable muss von einem ordinalen Typ sein. So können beispielsweise die Buchstaben des Alphabets (vom Typ char) als Laufvariable verwendet werden:

For buchstabe:='A' to 'Z' do 
zaehlfeld[buchstabe]:=0

Beachte, dass eine einzelne Anweisung einer For-Schleife nicht zwischen begin und end gesetzt werden muss.

For-Schleifen sind sinnvoll, wenn von Anfang an bekannt ist, wie oft eine Schleife durchlaufen werden muss. Der Endwert der Laufvariable kann dabei ohne weiteres zur Laufzeit bestimmt werden:

For laufvariable:=1 to length(eingabe)do begin
...
end; 

Im letzten Beispiel wird der Endwert der Laufvariablen durch die Länge der behandelten Zeichenkette eingabe zur Laufzeit des Programmes bestimmt.

Schleifen können ineinander "geschachtelt" werden, das heißt, innerhalb einer Schleife kann eine weitere stehen...

For i:=1 to 100 do begin
for j:=1 to 50 do begin
wert[i,j]:=0; 
...
end;
end;

Im letzten Beispiel wurde ein neuer Variablen-Typ verwendet, ein Array. Arrays werden häufig mit Hilfe von For-Schleifen verarbeitet. Eine Zeichenkette (string) kann beispielsweise als eindimensionales Array verstanden werden. Will man auf die einzelnen Zeichen der Zeichenkette zugreifen, verwendet man einen Index (Wert oder Variable wird zwischen eckige Klammern gesetzt):

var eingabe: string;
laufvar: byte;
...
begin
for laufvar:=1 to length(eingabe) do begin
eingabe[laufvar]:=UpCase(eingabe[laufvar]);
... 
end;
 ...
end; 

Im obigen Beispiel wird jedes Zeichen der Zeichenkette eingabe einzeln in einen Großbuchstaben umgewandelt.

Ein zweidimensionales Array kann man sich am besten als ein Speicherfeld vorstellen, dessen Speicherplätze wie im ebenen Koordinatensystem durch zwei Indizes festgelegt werden:
[1,1] [1,2] [1,3] [1,4] [1,5] [1,6] [1,7] [1,8]
[2,1] [2,2] [2,3] [2,4] [2,5] [2,6] [2,7] [2,8]
[3,1] [3,2] [3,3] [3,4] [3,5] ...

Beachte, dass die beiden Zahlen zwischen den eckigen Klammern nur die Platznummer im Array festlegen! Mehrdimensionale Arrays werden durch die Anzahl der Indizes festgelegt. Der gesamte Speicherbereich wird bei der Variablendeklaration angegeben. Um etwa den Speicherplatz für 25 ganze Zahlen in einem eindimensionalen Array bereitzustellen, geht man so vor:

var 
zahlenfeld: array[1..25] of integer;

Als Index muss ein ordinaler Typ verwendet werden. Dies können somit beispielsweise ganze Zahlen oder geordnete Zeichen sein - wie etwa die alphabethische Ordnung der Buchstaben in der ASCII-Tabelle. Der Speicherplatz selbst kann von (nahezu) beliebigem Typ sein:

type
wort=string[30]
wortfeld=array[1..100]of wort
var
zaehlfeld: array['A'..'Z'] of integer;
wert: array[1..100,1..50] of word;
ganzzahlfeld: array[1..8,1..3] of integer;
substantiv:wortfeld;
wuerfel: array[1..10,1..10,1..10] of char;

Ordinale Typen:

Ordinale Typen sind eine Teilmenge der einfachen Typen und enthalten eine endliche Anzahl von Elementen.
Integer
-32768 .. 32767 2 Bytes
Byte
0 .. 255 1 Byte
Word
0 .. 65535 2 Bytes
Boolean
False(0), True(1) 1 Byte
Char
ASCII-Zeichen 1 Byte


Um nur einen Ausschnitt von Ordinalen Typen zu verwenden, wählt man einen sogenannten Teilbereichstyp. Die Definition eines Teilbereichstypen spezifiziert den kleinsten und den größten Wert des Teilbereiches:

1..10, 0..99

'A'..'Z'

Aufzählungstypen

werden bei der Typenvereinbarung explizit angegeben:
type
Farbe = (Kreuz, Pik, Karo, Herz)
Klasse = (Herwig, Gerti, Susanne, Gerhard,
Michael, Anita, Peter, Franz, Maria)

9 Zeichenketten

Eine Zeichenkette ist eine Folge von ASCII-Zeichen (vgl. ASCII-Tabelle von 0 .. 255). Die Zeichenkette kann in einer Programmzeile stehen oder in einer String-Variablen gespeichert sein. Schließlich können Zeichenketten zu einer Liste verbunden werden.

1. Zeichen (char)

Einzelne (alphanumerische) ASCII-Zeichen sind die Grundelemente jedes Textes. Einzelne Zeichen werden über die Tastatur eingegeben, einzelne Zeichen dienen zur Steuerung von Geräten, usw. Delphi stellt einen eigenen Variablen-Typ für solche Zeichen zur Verfügung, char. Der Typ char speichert ein einzelnes ASCII-Zeichen. Zeichenkonstanten werden zwischen einfache Anführungszeichen gesetzt, z.B. 'A', '3', oder '+' usw. Die Funktion Chr kann einen Integer-Wert in ein Zeichen mit dem entsprechenden ASCII-Wert umwandeln. Die Funktion Ord liefert den ASCII-Wert eines Zeichens.

Der Typ char zählt wie die Typen integer, longint, byte, word, boolean, etc. zu den ordinalen Typen (vgl. Indizierung eines Arrays, Abschnitt 8).

2. Zeichenketten (string)

Zeichenketten entstehen durch Kombination einzelner Zeichen. Zeichenketten werden zwischen einfache Apostrophe gesetzt:
'Informatik ist schön'

'''' Zwei aufeinanderfolgende Apostrophe stehen für ein Apostroph

'' Der Null-String enthält kein Zeichen.

Zeichenketten werden in Variablen gespeichert, die vom Typ eines Strings sind. Diese Stringtypen werden mit dem reservierten Wort string deklariert. Grundsätzlich wird damit eine Zeichenfolge mit einer dynamischen Länge (bis maximal 255 Zeichen) festgelegt. Ist eine konstante Länge gewünscht, so gibt man die Länge bei der Variablendeklaration explizit an:

const
CZeilenlaenge = 79
type
TVorname=string[25];
TFamname=string[35];
Tadresse=string[CZeilenlaenge];
TPLZ=string[6]

Um auf Zeichen in einem String zuzugreifen, verwendet man den String-Bezeichner und den Index des Zeichens (vgl. Abschnitt 8 For-Schleife). Um die Länge eines Strings zu bestimmen, verwendet man die Funktion length:

 For laufvariable:=1 to length(eingabe)do ...

Mit Zeichenketten können folgende Operatoren verwendet werden:
+ Zwei Zeichenketten werden aneinander gefügt (verkettet, vgl. die Funktion concat).
= Zwei Zeichenketten werden miteinander verglichen
<> Zwei Zeichenketten werden auf Ungleichheit überprüft
< Zwei Zeichenketten werden zeichenweise auf die Stellung der Zeichen in der ASCII-Tabelle überprüft (das im Alphabet weiter oben stehende Zeichen ist "kleiner" als das untere...)
> ... das im Alphabet weiter unten stehende Zeichen ist "größer" als das obere
<=
>=


3. Listen aus Zeichenketten (stringlist)

In vielen Fällen arbeiten Delphi-Anwendungen mit Listen aus Zeichenketten. Solche Listen beinhalten beispielsweise die Einträge in einem Listenfenster, die Textzeilen in einem Memofeld, die Liste der vom Bildschirm unterstützten Schriftarten, die Namen der Register auf einem Arbeitsblatt u.a. (vgl. Delphi-Hilfe). Obwohl diese Listen auf ganz verschiedene Arten verwendet werden, basieren sie auf dem gemeinsamen Objekt "String-Liste". Dadurch können Stringlisten etwa ausgetauscht werden. Die gängigsten Aufgaben, die in Verbindung mit Stringlisten ausgeführt werden, sind:

a) Manipulieren der Strings in einer Liste (Zählen - count, Zugreifen auf einen String durch Angabe des Index, Hinzufügen eines Strings - Add, Insert, Löschen eines Strings - Delete, u.a. - vgl. Delphi-Hilfe)

b) Laden / Speichern von String-Listen (LoadFromFile, SaveToFile, vgl. Delphi-Hilfe)

c) Erzeugen neuer Stringlisten (vgl. Delphi-Hilfe)

d) Hinzufügen von Objekten zu einer String-Liste (vgl. Delphi-Hilfe)

e) Arbeiten mit Objekten in einer String-Liste (vgl. Delphi-Hilfe)

Verwende die Online-Hilfe der Delphi-Entwicklungsumgebung! Der "Inhalt" gibt einen Überblick über alle Konzepte - mit "Suchen" können Informationen zu allen Begriffen nachgelesen werden!

Projekt "PSTATMEM"

Verwende ein Memofenster zur Eingabe eines Textes und bestimme die absolute und relative Häufigkeit der vorkommenden Selbstlaute! Die Texte sollen entweder über die Tastatur eingegeben oder aus ASCII-Dateien (Textdateien) geladen werden können.

Die nachstehend angeführte Prozedur zeigt den entscheidenden Programmausschnitt. Beachte die Vewendung der Strings und Stringlisten!

procedure TForm1.AuswertenClick(Sender: ...);
type tbuchstabe='A'..'Z';
tzaehlfeld=array[tbuchstabe]of longint;
var buchstabe:tbuchstabe;
zaehlfeld:tzaehlfeld;
laufer:integer;
eingabe:string;
zeile:byte;
gesamtzahl:integer;
begin
for buchstabe:='A' to 'Z' do 
zaehlfeld[buchstabe]:=0;
{Schleife wird 26 mal durchlaufen!}
gesamtzahl:=0;
for zeile:=0 to Memo1.Lines.Count do begin
{Count gibt die Anzahl der Zeilen zurück}
eingabe:=memo1.lines[zeile];
{Die Zeilen des Memofeldes werden zeilenweise in die Hilfsvariable
eingabe übertragen und durchmustert} 
for laufer:=1 to length(eingabe) do begin
eingabe[laufer]:=UpCase(eingabe[laufer]);
if (eingabe[laufer]>='A') and 
(eingabe[laufer]<='Z') then begin
{Nur falls tatsächlich ein Buchstabe vorliegt, soll gezählt werden}
inc(zaehlfeld[eingabe[laufer]]);
inc(gesamtzahl);
end;
end;
end;
a.text:=IntToStr(zaehlfeld['A']);
e.text:=IntToStr(zaehlfeld['E']);
...
g.text:=IntToStr(gesamtzahl);
proza.text:= 
FloatToStr(round(10000*zaehlfeld['A'] 
div gesamtzahl)/100);
...
end;