Sammlung und Verarbeitung von Daten mit Arrays und Records
Auch wenn Arrays und Records zwei ganz unterschiedliche Themen sind, sind beide dennoch eine Erweiterung von
Variablen und Konstanten, da Arrays und Records in gewisser Weise Sammlung von Daten darstellt. Arrays ist
die Sammlung von Daten des gleichen Datentypes, wobei Records eher eine Art Objekt darstellt, das verschiedene
Datentypen enthalten kann.
Arrays:
Ein Array ist eine statische Liste, welche Werte eines vorbestimmten Types enthalten kann. Das ganze stellt
man sich am besten so vor: Man hat eine Straße (=Array) mit gleichen Häusern (=Typ), aber anderen Familien
(=Werte) und natürlich anderen Hausnummern. Die Hausnummern bilden die Indizes, über welche man auf die Werte
zugreifen kann. Der Index eines Arrays beginnt normalerweise bei "0" und wird in eckigen Klammer dargestellt:
myarray[0];
Name des arrays[Index des Arrays];
Einem Array wird ein Wert, wie bei einer Variable, zugewiesen.
Es gibt zwei verschiedene Arten von Arrays, statische Arrays und dynamische Arrays.
Es gibt zwei verschiedene Arten von Arrays, statische Arrays und dynamische Arrays.
Ein statisches Array ist ein Array mit einer bestimmten Größe. Es wird wie folgt deklariert:
var myArray : Array[0..4] of Interger ;
Name des Arrays ; Größe des Arrays ; Typ des Arrays
Die Größe kann bei diesem Beispiel während der Laufzeit nicht verändert werden.
Initialisiert wird das Array dann beispielsweise so:
Initialisiert wird das Array dann beispielsweise so:
myArray[ 0 ] := 0; myArray[ 1 ] := 0; myArray[ 2 ] := 0; myArray[ 3 ] := 0; myArray[ 4 ] := 0; |
Dynamische Arrays werden wie die statischen Arrays nur ohne die Größenangabe deklariert:
var myArray : Array of Interger ;
Name des Arrays ; Typ des Arrays
Die Größe eines dynamischen Array kann man während der Laufzeit ändern:
SetLength( myarray , 10 );
Name des Arrays ; Neue größe des Arrays
Initialisiert wird das dynamische genauso wie das statische Array.
Beispiele siehe später bei Step 11 (For-Schleife).
Records:
Records sind eine Art Verbund von mehreren Elementen.
Diese Elemente, die Variablen nicht unähnlich sind, können von verschiedenen Datentypen sein.
Hier die Deklaration und Initialisierung:
Diese Elemente, die Variablen nicht unähnlich sind, können von verschiedenen Datentypen sein.
Hier die Deklaration und Initialisierung:
procedure TMainForm.BtnDemoClick(Sender:TObject); type TAdresse = record Vorname: String; Nachname: String; Strasse: String; Hausnmr: Integer; Ort: String; PLZ: String; end; // of Record var tmpAdr : TAdresse; AdressenArray : Array[0..4] of TAdresse; // Beinhaltet insgesamt 5 Adressen! begin // Initialisierung des Adressen-Arrays AdressenArray[0].Vorname:='Klaus'; AdressenArray[0].Nachname:='Walter'; // ... AdressenArray[4].Ort:='Klaustal'; AdressenArray[4].PLZ:=54321; end; |
Die "Typdeklaration" besteht aus dem Schlüsselwort "type" und anschließend fast genauso, wie wir es bei der
Variablendeklaration kennengelernt haben.
(Wichtig ist "=" anstatt ":" und "end;" anstatt nur ";"!)
Der Vorteil hierbei ist, dass man mehrere "Instanzen" von diesem Typ bilden kann, wie man es mit Variablen bereits gewohnt ist.
(Wichtig ist "=" anstatt ":" und "end;" anstatt nur ";"!)
Der Vorteil hierbei ist, dass man mehrere "Instanzen" von diesem Typ bilden kann, wie man es mit Variablen bereits gewohnt ist.
Nun haben wir den Typus "Record" bereits kennengelernt. Am Ende im Abschnitt OOP werden wir eine weitere Art
von "type" kennenlernen.
Demo-Anwendung:
Hier eine fortgeschrittene Demo, was man mit dem "Type" Record und dem Array schönes machen kann:
Den Source-Code könnt ihr dann entsprechend ergänzen - und auch erweitern. Überall an den "..."-Stellen sollen
entsprechend die weiteren Zeilen für die anderen Edits stehen - hier ist das jetzt stark verkürzt um die Seite
nicht zu lang und unübersichtlich zu gestalten.
// das hier in den Interface-Bereich direkt bei type type TICQKontakt = record Nick : String[10]; // die Zahl in den Eckigen Klammern gibt Vorname : String[25]; // die maximale Größe des "Strings" an! Nachname : String[25]; UIN : Integer; end; T4ICQKontaktBuch = Array[0..3] of TICQKontakt; // das hier in den privat-Abschnit des TMainForms, direkt unter { Private-Deklarationen } ICQKontaktBuch : T4ICQKontaktBuch; // das hier in die Click-Procedure des Buttons, // der die Eingaben übernehmen soll: begin ICQKontaktBuch[0].Nick := EdNick1.Text; ICQKontaktBuch[0].Vorname := EdVorname1.Text; // ... copy & paste ;-) ICQKontaktBuch[3].Nachname := EdNachname4.Text; ICQKontaktBuch[3].UIN := StrToInt( EdIcqNummer4.Text); end; // das hier in die Click-Procedure des Buttons, // der die geladene Eingaben anzeigen soll: begin EdNick1.Text := ICQKontaktBuch[0].Nick; EdVorname1.Text := ICQKontaktBuch[0].Vorname; // ... copy & paste ;-) EdNachname4.Text := ICQKontaktBuch[3].Nachname; EdIcqNummer4.Text := IntToStr( ICQKontaktBuch[3].UIN); end; // das hier in die Click-Procedure des Buttons, // der alles speichern soll: var f : file of T4ICQKontaktBuch; begin // Dateihandling ist neu - nehmt euch Zeit um euch das kurz anzuschauen // wir definieren hier quasi erst einen sogenannten "Zeiger" f // auf die Datei "demofile.dat" um mit diesem weiter zu arbeiten // Damit die Datei im gleichen Verzeichnis landet, wie unsere Exe-Datei // ist hier noch ExtractFilePath als Hilfsfunktion dabei. AssignFile(f, ExtractFilePath(Application.Exename) + 'demofile.dat'); // da wir in diesem Fall "neu" speichern wollen, nutzen wir Rewrite() um // die Datei zu leeren ReWrite(f); // nun schreiben wir unser Kontaktbuch in die Datei Write(f,ICQKontaktBuch); // und zu guter Letzt, schließen wir den Zeiger auf die Datei, so dass ggf. // jemand Anderes darauf zugreifen kann :) CloseFile(f); end; // das hier in die Click-Procedure des Buttons, // der alles laden soll: var f : file of T4ICQKontaktBuch; begin // auch hier definieren wir erst den Zeiger auf die Datei AssignFile(f, ExtractFilePath(Application.Exename) + 'demofile.dat'); // nun stellen wir sicher, dass der Zeiger auf den Anfang zeigt ReSet(f); // Und jetzt lesen wir unser Kontaktbuch aus der Datei Read(f,ICQKontaktBuch); // Wie oben, alles wieder schließen CloseFile(f); end; |
Zum Testen könnt ihr einfach das Programm starten, dann die Felder ausfüllen, auf Übernehmen und Speichern klicken,
und nach dem Neustart sollten über Laden und Anzeigen die Werte wieder erscheinen :)
Auch wenn ICQ nicht mehr so wie früher existiert, dient die UIN heutzutage immer noch prima als Beispiel, wenn
man eine Nummer abspeichern möchte. ICQ war ein Messenger, der leider nie ausgebaut wurde.
Heutzutage haben die Betreiber von Mail.ru den Dienst übernommen und damit einen Start in die Neuzeit gewagt,
indem sie ihn prinzipiell mit ähnlichen Funktionen wie Whatsapp oder Telegramm ausgestattet haben.
Preisfrage: Wer erkennt hieran, dass das so lange nicht weitergehen kann, wenn man z.B. 300 Kontakte speichern
möchte? Eine Hinweis für eine dynamischere Lösung kann
Step 11
bringen und bei den Vertiefenderen-Tutorials
gehe ich unter Filehandling noch mehr darauf ein ;)
Den kompletten Source-Code für dieses Projekt findet ihr unter
GitHub.
Neu seit 10.4: Managed Records:
Managed Records sind eine neue Funktion, die in Delphi 10.4 Sydney eingeführt wurde. Sie ermöglichen
es, benutzerdefinierte Initialisierungs- und Finalisierungsoperatoren für Records zu definieren.
Hier sind zwei Beispiele:
In diesem Beispiel wird der Wert des Feldes "Value" auf 0 gesetzt, wenn eine neue Instanz von TMyRecord
erstellt wird.
Hier sind zwei Beispiele:
type TMyRecord = record Value: Integer; class operator Initialize(var ARecord: TMyRecord); end; class operator TMyRecord.Initialize(var ARecord: TMyRecord); begin ARecord.Value := 0; end; |
Beispiel Nummer Zwei:
In diesem Beispiel wird der Speicher freigegeben, der von ARecord.Value allokiert wurde, wenn eine Instanz von TMyRecord zerstört wird.
type TMyRecord = record Value: PChar; class operator Finalize(var ARecord: TMyRecord); end; class operator TMyRecord.Finalize(var ARecord: TMyRecord); begin if ARecord.Value <> nil then FreeMem(ARecord.Value); end; |
Managed Records können auch mit Arrays verwendet werden, um sicherzustellen, dass die Elemente des Arrays
ordnungsgemäß initialisiert und freigegeben werden.
procedure TMainForm.BtnTestMgmtRecordClick(Sender:TObject); type TScrumValue = record Value: string; class operator Initialize(out Dest: TScrumValue); class operator Finalize(var Dest: TScrumValue); end; class operator TScrumValue.Initialize(out Dest: TScrumValue); begin Dest.Value := 'not set'; end; class operator TScrumValue.Finalize(var Dest: TScrumValue); begin if Dest.Value <> nil then FreeMem(Dest.Value); end; var ScrumValues: array[0..4] of TScrumValue; begin // ... ScrumValues[0].Value := 'Commitment'; ScrumValues[1].Value := 'Mut'; ScrumValues[2].Value := 'Respekt'; ScrumValues[3].Value := 'Fokus'; ScrumValues[4].Value := 'Offenheit'; // ... end; |