Programmierkurs - Schuljahr 2008/2009

Delphi 7 - Programmcode

Beenden eines Programms (z. B. durch Klick auf den Ende-Button)
    application.terminate;



Beschriften eines Buttons
    Button1.Caption:='Neue Aufschrift';

Analog können auch andere Komponenten beschriftet werden.



Rechnen mit Werten, die in Edit-Komponenten stehen

Addieren der in Edit1 und Edit2 eingegebenen Werte und Speichern der Summe in Edit3.
    Edit3.Text:=IntToStr(StrToInt(Edit1.Text)+StrToInt(Edit2.Text));



Definition von Variablen

Variable werden definiert (=festgelegt) durch
    var  <Variable1 , Variable2 , Variable3> : <typ> ;
Das Wort "var" zeigt an, dass jetzt die Variablendefinition folgt.
Es folgen die Namen der Varibalen, die alle den gleichen Typ haben werden, jeweils getrennt durch ein Komma.. Es darf auch nur ein einziger Variablenname sein.
Danach folgt ein Doppelpunkt.
Dann wird der Typ genannt. Kennengelernt haben wir die Typen
    integer        :   ganze Zahl, z. B. -23, 0, 123
    extended    :    Fließkommazahl bzw. Dezimalzahl, z. B. 3.14 oder -6.1324657
                          große oder kleine Zahlen werden mit einem Zusatz (Zehner-Potenz) geschrieben, der angibt, um wie viel Stellen der Dezimalpunkt verschoben werden muss
                          Beispiele:  3.16854E3 = 3168.54   ;   6.24365E-4 = 0.000624365
Es folgt abschließend ein Semikolon.



Grundrechenarten mit Variablen
Die Inhalte zweier Edit-Komponenten werden als Variable gespeichert und dann mit einer Grundrechenart verknüpft.
Das Ergebnis wird in einer dritten Edit-Komponente ausgegeben.
Als Typ wird extended gewählt, damit man auch dividieren kann.


var x1, x2, y : extended;
begin
    x1:=StrToFloar(Edit1.Text);
    x2:=StrToFloat(Edit2.Text);
    y:=x1+x2;                              (oder y:=x1-x2;  oder y:=x1*x2;    oder y:=x1/x2;)
    Edit3.Text:=FloatToStr(y);
end;



Berechnung von Termen
Ein Term y, der aus einer Berechnung mit der Variablen x besteht, wird in Edit2 ausgegeben. In Edit1 wird der x-Wert eingegeben.
Beispiel:
01

var x, y : extended;
begin
    x:=StrToFloat(Edit1.Text);
    y:=(3*x-7)/((5*x+2)*(6*x-4));
    Edit2.Text:=FloatToStr(y);
end;



for-Schleife 
Soll ein bestimmter Programmcode (eine oder mehrere Anweisungen) eine bestimmte Anzahl mal wiederholt werden, so kann sinnvoll die for-Schleife verwendet werden.
Aufbau einer for-Schleife:
for <integer-Variable> := <Anfangswert> to <Endwert> do <Anweisung>
for, :=, to und do sind Schlüsselworte und müssen mit mindestens 1 Leerzeichen Abstand zu den benachbarten Werten geschrieben werden.
Die <integer-Variable> erhält zu Beginn den Wert von <Anfangswert> und wird bei jeder Wiederholung der <Anweisung> um 1 vergrößert, bis sie den <Endwert> erhalten hat.
In <Anweisung> kann der Wert von <integer-Variable> verwendet werden. Im ersten Durchlauf ist das der Wert <Anfangswert>, im letzten Durchlauf der Wert <Endwert>.
Soll mehr als eine Anweisung wiederholt werden, werden die zu wiederholenden Anweisungen zwischen begin und end gestellt (siehe Beispiel).

Beispiel 1 (Das kleine Einmal-Sieben wird im Memo-Fenster zeilenweise ausgegeben):
var i,Zahl:integer;
begin
   Zahl:=7;
   for i:=1 to 10 do
      Form1.Memo1.Lines.Add(IntToStr(7*i));
end;

Beispiel 2 (ein Muster wird auf der Image1-Komponente ausgegeben):
var i:integer;
begin
   for i:=0 to 100 do
   begin
      Form1.Image1.Canvas.moveto(0,4*i);
      Form1.Image1.Canvas.lineto(400,400-4*i);
   end;
end;



Anwendungen zur for-Schleife

Summenbildung (kleiner Gauss)
Der junge Gauss soll vom Lehrer die Aufgabe erhalten haben, die ersten 100 natürlichen Zahlen zusammenzuzählen.
Er hat dazu eine Formel entwickelt und konnte sehr bald das Ergebnis nennen.
Der Rechner erledigt diese Aufgabe mit einer for-Schleife:


var Zahl,Summe:integer;
begin
  Summe:=0;  //verwendete Variablen zuerst initialisieren (Anfangswert geben)
  for Zahl:=1 to 100 do
    Summe:=Summe+Zahl;
  Form1.Edit1.Text:=IntToStr(Summe);
end;

Berechnen einer Fakultät
Das Produkt der ersten natürlichen Zahlen nennt man Fakultät und schreibt es als Zahl mit einem Ausrufezeichen:  6!=1·2·3·4·5·6
Das Programm berechnet zu den Zahlen in Edit1 die Fakultät und zeigt sie samt allen vorherigen Berechnungen in einer Memo-Komponente an.


var Zahl, Produkt, Wert : integer;
begin
  Produkt:=1;
  Zahl:=StrToInt(Edit1.Text);
  for Wert:=1 to Zahl do
    Produkt:=Produkt*Wert;
  Form1.Memo1.Lines.Add(IntToStr(Zahl)+'! = '+IntToStr(Produkt));
end;



Zeichnen auf Image1

Folgende Zeichenelemente haben wir kennen gelernt:


Zufallszahlen
Beispiel: Füllen eines rechteckigen Bereiches der Breite 300 und der Höhe 100 mit zufällig verteilten Punkten
var i:integer;
begin
  for i:=1 to 1000 do
    Form1.Image1.Canvas.Pixels[random(300),random(200)]:=clblack;
end;


Warteschleife
procedure delay(x:integer);
var StartZeit,StopZeit:TTimeStamp;             // Zeit mit 1/100 sec. Genauigkeit
     Differenz:integer;
begin                                                       // now fragt die aktuelle Zeit ab,
  StartZeit:=DateTimeToTimeStamp(now);   // hier die Startzeit
  repeat
    StopZeit:=DateTimeToTimeStamp(now); // hier die aktuelle Zeit
    Differenz:=StopZeit.Time-StartZeit.Time;
    application.ProcessMessages;              // hier Notausstieg bei zu langer
    if Ende then exit;                                  // Wartezeit
  until Differenz>x;
end;
Anmerkung: Der Aufruf  sleep(<Zeit>)  leistet das gleiche. Statt <Zeit> setzt man als Parameter die Anzahl der Millisekunden ein, während derer gewartet werden soll.

repeat-until-Schleife

Weiß man nicht, wie oft eine Schleife durchlaufen werden soll und ist das Verlassen der Schleife durch eine Bedingung gegeben, so kann man günstig die repeat-until-Schleife benutzen.
Zwischen den festgelegten Worten repeat und until stehen die ANweisungen, die immer wieder wiederholt werden sollen.
Nach until folgt eine Bedingung. Ist diese Bedingung erfüllt, so wird die Schleife nicht mehr durchlaufen.

Beispiel: Addiert man die natürlichen Zahlen immer weiter (1+2+3+...), so wird die Summe irgendwann die Grenze 1000 überschreiten. Bei welcher natürlichen Zahl ist das der Fall?
var Zahl,Summe:integer;
begin
  Zahl:=0;
  Summe:=0;
  repeat
    Zahl:=Zahl+1;
    Summe:=Summe+Zahl;
  until Summe>1000;
  Edit1.Text:=IntToStr(Zahl);


 
Division

In delphi gibt es 2 Divisionen:
Bei 27/5 wird das Ergebnis durch eine Zahl mit Dezimalpunkt ausgegeben: 27/5=5.4
Bei 27 div 5 wird 27 durch 5 geteilt und der ganzzahlige Teil ist das Ergebnis: 27 div 5 = 5
Der Rest wird durch 27 mod 5 ermittelt: 27 mod 5 = 2



Verzweigung mit if ... then ... else

Hängt von eienr Bedingung ab, mit welcher Anweisung das Programm weiter machen soll, eignet sich die if ... then ... else-Anweisung:
Der Aufbau dieser Anweisung folgt diesem Schema:
if  <Bedingung>
  then begin <Anweisungen, die ausgeführt werden sollen, wenn die Bedingung erfüllt ist> end
  else begin  <Anweisungen, die ausgeführt werden sollen, wenn die Bedingung nicht erfüllt ist> end;

Beispiel: Ulam-Folge: Es werden nacheinander Zahlen aufgeschrieben, die nach folgender Regel gebildet werden:
Ist eine Zahl x gerade, so wird die nächste Zahl gebildet aus x div 2.
Ist eine Zahl ungerade, so wird die nächste Zahl gebildet aus 3·x+1

var Zahl,Nummer:integer;
begin
 try
  Zahl:=StrToInt(Edit1.Text);
  Nummer:=1;
  Memo1.Lines.Add(IntToStr(Nummer)+'      '+IntToStr(Zahl));
  repeat
    if round(Zahl/2)*2=Zahl
      then Zahl:=Zahl div 2
      else Zahl:=3*Zahl+1;
    Nummer:=Nummer+1;
    Memo1.Lines.Add(IntToStr(Nummer)+'      '+IntToStr(Zahl));
  until Zahl<2;
 except
   showmessage('Edit1 enthält keine Zahl');
 end;
end;



Bewegen einer Figur über den Bildschirm

Nach folgendem Schema kann man Figuren über den Bildschirm bewegen:
1. Den Bildschirm mit einer vorhandene Figur löschen
2. Die Koordinaten der Figur neu einstellen
3. Die Figur zeichnen.
4. bei 1. weiter machen

Es ist günstig, alle Punkte der Figur relativ zu einem einzigen Punkt anzugeben. Wird dieser Punkt auf dem Bildschirm verschoben, werden alle anderen Punkte und damit die Figur auch verschoben.

var x,i:integer;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  image1.Canvas.Brush.Style:=bssolid;
  image1.Canvas.Brush.Color:=clyellow;
  image1.Canvas.Rectangle(0,0,image1.Width,image1.Height);
  if (x<0) or (x>image1.Width) then i:=-i;
  x:=x+i;
  image1.Canvas.Brush.Color:=clred;
  image1.Canvas.Rectangle(x,round(sin(x/10)*100)+150,x+30,150);
end;

initialization
  x:=0;
  i:=1;



Bewegen eines "Balls" über den Bildschirm

Der Ball wird an den Kanten des Bildschirms reflektiert.
Vergleiche auch den oben stehenden Programmcode.

var x,y,dx,dy:integer;  // Diese Variablen gelten im gesamten Programm

const Breite=20;        // Breite ist als Konstante festgelegt
                                // Breite kann man nicht als Variable benutzen

procedure TForm1.BEndeClick(Sender: TObject);
begin
 application.Terminate;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 image1.Canvas.Brush.Style:=bssolid;
 image1.Canvas.Brush.Color:=clwhite;
 image1.Canvas.Ellipse(x,y,x+Breite,y+Breite);
 image1.Canvas.Brush.Color:=clred;
 x:=x+dx;
 y:=y+dy;
 if x<0 then dx:=-dx;
 if y<0 then dy:=-dy;
 if x+Breite>image1.Width then dx:=-dx;
 if y+Breite>image1.Height then dy:=-dy;
 image1.Canvas.Ellipse(x,y,x+Breite,y+Breite);  // Löschen des Balls
    // oder  image1.Canvas.Rectangle(0,0,image1.width,image1.height);  um den genzen Bildschirm zu löschen
end;

procedure TForm1.Button1Click(Sender: TObject);
begin     // mit diesem Programmteil kann man den Timer an- und abschalten
 timer1.Enabled:=not(timer1.Enabled);
 if Button1.Caption='Pause'
  then Button1.Caption:='Weiter'
  else Button1.Caption:='Pause';
end;

initialization
 x:=10;
 y:=10;
 dx:=2;
 dy:=2;




Die logischen Operatoren "and" und "or"

Wird im Programm eine Bedingung erwartet
(Beispiel: if <Bedingung> then <Anweisung1> else <Anweisung2>;),
so können mehrere Bedingungen mit den Operatoren "and" und "or" verbunden werden.

"and" steht dafür, dass beide angegebenen Teil-Bedingungen erfüllt sein müssen, damit die Bedingung insgesamt erfüllt ist.
Beispiel: (a=6) and (b>3)  ist dann richtig, wenn die Variable a genau den Wert 6 hat und die Variable b eine Zahl enthält, die größer als 3 ist.
a=6 und b=1 erfüllt die Bedingung nicht.
a=2 und b=8 erfüllt die Bedingung auch nicht.
a=6 und b=12 erfüllt die Bedingung.

"or" steht dafür, dass wenigstens eine der angegebenen Teil-Bedingungen erfüllt ist, damit die Bedingung insgesamt erfüllt ist.
Beispiel: (a=6) or (b>3)  ist dann richtig, wenn die Variable a genau den Wert 6 hat oder die Variable b eine Zahl enthält, die größer als 3 ist oder sowohl a=6 ist als auch b eine Zahl größer 3 ist.
a=6 und b=1 erfüllt die Bedingung, da a=6 zutrifft.
a=2 und b=8 erfüllt die Bedingung auch, da b>3 ist.
a=6 und b=12 erfüllt die Bedingung auch, da beide Teilbedingungen erfüllt sind.
a=2 und b=1 erfüllt die Bedingung nicht, da a nicht 6 ist und b nicht größer als 3 ist.



procedure

Einzelne Anweisungen kann man zu einem Modul kapseln und sie von anderer Stelle aus durch ihren Namen aufrufen.
Aufbau einer solchen Prozedur:

procedure <Name>;
begin
 <Anweisungen>
end;

Hinter <Name> kann noch in Klammern eingeschlossen eine Liste mit Variablennamen angeführt werden, deren Werte beim Aufruf der Prozedur übergeben werden.

Beispiel:

procedure Zeichne(x,y,Laenge,Hoehe:integer; Farbe:tcolor);
begin
 with form1.Image1.Canvas do
 begin
  brush.Color:=Farbe;
  rectangle(x,y,x+Laenge,y+Hoehe);
 end;
end;

procedure TForm1.BZeichneClick(Sender: TObject);
var i:integer;
begin
 for i:=1 to 10 do
  Zeichne(10*i,20*i,50*i,110-10*i,100000*i);
end;

Ausgabe des Programms:  01
Herunterladen des Programms mit Klick auf den Link oder das Bild.



Parameterübergabe bei Prozeduren und Funktionen

Zunächst eine vollständige Prozedur zur Berechnung von Potenzen der Art ab :

procedure ahochb (a:extended; b:integer; var Potenz:extended);
var i:integer;
begin
  Potenz:=1;
  for i:=1 to b do
    Potenz:=Potenz*a;
end;

An einer anderen Stelle im Programm kann man diese Prozedur aufrufen z.B. durch
   ahochb (Basis, Exponent, Ergebnis);
wobei die Variablen "Basis" und "Ergebnis" als extended und "Exponent" als integer deklariert werden.
Beim Aufruf müssen "Basis" und "Exponent" gültige Werte beinhalten.
"Ergebnis" bekommt seinen Wert aus der Prozedur.
In der Reihenfolge, wie es beim Aufruf in der Klammer angegeben ist, erhalten die Variablen in der Prozedur ihre Werte.
Die Werte a und b können in der Prozedur ruhig verändert werden. Im Hauptprogramm bleiben die Variablenwerte für "Basis" und "Exponent" erhalten.
Vor "Potenz" steht var. Das bedeutet, dass diese Variable zunächst den Wert von "Ergebnis" bekommt und dann den neuen Wert an "Ergebnis" übergibt. Dabei wird der alte Wert von "Ergebnis" überschrieben.

Man kann die Prozedur auch als Funktion schreiben. Dann muss die Kopfzeile heißen:
function ahochb (a:extended; b:integer) : extended;
Das heißt, dass dem Funktionsnamen ein Datentyp zugeordnet wird.
Aufgerufen wird dann die Funktion z.B. bei der Rechnung y=3+25-7 durch 
y:=3 + ahochb(2,5) - 7



Felder

Sollen in einem Programm Messreihen verarbeitet werden, macht es wenig Sinn, für jeden Messwert eine eigene Variable zu definieren.
Man fasst stattdessen viele Werte unter einem Variablennamen zusammen und unterscheidet die Werte durch Indizes.

Beispiel:
var Werte:array[0..10] of integer;
Eine Variable mit Namen "Werte" wird definiert, unter der auf 11 verschiedene Speicherstellen zugegriffen werden kann: Werte[0], Werte[1], ... ,Werte[9], Werte[10]
In allen 11 Speicherstellen kann jeweils eine integer-Zahl abgelegt werden.