Array mit verschiedenen Records
Hallo zusammen,
ich hab mal wieder ein Problemchen, bei dem ich nicht weiterkomme und ich denke mal hier wird mir die Frage schnell beantwortet. Ich möchte eigentlich nur wissen, ob es möglich ist ein Array zu erstellen, in dem 5 verschiedene Records drin sind. also ungefähr so:
Delphi-Quellcode:
Geht das so wie ich mir das wünsche ? oder muss ich mir was anderes einfallen lassen ?
type
Rec1 = record a : char; b : char; end; type Rec2 = record c: char; d: char; end; ... RecArray:Array[0..4]of record; RecArray[0]:=Rec1; RecArray[1]:=Rec2; ... RecArray[4]:=Rec5; Bisher hab ich das nicht hinbekommen. :wall: Vielen Dank für jede Hilfe. mfg Scrutor |
Re: Array mit verschiedenen Records
Geht, aber nur mit Tricks.
Einfacher machst du dir es hier mit Klassen. Vielleicht nimmst du dann auch gleich eine TObjectList als Container statt eines Arrays. |
Re: Array mit verschiedenen Records
hmm,
hast du da irgendwo ein brauchbares Beispiel für ? Hab mich mit Klassen und Containern noch nicht so befasst. mfg Scrutor |
Re: Array mit verschiedenen Records
Hi,
so geht das nicht. Ein Array ist eine sehr einfache Art von Speicherstruktur, die nur dazu bestimmt ist einfach (und schnell) auf eine bestimmte (feste) Menge von gleichen Daten zugreifen zu können. Legst Du ein Array an, so wird einfach die Größe eines Elements mit der Anzahl der Elemente multitpliziert und der entsprechend Wert wird als Menge an Speicher alloziert. Anders gesagt, hast Du ein Array, dass aus 10 Integer Werten besteht (egal ob dynamisch oder statisch), dann wird hier einfach 10 * 4 Byte (sizeOf(Integer) = 4) alloziert. Nun merkt sich Delphi noch die Adresse des ersten Elements im Array. Möchtest Du nun auf das 7te Element zugreifen, so weiß Delphi hier, dass es einfach an 4 Byte an der Adresse (StartadresseDesArrays + 7 * 4) zugreifen muss. Das ist gerade der Vorteil eines solchen Array, die Daten liegen alle am Stück im Speicher, da greifen einerseits Caching-Techniken recht gut und er wahlfreie Zugriff (Element an Stelle x) ist möglich. Unterschiedliche Typen können eben genau diese Art von Zugriff nicht garantieren, das gilt auch für gleich große Elemente (z.B. Cardinal und Integer). Schließlich sind das unterschiedliche Typen, die könnten also (theoretisch) auch die Größe unabhängig voneinander ändern! Was Du benutzen kannst ist immer etwas gleiches. Da gibt es schon mal die Möglichkeit, dass Du ein Array von Zeigern verwaltest und die speicherst. Die Records kannst Du dann (wenn Du die dyn. erzeugen willst) mit new erzeugen und die Adresse im Array speichern. Sind die Records statisch, musst Du darauf achten, dass die adresse nur lokal gültig ist, alles was Du in einer Methode als lokale Parameter deklarierst landet nur auf dem Stack und wird beim verlassen der Methode dort auch abgeräumt. Globale Variablen, Instanz- und Klassenvariablen, Instanzen von Klassen und eben mittels new erzeugte Typen unterliegen nicht der Einschränkung (Daten landen im Heap). Das Problem dass Du beim arbeiten mit Zeigern hast (kannst hier auch auf eine TList statt einem Record of Pointerzurückgreifen) ist, dass Du nicht weißt was für einen Typ sich hinter dem Zeiger verbirgt. Der speichert nur eine Adresse, was sich an der Adresse befindet musst Du schon selbst wissen. Hier ist also die Frage, wie Du das ganze dann erkennen möchtest, eine Möglichkeit ist natürlich ein Record aus dem Typ und dem Zeiger. Ansonsten kannst Du das ganze auch über Klassen realisieren. Die erben immer von der Basisklasse TObject. Details zu Klassen und OOP kannst Du in vielen Tutorials nachlesen, die meisten behandeln sicherlich auch Vererbung (und vergessen dafür häufiger mal die wichtigen Ideen der OOP). Jedenfalls kannst Du jede Instanz einer Klasse immer wie eine TObject Instanz behandeln. Dabei siehst Du dann nur dass, was eben ein TObject anbietet (z.B. die Methode Free zum Freigeben der Instanz). Hier kannst Du also auf ein Object of TObject oder eine TObjectList zurückgreifen. Ob eine Instanz nun vom Typ Klasse1 oder Klasse2 ist, kannst Du mittels dem Operator is (if Variable is TKlasse1 then ...) testen. Gruß Der Unwissende |
Re: Array mit verschiedenen Records
Hi - ich mache das immer so:
Delphi-Quellcode:
Somit kann man in ein Array die unterschiedlichsten Sachen packen. :)
type
Rec1 = record a : byte; b : string[255]; end; Rec2 = record c: integer; d: word; end; RecComplete = record RecPart1 : Rec1; RecPart2 : Rec2; end; RecArray : Array[0..4] of RecComplete; |
Re: Array mit verschiedenen Records
Zitat:
Bei solchen unterschiedlichen Typen kannst Du dann auch ein varianten Record (einfach mal in die OH schauen) verwenden. |
Re: Array mit verschiedenen Records
hui, danke für die umfangreiche Info Der_Unwissende.
Nun weiss ich zumindest schonmal, dass die Lösung über Records in meinem Fall nicht (nie) funktionieren kann. Ich werde mich dann nun mal den Klassen und Objecten widmen. @christian.noeding das wäre eine möglichkeit, aber ist für meinen Fall auch leider nicht brauchbar. trotzdem vielen dank. ich beschreibe mal mein problem, vielleicht hat ja einer eine gute lösung: Also, ich hab eine Text-Datei in der Datensätze gespeichert sind. Diese muss ich laden. Zeile 1 hat zum Beispiel 14 Datensätze, die bis auf den ersten Datensatz alle 8 Zeichen lang sind. Der erste Datensatz hat 10 Zeichen. Nun kann es aber sein, dass bei einem alten Datenformat der erste Datensatz nur 9 Zeichen lang ist. Also prüfe ich das Datei-Erstellungsdatum und entscheide danach, welchen Record ich benutze, um den Datensatz der ersten Zeile korrekt zu laden. Datei von 2002 sieht so aus:
Delphi-Quellcode:
Datei von 2004 sieht so aus:
type
TDaten_Zeile_1_altesFormat = record Auftr : array[0..8]of char; //Auftragsnummer Dum1 : array[0..7]of char; //Dummy ProgNr : array[0..7]of char; //Programmnummer ZeichNr : array[0..7]of char; //Zeichnungsnummer LineNr : array[0..7]of char; //Lineelement IdBohr : array[0..7]of char; //Ident Bohren IdVorr : array[0..7]of char; //Ident Vorrichtung Dum2 : array[0..7]of char; //Dummy AVO : array[0..7]of char; //AVO Mach : array[0..7]of char; //Maschine Durchm : array[0..7]of char; //Raddurchmesser AusWink : array[0..7]of char; //Austrittswinkel AnzScha : array[0..7]of char; //Anzahl Schaufeln SchaHohe: array[0..7]of char; //Schaufelhöhe LineFeed: array[0..1]of char; end;
Delphi-Quellcode:
so, davon gibt es also mehrere unterschiedliche Datensätze zu unterschiedlichen Datumsangaben.
type
TDaten_Zeile_1_neuesFormat = record Auftr : array[0..9]of char; //Auftragsnummer Dum1 : array[0..7]of char; //Dummy ProgNr : array[0..7]of char; //Programmnummer ZeichNr : array[0..7]of char; //Zeichnungsnummer LineNr : array[0..7]of char; //Lineelement IdBohr : array[0..7]of char; //Ident Bohren IdVorr : array[0..7]of char; //Ident Vorrichtung Dum2 : array[0..7]of char; //Dummy AVO : array[0..7]of char; //AVO Mach : array[0..7]of char; //Maschine Durchm : array[0..7]of char; //Raddurchmesser AusWink : array[0..7]of char; //Austrittswinkel AnzScha : array[0..7]of char; //Anzahl Schaufeln SchaHohe: array[0..7]of char; //Schaufelhöhe LineFeed: array[0..1]of char; end; Ich hab 5 Zeilen-Records und für jeden Zeilen Record kann es sein, dass ich 6 verschiedene Zeit-Records erstellen muss. (Hab nämlich noch nicht alle Format unterschiede mir angeschaut) ich hoffe jemand versteht mein Porblem wenigstens ansatzweise :) |
Re: Array mit verschiedenen Records
Iim einfachsten Fall:
Delphi-Quellcode:
Soweit erstmal.
type TClass1=class
x,y:integer; end; type TClass2=class b:string; c:char; end; ... var Liste:TObjectList Class1:Tclass1; Class2:Tclass2; //irgendwo Liste erstellen Liste:=Tobjectlist.create; Liste.ownsobjects:=true; //damit verwaltet die Liste ihre Elemente selber //Object einfügen Class1:=Tclass1.create; Liste.add(Class1); Class1.x:=5; //usw.. Class2:=Tclass2.create; ... //Zugriff über list.Items[0] list.items[1] //also Class1:=list.items[0]; ergebnis:=Class1.x //oder ergebnis:=TClass1(list.items[0]).x; Hier geht aber noch viel mehr. |
Re: Array mit verschiedenen Records
Hallo Scrutor,
bei Textdateien gibt es zwei Basis-Formate: Fixed-Field und Comma-Separated. Die Bezeichnungen sagen aus, dass im ersten Fall die einzelnen Felder über ihren Offset und im letzteren Fall durch Abzählen der Trennzeichen lokalisiert werden. Deine Textdaten gehören in die erste Kategorie. Für deine beiden Datensatztypen kommt man leicht zu folgenden Strukturen:
Delphi-Quellcode:
Einlesen kannst du diese Daten wahlweise über die alten Pascal Standardroutinen ReadLn (ohne vorherige Kenntnis der Satzlänge) und BlockRead (mit vorheriger Kenntnis der Satzlänge) oder über einen FileStream.
type
TAuftragDaten = record Dum1 : array[0..7]of char; //Dummy ProgNr : array[0..7]of char; //Programmnummer ZeichNr : array[0..7]of char; //Zeichnungsnummer LineNr : array[0..7]of char; //Lineelement IdBohr : array[0..7]of char; //Ident Bohren IdVorr : array[0..7]of char; //Ident Vorrichtung Dum2 : array[0..7]of char; //Dummy AVO : array[0..7]of char; //AVO Mach : array[0..7]of char; //Maschine Durchm : array[0..7]of char; //Raddurchmesser AusWink : array[0..7]of char; //Austrittswinkel AnzScha : array[0..7]of char; //Anzahl Schaufeln SchaHohe: array[0..7]of char; //Schaufelhöhe end; TAuftrag2002 = record Nr : array[0..8]of char; //Auftragsnummer Spec: TAuftragDaten; end; TAuftrag2004 = record Nr : array[0..9]of char; //Auftragsnummer Spec: TAuftragDaten; end; Wenn nur diese beiden Datensatztypen existieren, dann kannst du auch einfach den größeren Typ verwenden und beim Einlesen die erste Stelle mit einem Leerzeichen oder einer Null initialisieren, wenn die kurzen Sätze verarbeitet werden. Grüße vom marabu |
Re: Array mit verschiedenen Records
Hallo marabu,
diese Lösung hört sich sehr gut an. Da ja mehr als nur diese 2 datensätze existieren, ist diese Möglichkeit brauchbar. Ich hab das mal wie folgt angefangen:
Delphi-Quellcode:
so, nun lese ich aber ja in einer procedure die Datei mit Filestream aus und übergebe die ausgelesenen records an eine weitere procedure, die die einzelenen Daten dann in Editfelder, etc. einträgt.
type
TZeile_1 = record Dum1 : array[0..7]of char; //Dummy ProgNr : array[0..7]of char; //Programmnummer ZeichNr : array[0..7]of char; //Zeichnungsnummer LineNr : array[0..7]of char; //Lineelement IdBohr : array[0..7]of char; //Ident Bohren IdVorr : array[0..7]of char; //Ident Vorrichtung Dum2 : array[0..7]of char; //Dummy AVO : array[0..7]of char; //AVO Mach : array[0..7]of char; //Maschine Durchm : array[0..7]of char; //Raddurchmesser AusWink : array[0..7]of char; //Austrittswinkel AnzScha : array[0..7]of char; //Anzahl Schaufeln SchaHohe: array[0..7]of char; //Schaufelhöhe LineFeed: array[0..1]of char; end; type TZeile_1_vor04 = record Auftr : array[0..8]of char; //Auftragsnummer Spec : TZeile_1; end; type TZeile_1_nach04 = record Auftr : array[0..9]of char; //Auftragsnummer Spec : TZeile_1; end; type TZeile_2 = record MesDurch: array[0..8]of char; EinDur : array[0..7]of char; FLAS : array[0..4]of char; Wkstoff : array[0..7]of char; Stueck : array[0..7]of char; Dum4 : array[0..7]of char; end; type TZeile_2_vor03 = record Spec : TZeile_2; SchaHoSi: array[0..7]of char; ZwShaSi : array[0..7]of char; LineFeed: array[0..1]of char; end; type TZeile_2_nach03 = record Spec : TZeile_2; SchaHoSi: array[0..7]of char; ZwShaSi : array[0..7]of char; MaxType : array[0..7]of char; LineFeed: array[0..1]of char; end; wie deklariere ich in der ersten procedure am besten die verschiedenen records ? und wie übergebe ich die an die nächste procedure ? alle global deklarieren ? mfg Scrutor |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz