![]() |
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 |
Re: Array mit verschiedenen Records
so gehts:
Delphi-Quellcode:
Dabei ist das Array-Elemente so groß wie der größte Recordtyp - Wenn also TRec1 und TRec2 gleich groß sind wird nicht mehr speicher als normal verbraucht.
TRec1 = record
a : char; b : char; end; TRec2 = record c: char; d: char; end; TRec1or2 = record case Bool of True: (Variante1: Rec1); False: (Variante2: Rec2); end; RecArray:Array[0..4]of record; |
Re: Array mit verschiedenen Records
Ich hänge nun an folgendem Problem fest:
Delphi-Quellcode:
ich weiss nicht, wie ich anders den Datensatz in das array bekomme, um den richtigen datensatz auslesen zu können
type
TDataArray = array[0..4] of variant; var DataArray : TDataArray; // ??? ... Format:=0; CreateDate:=StrToDate(FormatDateTime('dd.mm.yy',GetFileModifyDate(Fread))); if CreateDate<StrTodate('22.01.04') then Format:=1; if CreateDate<StrTodate('23.07.03') then Format:=2; if CreateDate<StrTodate('21.02.02') then Format:=3; if CreateDate<StrTodate('27.04.01') then Format:=4; if CreateDate<StrTodate('31.10.00') then Format:=5; case Format of 0: begin DataArray[0]:=TZeile_1_nach04; DataArray[1]:=TZeile_2_nach03; ... DataArray[4]:=TZeile_5_nach04; end; 1: begin DataArray[0]:=TZeile_1_vor04; DataArray[1]:=TZeile_2_nach03; end; 2: begin DataArray[0]:=TZeile_1_vor04; DataArray[1]:=TZeile_2_vor03; end else begin ShowMessage('Format wird noch nicht unterstützt.'); exit; end; end; fStream:=TMemoryStream.Create; try fStream.LoadFromFile(Fread); fStream.ReadBuffer(DataArray[0],SizeOf(DataArray[0])); fStream.ReadBuffer(DataArray[1],SizeOf(DataArray[1])); fStream.ReadBuffer(DataArray[2],SizeOf(DataArray[2])); fStream.ReadBuffer(DataArray[3],SizeOf(DataArray[3])); fStream.ReadBuffer(DataArray[4],SizeOf(DataArray[4])); finally fStream.Free; end; :gruebel: :cry: :wall: :freak: |
Re: Array mit verschiedenen Records
Dein Sizeof(DataAray[x]) dürfte unabhängig von x immer 16 liefern. so groß ist eben ein Variant. Und in den 16 Bytes des Variant steht dann der Typ mit dem das Variant derzeit belegt ist und je nach Typ die entspr Daten.
:gruebel: Kann man ein Variant eigentlich mit einem Record direkt füllen? Edit: Hier ist ja noch einiges anderes schief. :warn: DataArray[0]:=TZeile_1_nach04; Und Recods kann man tatsächlich nicht einem variant zuordnen (Delphi 7). Den Ansatz solltest du besser wegwerfen. |
Re: Array mit verschiedenen Records
ich bin grad dabei es mit einem array of pointer zu probieren. (learning by doing :D )
mit sizeof ist mir grad auch schon aufgefallen. ganz schön verzwickt der scheiss. edit: der erste ansatz ist schon weg :D |
Re: Array mit verschiedenen Records
...also habe ich das richtig verstanden: das Format hängt nur vom Datum der Datei ab?
|
Re: Array mit verschiedenen Records
richtig Billa,
anhand des erstellungsdatums wähle ich das dafür notwendige format. nur ich verzweifel grad an der zuweisung mfg Scrutor |
Re: Array mit verschiedenen Records
Warum liest Du nicht - abhängig vom Datum - SizeOf(xxx) Zeichen in einen String, fügst bei den kleineren(älteren?) Sätzen ans Ende des Feldes von AuftrNr mit insert ein Leerzeichen (oder bei numerischen Auftragsnummer am Anfang eine führende Null) ein und benutzt nur EINE Datenstruktur? Sprich: anschließend den String per Typecast oder Move(src,dest,cnt) in die Struktur kopieren Ok...ist nicht gerade schnell, aber das sieht nach einem einmaligen Import aus. Da ist "Speed" wohl nicht so entscheidend.
|
Re: Array mit verschiedenen Records
@Billa
weil das doch zu aufwendig wäre meiner meinung nach. die unterschiede in den formaten sind auch mal mitten in einem record, also nicht immer am ende oder am anfang. und da dann immer die richtige stelle zu finden ist bestimmt möglich, aber zu umständlich find ich. ich hab 6 Zeitabfragen und 5 Zeilen, die je nach datum anders aussehen (können).
Delphi-Quellcode:
Zeile1
Zeile1_1 //Format 1, etc. Zeile1_2 Zeile1_3 Zeile1_4 Zeile1_5 Zeile1_6 Zeile2 Zeile2_1 Zeile2_2 Zeile2_3 Zeile2_4 Zeile2_5 Zeile2_6 |
Re: Array mit verschiedenen Records
..ich finde es relativ einfach je nach Struktur Leerzeichen einzufügen... sowas lässt sich sogar prima über eine Steuerdatei mit der jeweiligen Satzstruktur steuern. Damit ist man dann auch für weitere Formate offen, ohne die "hart" codieren zu müssen. Ändern der Steuerdatei und NICHT neu compilieren. D.h. das funktioniert dann auch beim Kunden oder wenn der Programmierer mal NICHT da ist, Delphi nicht zur Verfügung steht oder, oder, oder.... Aber ok. Ist das ganze denn jetzt ein einmaliger Vorgang?
|
Re: Array mit verschiedenen Records
ich programmiere einfach nur ein altes Fortran-Programm in Delphi neu.
und diese Dateiformate sind halt historisch gewachsen. ich will halt nur, dass man die alten Datensätze auch noch in meinem neuen Programm weiterhin benutzen kann (zumindest laden). Deswegen ja die Datumsabfrage. alle datensätze die nach 2004 erstellt wurden, ändern sich vorerst nicht und wenn dann mach ich das dateiformat eh komplett neu. also ist das mit einer steuerdatei hinfällig. und da der kunde nur aus 2 leuten besteht (ich bin einer von den 2 :) ), ist es auch nicht schlimm, wenn der programmierer mal pennt :D :roll: ich hätte am liebsten nur die aktuellste datei-struktur genommen, aber dann hätte man alle alten sachen (wenn sie denn wiederkommen) komplett neu oder erst mit dem alten Fortran-Programm machen müssen. also es ist ein einmaliger vorgang mfg Scrutor |
Re: Array mit verschiedenen Records
uppsss.. laufen denn die Fortran-Programme parallel weiter? In solchen Umgebungen gibt es i.d.R. noch mehr "Dinosaurier", deshalb könnte eine solche Routine mehrfach verwendet werden. In meinem Job haben wir es aus historischen Gründen mit dBase und Dataease-Dateien aus mehreren Projekten zu tun. (eigene und von Kunden) Also haben wir uns die Mühe EINMAL gemacht und einen Konverter nach SQL geschrieben. Der wird über Textdateien gesteuert. Das Ding taugte bisher für ca ein Dutzend Migrationsprojekte. Aber das scheint ein anderer Fall zu sein.
Wenn Du sowieso später neue Datenstrukturen entwickeln willst, lohnt sich der Aufwand vielleicht wirklich nicht. Ich ziehe es allerdings vor, im Klartext lesbare Steuerdateien zu verwenden, statt verschachtelte Klassen und Objekte. Nach spätestens einem halben Jahr taucht dann doch ein Fall auf, wo das ohne Zweifel elegante Konstrukt dann doch nicht mehr passt. Ich will Dich nicht überreden, aber Wiederverwendbarkeit ist ein n icht zu unterschätzender Kosten- und Zeitvorteil. Viel Erfolg jedenfalls. An dieser Stelle klinke ich mich aus. ...muß ja schließlich ein bißchen was arbeiten.... |
Re: Array mit verschiedenen Records
Was haltet ihr von einem array of pointer? Also ungefähr so:
Delphi-Quellcode:
Ist natürlich relativ viel Code, da du oft alteVersion abfragen musst, aber du kannst dir ja Funktionen bauen, die das automatisieren.
type
TRec1=record //alter Record // end; PRec1=^TRec1; TRec2=record //neuer Record; // end; PRec2=^TRec2; var alteversion: boolean; Daten:array[0..9] of pointer;//Größe des Arrays natürlich beliebig groesse:integer; //abhängig von alteVersion auf sizeof(TRec1) oder sizeof(TRec2) gesetzt //Jetzt erstmal alteVersion und Groesse richtig setzen. Dann für jedes Element von Daten mit getmem genau so viel Speicher allozieren, wie für den benutzten Record gebraucht wird. Beim auslesen dann in den entsprechenden Zeigertyp casten for i:=0 to 9 do getmem(array[i],groesse) //Jetzt einlesen meinStream.read(array[i]^,groesse); //Verwendung: if alteVersion then begin PRec1(Daten[0])^ //Und irgendwas damit machen end else begin PRec2(Daten[0])^ //Und irgendwas damit machen end; //Am Ende natürlich freemem nicht vergessen |
Re: Array mit verschiedenen Records
so, ich hab mir nun was ganz anderes einfallen lassen, was meiner meinung nach auch am einfachsten ist.
ich habe nun 6 verschiedene records, also für jeden Datumsfall ein extra record. nur jetzt steh ich wieder auf dem schlauch, wie kann ich die denn jetzt zuordnen ?
Delphi-Quellcode:
...
var Data0:TDaten_0; Data1:TDaten_1; Data2:TDaten_2; Data3:TDaten_3; Data4:TDaten_4; Data5:TDaten_5; ... Format:=0; CreateDate:=StrToDate(FormatDateTime('dd.mm.yy',GetFileModifyDate(Fread))); if CreateDate<StrTodate('22.01.04') then Format:=1; if CreateDate<StrTodate('23.07.03') then Format:=2; if CreateDate<StrTodate('21.02.02') then Format:=3; if CreateDate<StrTodate('27.04.01') then Format:=4; if CreateDate<StrTodate('31.10.00') then Format:=5; case Format of //format wählen 0: begin //benutze "Data0" record DataArray[0]:=Data0; groesse[0]:=Sizeof(TDaten_0); end; 1: begin //benutze "Data1" record end else begin ShowMessage('Format wird noch nicht unterstützt.'); exit; end; end; fStream:=TMemoryStream.Create; try fStream.LoadFromFile(Fread); fStream.ReadBuffer(DataArray[0],sizeof(groesse[0])); {fStream.ReadBuffer(DataZ2,SizeOf(DataZ2)); fStream.ReadBuffer(DataZ3,SizeOf(DataZ3)); fStream.ReadBuffer(DataZ4,SizeOf(DataZ4));} // fStream.ReadBuffer(DataZ5,SizeOf(DataZ5)); finally fStream.Free; end; EditIdVor.Text:=trim(DataArray[0].IdVorr); |
Re: Array mit verschiedenen Records
es ist zum verzweifeln, ich komme einfach nicht weiter. :wall:
ist es vielleicht möglich eine Variable dynamisch zuzuordnen ? also beispielsweise im Prinzip so:
Delphi-Quellcode:
ich weiss einfach nicht wie ich das machen soll
var
Data : ???; begin case Format of 0: Data:=TDaten_0; 1: Data:=TDaten_1; end; end; mfg Scrutor |
Re: Array mit verschiedenen Records
Ja, du kannst es dynamisch zuordnen. Da musst du den Speicher selbst verwalten.
Prinzip:
Delphi-Quellcode:
Anmerkung du kannst dir auch gleich einen Typ machen
type TDaten1=record
... var typ:array of byte; DatenArray:Array of pointer; procedure readversion1(const Stream:Tstream;pos:integer); var Daten1:^TDaten1; begin new(Daten1) //Speicher reservieren stream.read(Daten1^,sizeof(TDaten1); Datenarray[pos]:=Daten1; typ[pos]:=1; //du musst dir ja merken, an welcher Stelle du welchen Typ von record hast end; procedure readversion2..... //zugriff Daten1:=Datenarray[pos]; showmessage(Daten1^.xyz); //am Ende speicher mit dispose freigeben case typ[pos] of 1: begin Daten1:=Datenarray[pos]; dispose(Daten1); ... So, ich muss erstmal los.... |
Re: Array mit verschiedenen Records
danke sirius,
aber irgendwie versteh ich nicht so ganz was du da machst bzw. vorhast. wieso "procedure readversion2....." blick da nicht so durch . mfg Scrutor |
Re: Array mit verschiedenen Records
Hallo,
ich denke, du gehst falsch heran. Das einfachste ist doch, wenn du die alten Daten in das neue Format konvertierst und dann nur mit dem neuen arbeitest. Ausnahme: Das alte Fortran-Programm läuft immer noch. In diesem Fall würde ich auf jeden Fall auf Klassen umsteigen. Trenne das Lesen der Daten von deinen internen Datenstrukturen.
Delphi-Quellcode:
Zum Lesen benutzt du deine Records,
type
TDataItem = class public iVersion : Integer; // 1-6 ? sProjectNo : String; end; schreibst die Daten aber dann in das TDataItem rein Jetzt gibt es nur noch einen Unterschied beim Lesen und Schreiben. In deinem Code benutzt du nur das TDataItem. Heiko |
Re: Array mit verschiedenen Records
Hallo hoika,
also das alte Fortran-Programm ist natürlich noch im Dienst und soll auch vorerst parallel weiterlaufen können, deswegen mach ich mir ja diese Arbeit. Mit den Klassen hab ich das noch nicht geschnallt. Bin erstmal grad nun noch dran mit Pointern zu arbeiten. es muss doch irgendwie auch so gehen mfg Scrutor |
Re: Array mit verschiedenen Records
Ich und Sirius meinten prinzipiell das selbe. Die unterschiedlichen Readversions bei Sirius gibt es, damit du in einem Fall readversion1 aufrufst und im anderen Fall readversion2. Sirius kapselt das, was ich mittendrin gemacht habe. Du machst also von deiner Version abhängig, welche Funktion du aufrufst.
|
Re: Array mit verschiedenen Records
ich bekomme aber nichts von alledem an meinem beispiel zum laufen.
weder deinen ansatz noch den von sirius. entweder klappt das nicht, oder ich hab einfach nur irgendwo nen denkfehler |
Re: Array mit verschiedenen Records
Mein Vorschlag wäre:
Delphi-Quellcode:
Jetzt kannst Du Dir ein Array von diesen Records erstellen und abhängig vom Dateidatum den RecordKind ermitteln. Diesen schreibst Du mit in den Record und kannst dann überall im Programm wissen, welcher art dieser Record ist und dementsprechend zugreifen.
Type
TRecordKind=(rkGanzAlt, rkNichtsoAlt, rkNeu, ...); TMyRecord= Record Kind: TRecordKind; case TRecordKind of rkGanzAlt: // hier alle Member vom alten typ rkNichtsoAlt: // hier alle Member vom alten typ rkNeu: // hier alle Member vom alten typ ..: // hier alle Member vom alten typ end; end; Zu dem Stream lesen: Erstelle Dir für jeden RecordKind eine Konstante, die die jeweilige Gesaamtlänge beinhaltet, dann kannst Du immer soviele Bytes einlesen. |
Re: Array mit verschiedenen Records
Dann aber im richtigen Stil für variante records (kein end nach dem case!):
Delphi-Quellcode:
TMyRecord= Record
case Kind:TRecordKind of rkGanzAlt: // hier alle Member vom alten typ rkNichtsoAlt: // hier alle Member vom alten typ rkNeu: // hier alle Member vom alten typ ..: // hier alle Member vom alten typ end; |
Re: Array mit verschiedenen Records
Das einlesen ist nicht das Problem.
das erstellen des richtigen records nun auch nicht mehr. nur wie sag ich der Variablen Data, dass sie mal der eine record ist und mal der andere ? Prinzip:
Delphi-Quellcode:
edit: ich find es leichter und einfacher 6 records zu erstellen, als mit den variant recordds rumzukaspern.
var
Data : ???; begin case Format of 0: Data:=TDaten_0; 1: Data:=TDaten_1; end; end; die 6 records sind ja schon erstellt und fertig, nur die zuweisuzng und auslesen und einem editfeld zuweisen klappt nicht |
Re: Array mit verschiedenen Records
Hallo,
so wie du das schreiben willst, musst du für jede der 6 Versionen eine eigene Variable mitführen. Die 6 Records unterscheiden sich noch mal wodurch ? Durch bestimmte String-Längen ? Wenn ja, benutze für das Lesen/Schreiben deine 6 verschiedenen Records, aber in allen anderen Routionen genau einen Record (nur String als Type, nicht array[0..] of Char). Wenn du unbedingt eine 6 records haben willst, dann könntest du auch so vorgehen
Delphi-Quellcode:
Sie umständlich aus, ist es auch ...
type
TRec1 = record // Daten end; type TRec2 = record // Daten end; .. type TRec6 = record // Daten end; type TRecAllData : record iVersion: Integer; //1-6 Rec1: TRec1; Rec2: TRec2; .. Rec6: TRec6; end; Heiko |
Re: Array mit verschiedenen Records
naja, ich mache dann jetzt zu den 6 verschiedenen records noch 6 proceduren, die die datei dann mit dem richtigen record auslesen.
find ich zwar unschön und irgendwie umständlich, aber es geht wohl nicht anders, bzw. ich bekomme es nicht anders hin. vielen dank trotzdem an alle hier für ihre bemühungen Edit: so, mit den 6 records und 6 proceduren funktioniert es nun einwandfrei. mfg Scrutor |
Re: Array mit verschiedenen Records
Es reicht eigentlich 1 Routine zum lesen:
Delphi-Quellcode:
procedure ReadFromStream(Data:Pointer;Datasize:Integer);
begin Stream.Read(data^,datasize); end; Je nach Typ mußt du natürlich entsprechend die Daten übergeben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz