Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Mehrdimensionales, dynamisches Array speichern (https://www.delphipraxis.net/159643-mehrdimensionales-dynamisches-array-speichern.html)

Dunkelbunt27 6. Apr 2011 16:55

Mehrdimensionales, dynamisches Array speichern
 
Hallo Delphi-PRAXIS,

ich möchte mein zweidimensionales dynamsiches Array (mit Record) in einer Datei speichern und wieder laden.
Kann mir jemand beschreiben wie das funktioniert?

(Die Suche hat mir nicht wirklich wieter geholfen...)

FG Dunkelbunt

DeddyH 6. Apr 2011 17:17

AW: Mehrdimensionales, dynamisches Array speichern
 
Die Array-Dimensionen sollen dabei erhalten bleiben, oder geht es rein um die Daten in den Records?

Dunkelbunt27 6. Apr 2011 17:19

AW: Mehrdimensionales, dynamisches Array speichern
 
Nein, es ist wichtig, dass die Dimensionen auch erhalten bleiben.

shmia 6. Apr 2011 17:23

AW: Mehrdimensionales, dynamisches Array speichern
 
Zum Beispiel als CSV-Datei.
Die ersten beiden Felder enthalten die Position im Array; anschliesend folgen die Daten der Struktur.
(ich nehme hier ein 2-dimensionales Array an)
Code:
0, 0, VW, blau, 90
0, 1, Audi, rot, 110
0, 2, Opel, rot, 75
1, 0, ....
So kann man auch Sparse Arrays speichern.
Vorteil der CSV-Datei ist die leichte Weiterverarbeitung in externen Tools.

Dunkelbunt27 6. Apr 2011 17:33

AW: Mehrdimensionales, dynamisches Array speichern
 
Hm, okay.
ich weiß nicht ganz wie ich vorgehen soll...

EDIT:
Ich hab es jetzt so 'versucht':

Delphi-Quellcode:
procedure Speichern;
var
Datei: TextFile;
Zeile, Spalte: string;
i, n : integer;
StringList1 : TStringList;
begin
Zeile:='';
Spalte := '';
StringList1 := TStringList.Create;
Try
for i := 0 to Length(Xdimension)  do
    for n := 0 to length(Ydimension) do
      begin
        Zeile := '';
        Zeile :=myarray[i,n].zeichen+';'+ IntToStr(myarray[i,n].attribut)+';';
        StringList1.Add(Zeile);
      end;
StringList1.SaveToFile(ExtractFilePath(Application.ExeName)+'test.CSV');
Finally
  StringList1.Free;
end;
end;
Ist das korrekt?

Wie kann ich das ganze jetzt wieder auslesen?

Bummi 6. Apr 2011 19:34

AW: Mehrdimensionales, dynamisches Array speichern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Vielleicht kannst Du damit was anfangen ...

ASM 7. Apr 2011 13:54

AW: Mehrdimensionales, dynamisches Array speichern
 
zur Unit uReadWrite_2D_Arrays:

Die mit der Verwendung des Parameters T2DStringArray überladenen Prozeduren Save2DArray() and Load2DArray() enthalten einen äußerst fatalen Fehler:
In den Anweisungen dieser beiden Prozeduren writer.Write() bzw. reader.Read() wird das Element [i,x] des Array A (also A[i,x]) ja nicht als String, sondern als Puffer übergeben. Daher muss zwingend als Start des übergebenen Puffers die erste Position des Stringelements A[i,x][1] gesetzt werden (nicht einfach nur A[i,x]).

Die beiden betroffenen Prozeduren müssen richtig wie folgt codiert sein:

Code:
procedure Save2DArray(const A: T2DStringArray; S: TStream); overload;
var
  writer: TWriter;
  i,x: Integer;
begin
  Assert(Assigned(S));
  writer := TWriter.Create(S, 8096);
  try
    writer.WriteInteger(Length(A));
    for i := 0 to Length(A) - 1 do
    begin
      writer.WriteInteger(Length(A[i]));
      for x := 0 to Length(A[i]) - 1 do
        begin
        Writer.WriteInteger(Length(A[i,x]));
        writer.Write(A[i, x][1], Length(A[i,x]));   // <-- !
        end;
    end; { For }
  finally
    writer.Free;
  end; { Finally }
end;
Code:
procedure Load2DArray(var A: T2DStringArray; S: TStream); overload;
var
  reader: TReader;
  i,x, numrows, numcols,slen: Integer;
begin
  Assert(Assigned(S));
  reader := TReader.Create(S, 8096);
  try
    numrows := reader.ReadInteger;
    SetLength(A, numrows);
    for i := 0 to numrows - 1 do
    begin
      numcols := reader.ReadInteger;
      SetLength(A[i], numcols);
      for x := 0 to numcols - 1 do
        begin
          slen := reader.ReadInteger;
          SetLength(A[i,x], slen);
          if slen>0 then
            reader.Read(A[i, x][1], slen);   // <-- !
        end;
    end; { For }
  finally
    reader.Free;
  end; { Finally }
end;

himitsu 7. Apr 2011 14:06

AW: Mehrdimensionales, dynamisches Array speichern
 
Bei Verwendung von ShortStrings kann man alle Strings einer Ebene zusammenhängens abspeichern/lesen und mü0te somit nur noch die i-Ebene durchlaufen

- kein Unicode (ShortStrings, also String[x] gibt es nur in ANSI)
- es wird immer die maximale Zeichenanzahl der Strings gespeichert

shmia 7. Apr 2011 15:52

AW: Mehrdimensionales, dynamisches Array speichern
 
Also ich würde schon bei einer CSV-Datei bleiben.
Binäre Datenformate sind so schwer zu debuggen und können nicht weiterverarbeitet werden.
Ich habe mal deine "Speicher"-Prozedur etwas aufgearbeitet.
Bei grösserer Datenmenge kann man dann auch auf einen TFileStream umschwenken,
um den Speicherverbrauch durch TStringList zu vermeiden.
Delphi-Quellcode:
procedure Speichern(const filename:string);
var
Datei: TextFile;
Zeile, Spalte: string;
i, n : integer;
StringList1 : TStringList;
begin
  StringList1 := TStringList.Create;
  Try
    for i := 0 to Xdimension-1 do
      for n := 0 to Ydimension-1 do
        begin
          Zeile := Format('%d;%d;', [i,n])+
             myarray[i,n].zeichen+';'+ IntToStr(myarray[i,n].attribut);
          StringList1.Add(Zeile);
        end;
    StringList1.SaveToFile(filename);
  Finally
    StringList1.Free;
  end;
end;

Dunkelbunt27 7. Apr 2011 15:58

AW: Mehrdimensionales, dynamisches Array speichern
 
Hallo,
Zitat:

Also ich würde schon bei einer CSV-Datei bleiben.
Danke, binäre Datenformate sind momentan etwas sehr kompliziert zu verstehen, da ich lieber etwas verwende, was ich auch verstanden habe. (trotzdem vielen Dank auch an die Anderen!)

Wie genau kann ich denn jetzt die Datei wieder auslesen? Und wie kann ich die Daten nun in mein Array kopieren?
Damit wäre mir sehr geholfen.

Fg Dunkelbunt

Trebxson 7. Apr 2011 16:18

AW: Mehrdimensionales, dynamisches Array speichern
 
naja, ich machs mal etwas Pseudomäßig...

Code:
Array
 (
  Array ('e1', 'e2', 'e3'),
  Array ('f1', 'f2', 'f3')
 )
=> als CSV, getrennt durch TAB und Zeilenumbruch

Code:
e1   e2   e3
f1   f2   f3
Dies wäre die einfachste Variante.

Delphi-Quellcode:
filecontent := '';

for i := 0 to length (Array) - 1 do
 begin

  for j := 0 to length (Array[i]) - 1 do
   begin
    filecontent := filecontent + Array[i][j];

    if (j + 1 < length (Array[i])) then
     begin
      filecontent := filecontent + #9;
     end;
   end;

  if (i + 1 < length (Array)) then
   begin
    filecontent := filecontent + #13#10;
   end;
 end;

//WriteToFile... (filename, filecontent);

himitsu 7. Apr 2011 16:39

AW: Mehrdimensionales, dynamisches Array speichern
 
Zeilenweise einlesen (ReadLn oder über eine TStringList) und dann könnte man erstmal die Zeilen zerlegen (manuell oder z.B. über ExplodeExplode) und weist sie dann seinem Record zu.

Dunkelbunt27 7. Apr 2011 18:19

AW: Mehrdimensionales, dynamisches Array speichern
 
Okay, danke soweit =)

EDIT: Wo kann ich anchlesen wie das mit der Stringlist funktioniert (Strings ausplitten), ich hab hier im Forum nur andere Varianten gefunden.

Wenn die Information in der ersten Zeile 1;1;A;0 beträgt, wie komme ich dann an das 'A' dran?
EDIT: Ich hab es (wahrscheinlich falsch) mit dem Explode von alzaimar probiert und meine 4GB Ram voll ausgelastet...
Delphi-Quellcode:
procedure laden;
var
Datei: TextFile;
Zeile: string;
i, n : integer;
StringList1, sSubStrings : TStringList;
MyDivider: TStringDivider;
MyIterator: TStringDivideIterator;

begin
 StringList1 := TStringList.Create;
 sSubStrings := TStringList.Create;
  try
  StringList1.LoadFromFile(ExtractFilePath(Application.ExeName)+'text.CSV');
  for i := 1 to AnzahlZeilen  do
    for n := 1 to AnzahlSpalten do
      begin
        MyDivider := TStringDivider.Create;

        MyDivider.Pattern := ';';
        MyDivider.Explode(StringList1.Strings[i], sSubStrings);

        MyIterator := TStringDivideIterator.Create;
        MyIterator.Pattern := ';';
        MyIterator.Text := StringList1.Strings[i];

        While MyIterator.MoveNext do
         sSubStrings.Add(MyIterator.CurrentStr);
     end;
  finally
    StringList1.Free;
    sSubStrings.Free;
    MyDivider.Free;
    MyIterator.Free;
  end;
end;

Trebxson 7. Apr 2011 22:02

AW: Mehrdimensionales, dynamisches Array speichern
 
Das ist ganz schön krass was du da zusammen würfelst. Unabhängig davon ob deine Logik funktioniert erzeugst du mit dem Beispiel AnzahlZeilen x AnzahlSpalten Speicherlecks!

Denn du erstellst innerhalb der Schleife jedesmal ein Objekt. Mit nächstem Durchlauf überschreibst du gnadenlos die Referenz. Und nach der Schleife gibst du nur ein Objekt frei?
Und das ganze sogar zweimal...

Setze mal mit dem Anwendungsstart (DPR)

Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := true
und lass deine Funktion durchlaufen und beende dein Programm anschließend (wenn dies überhaupt ohne Zugriffsfehler möglich ist).
Wenn du gar nicht begreifst was ich meine dann starte mal deine Funktion 20 mal und schau dir im Taskmanager die Speicherauslastung an.
Und wenn du jetzt sagst, was solls... Speicheranforderungen sind Systemaufrufe und die kosten viel viel Zeit! Und das in einer Schleife?

Und wieso erstellst du die Objekte oberhalb vom try-finally-Block? Und woher willst du im finally-Block wissen, dass alle Objekte auch wirklich existieren?

Was ist deine Zieldatei nicht existiert oder das ganze inmitten der Schleifen abbricht?

Worauf zeigt dann MyIterator? Und worauf die Methode Free ()? Oder anderen Sachen?

Vielleicht geht alles noch beim Lesen der Datei irgendwie gut. Jedoch wenn du auf deinem System irgendwann nur noch halbe Dateien findest solltest du dich nicht wundern.

Du solltest dir eine Funktion explode ('delimiter', 'content') schreiben die möglichst gar keine Objekte verwendet und nichts anderes macht als einen String in Teile zu zerlegen.

Bummi 7. Apr 2011 23:34

AW: Mehrdimensionales, dynamisches Array speichern
 
@ASM
danke ...
aber hast Du mal meine und Deine Varianten Debugt? IMHO sind meine die korrekten.

ASM 8. Apr 2011 16:23

AW: Mehrdimensionales, dynamisches Array speichern
 
Zitat:

Zitat von Bummi (Beitrag 1093793)
@ASM
IMHO sind meine die korrekten.

Nein sind sie definitiv nicht!!

Du kannst nicht die Fehlerfreiheit einer Codierung dadurch korrekt prüfen und angeblich nachweisen, wenn Du - wie Du es gemacht hast - die relativ komplizierte Struktur eines 2-dimensionalen Arrays an gerade mal einer einzigen Elementposition des Arrays testest.
Das ist nicht eine Frage rein theoretischer Interpretation, sondern vor allem eine der praktischen Prüfung.

Auf den Fehler in Deinem Code bin ich nämlich gerade dadurch aufmerksam geworden, nachdem ich das komplette 2D-Array mit unterschiedlichen Werten gefüllt hatte und dann folgendermaßen vorgegangen bin: zum einen nach programminternem Austausch per Memorystream zwischen zwei formal gleichen Arrayvariablen (A und B), zum anderen nach Abspeicherung des ersten Arrays (A) per Filestream in einem File und anschließenden Einlesen dieses Files per Filestream in das zweite Array (B), wobei sich ergänzend mit einem Hexeditor die im File gespeicherte Information exakt nachprüfen ließ.

Ergebnis:
Mit Deinem originalen Code wurde in beiden Verfahren nur Garbage sichtbar, und außerdem führte es zufallsbedingt an unregelmäßigen Arraypositionen zu Crash wegen Access violation.

Wie Du also zu Deiner jetzigen Verteidigung und Behauptung kommen kannst, ist mir rätselhaft. Vielleicht solltest Du es einmal kontrollieren mit meiner folgenden Erweiterung Deines Beispielcodes zur Anwendung:
Code:
procedure TForm1.Button2Click(Sender: TObject);
var
  a,b:T2DStringArray;
  i:Integer;
  ms:TMemoryStream;
begin
   ms:=TMemoryStream.Create;
   try
   SetLength(a,100,0);
   for I := Low(a) to High(a) do
    begin
       // hier ist im Original (SetLength(a[i],i) schon einmal ein Fehler:
       // bei i=0 wäre das Array a[0,0] an dieser Stelle sonst nur 1-dimensional!,
       // der Versuch einer Belegung führt unweigerlich zum Crash
       // also muss entweder die Länge der zweiten Dimension auf mindestens 1
       // gesetzt werden oder es müsste eine Sicherheitsabfrage auf das Element A[i,0]
       // erfolgen
       SetLength(a[i],i+1);
       a[i][random(i)]:=char(32+1);
   end;
   a[19,5] := 'Haus';
   a[59,2] := 'Dies ist ein Test';
   Save2DArray(a,ms);
   // hierdurch wird unmissverständlich sichtbar,
   // wie verheerend der originale Code sich auswirkt!
   // Da das Array A ja ab hier nicht mehr benötigt wird,
   // darf seine Eliminierung in der folgenden Anzeige der Elemente des Array B
   // keinerlei Folgen haben; ist das so bei Deinem Code ?
   setlength(a,0,0);
   ms.Position := 0;
   Load2DArray(b,ms);
   Showmessage(format('%s'#13#10'%s',[b[19,5], b[59,2]]));
   finally
     ms.Free;
   end;
end;
Was passiert wohl, wenn Du das Ergebnis der entsprechende Anwendung unter Verwendung Deiner Originalunit vergleichst mit der von mir korrigierten Version der Unit ?

Ach ja, und im übrigen stammt der von Dir gepostete Code in seinem Kern eigentlich nicht von Dir (bzw. von einem Thomas Wassermann ?), sondern von einem P.Below aus dem Jahre 2003, der den Code unter dem Titel "Save and load a 2-dimensional dynamic array" in Torry's Delphi Pages veröffentlicht hatte (http://www.swissdelphicenter.ch/torr....php?id=1971); leider ist diese Urheberschaft in Deiner Unit nirgendwo erwähnt. Bei diesem Code ist der von Dir eingebrachte Fehler allerdings nicht relevant, da der Autor das 2D-Array nicht mit einem T2DStringArray, sondern mit einem T2DBooleanArray entworfen hat. Dieser Code wurde in Deiner Unit uReadWrite_2D_Arrays.pas exakt übernommen und allein der Typ des Arrays ohne jede Rücksicht auf notwendige weitere Anpassung ausgetauscht.

Bummi 8. Apr 2011 20:28

AW: Mehrdimensionales, dynamisches Array speichern
 
Ja, ich war wohl recht müde ....
[delphi]
writer.Write(A[i, x][1], SizeOf(Char) * Length(A[i,x]));

//bzw.

reader.Read(A[i, x][1],SizeOf(Char) * slen);
[delphi]

ist der richtige Code.

Maik81ftl 8. Apr 2011 22:27

AW: Mehrdimensionales, dynamisches Array speichern
 
Was gegen, wenn ich den hier mal ein Anstoß einwerfe???

Delphi-Quellcode:
procedure TRegel.SetYear(AValue: TYear);
var
  d, m: integer;
  s: string;
begin
  FYear := AValue;
  FFilename := Format('%s%d.%s', [FPath, FYear.Yaer, FExt+FYear.Benutzer.Name+' '+FYear.Benutzer.Lastname]);
  if FileExists(FFilename) then begin
    // Daten laden
     with TIniFile.Create(FFilename) do try
       for m := 1 to 12 do begin
         for d := 1 to 31 do begin
           s := Format('%.2d-%.2d', [m, d]);
           Items[d, m].HasRegel := ReadString(s, 'HasRegel', 'false');
         end;
       end;
     finally
       Free;
     end;
  end;
end;
sollte sich eigendlich von selbst erklären. must nur die variablen an deines anpassen.
zur not bitte via PN nachfragen.
würde denne in tewa so aussehen.

Code:
[01-05]
HasRegel=1
Stärke=Normal
Schmerz=Keine

[01-06]
HasRegel=1
Stärke=Normal
Schmerz=Keine

[01-07]
HasRegel=1
Stärke=Normal
Schmerz=Keine

[01-08]
HasRegel=1
Stärke=Leicht
Schmerz=Keine
zugegeben. ist ein Programmausschnitt aus meinem Aktuellen Projekt "Mestruationskalender"

himitsu 9. Apr 2011 07:16

AW: Mehrdimensionales, dynamisches Array speichern
 
Nein, TIniFile ist nicht für viele Daten gedacht, welche sich auch noch oft ändern.

(Begründung siehe anderer Thread)

PS: "HasRegel" schreibt man mit Doppel-S oder mit T.

haentschman 9. Apr 2011 07:49

AW: Mehrdimensionales, dynamisches Array speichern
 
@himi:
Zitat:

PS: "HasRegel" schreibt man mit Doppel-S oder mit T.
... im Denglisch nicht. :stupid:

Maik81ftl 9. Apr 2011 08:20

AW: Mehrdimensionales, dynamisches Array speichern
 
Zitat:

Zitat von himitsu (Beitrag 1094040)
Nein, TIniFile ist nicht für viele Daten gedacht, welche sich auch noch oft ändern.

(Begründung siehe anderer Thread)

PS: "HasRegel" schreibt man mit Doppel-S oder mit T.

Deine Begründung in genanten Thread gelesen. und da hab ich mal eine Frage??? Wen zum Teufel kratzen denne Laufzeiten, wenn es auf die nicht in Geringsten ankommt???

wenn ich 'nen Programm schreibe, wo je ns Zählt, denne würde ich auch auf ein anderen Format umsteigen.

Zitat:

Zitat von haentschman (Beitrag 1094044)
@himi:
Zitat:

PS: "HasRegel" schreibt man mit Doppel-S oder mit T.
... im Denglisch nicht. :stupid:

Jopp da hast du recht. :D

Dunkelbunt27 10. Apr 2011 14:03

AW: Mehrdimensionales, dynamisches Array speichern
 
Hallo,

könnte mir vielleicht jemand mal eine Speichern und Laden-Prozedur für meine Variablen schreiben?
So komme ich momentan nicht voran...

Delphi-Quellcode:
type
  TBuchstabe = record
                      Zeichen : char;
                      attribut : byte;
                    end;
buchstabe : array of array of TBuchstabe;
Man kann folgendes verwenden:
Delphi-Quellcode:
SetLength(buchstabe,AnzahlZeilen+1,AnzahlSpalten+1);

for i := 1 to AnzahlZeilen do             // von 1 starten - nicht ändern!
    for n := 1 to AnzahlSpalten do
    begin
      buchstabe[i,n].Zeichen := ' ';
      buchstabe[i,n].attribut := 0;
    end;
  end;
Diesen Datensatz möchte ich möglichst unkompliziert in eine Datei packen UND auch wieder laden können, also aus den gespeicherten Daten der Datei das buchstaben-Array wieder befüllen.

Ich hoffe jemand kann helfen.

FG Dunkelbunt

Bummi 10. Apr 2011 22:21

AW: Mehrdimensionales, dynamisches Array speichern
 
Delphi-Quellcode:
type
  TBuchstabe = record
                      Zeichen : char;
                      attribut : byte;
                    end;


TbuchstabenArray = array of array of TBuchstabe;

Procedure SaveTBuchstabenArray(b:TbuchstabenArray;const fn:String);
var
  fs:TFileStream;
  i,x,y:Integer;
begin
  fs:=TFileStream.Create(fn, fmCreate or fmShareDenyWrite);
  try
    x := High(b) + 1;
    y := High(b[0]) + 1;
    fs.Write(x,SizeOf(x));
    fs.Write(y,SizeOf(y));
    for i := low(b) to high(b) do
    fs.Write(b[i][0].Zeichen, y*SizeOf(TBuchstabe));
  finally
    fs.Free;
  end;
end;

Procedure LoadTBuchstabenArray(var b:TbuchstabenArray;const fn:String);
var
  fs:TFileStream;
  i,x,y:Integer;
begin
  fs:=TFileStream.Create(fn, fmOpenRead);
  try
    fs.Read(x,SizeOf(x));
    fs.Read(y,SizeOf(y));
    SetLength(b,x,y);
    for i := low(b) to high(b) do
    fs.Read(b[i][0].Zeichen, y*SizeOf(TBuchstabe));
  finally
    fs.Free;
  end;
end;

Dunkelbunt27 11. Apr 2011 15:23

AW: Mehrdimensionales, dynamisches Array speichern
 
Ich stand ja richtig auf der Leitung...
ich hab es etwas abgeändert, nur zur 'Übersichtlichkeit', da ich mich mit sprechenden Bezeichnungen besser zurecht finde.
Delphi-Quellcode:
type
  TBuchstabe     = record
                      Zeichen : char;
                      attribut : byte;
                    end;
var
  buchstabe      : array of array of TBuchstabe;

Procedure Speichern(const Dateiname:String);
var
  Datei:TFileStream;
  i,x,y:Integer;
begin
  Datei:=TFileStream.Create(Dateiname, fmCreate or fmShareDenyWrite);
  try
    x := High(buchstabe) + 1;
    y := High(buchstabe[0]) + 1;
    Datei.Write(x,SizeOf(x));
    Datei.Write(y,SizeOf(y));
    for i := low(buchstabe) to high(buchstabe) do
    Datei.Write(buchstabe[i][0].Zeichen, y*SizeOf(TBuchstabe));
  finally
    Datei.Free;
  end;
end;

Procedure Laden(const Dateiname:String);
var
  Datei:   TFileStream;
  i,x,y: Integer;
begin
  Datei:=TFileStream.Create(Dateiname, fmOpenRead);
  try
    Datei.Read(x,SizeOf(x));
    Datei.Read(y,SizeOf(y));
    SetLength(buchstabe,x,y);
    for i := low(buchstabe) to high(buchstabe) do
    Datei.Read(buchstabe[i][0].Zeichen, y*SizeOf(TBuchstabe));
  finally
    Datei.Free;
  end;
end;

Vielen Dank für eure Arbeit! :dp:
FG Dunkelbunt

DeddyH 11. Apr 2011 15:44

AW: Mehrdimensionales, dynamisches Array speichern
 
Wenn das Array leer ist, bekommst Du Probleme beim Speichern, da Du in der ersten Dimension auf das erste Element zugreifst, ohne es auf Existenz zu prüfen. Beim Lesen hast Du das selbe Problem bei einer leeren Datei. Und statt
Zitat:

Delphi-Quellcode:
x := High(buchstabe) + 1;

würde ich eher
Delphi-Quellcode:
x := Length(buchstabe);
schreiben.

himitsu 11. Apr 2011 15:54

AW: Mehrdimensionales, dynamisches Array speichern
 
Zitat:

Zitat von DeddyH (Beitrag 1094443)
Wenn das Array leer ist, bekommst Du Probleme beim Speichern, da Du in der ersten Dimension auf das erste Element zugreifst, ohne es auf Existenz zu prüfen. Beim Lesen hast Du das selbe Problem bei einer leeren Datei. Und statt
Zitat:

Delphi-Quellcode:
x := High(buchstabe) + 1;

würde ich eher
Delphi-Quellcode:
x := Length(buchstabe);
schreiben.

Das macht eigentlich keinen unterschied, da es equivalent ist, denn die Funktion High ist so definiert
Delphi-Quellcode:
function High(const a: TMyArray): integer;
begin
  Result := Length(a) - 1;
end;
Bei statischen Arrays wird es ebenso im Compiler ausgerechnet und dann direkt verwendet.


Aber natürlichst speicherst/liest du immer nur den ersten Wert aller SubArrays (egal ob sie existieren oder nicht) und alle weiteren Daten der Subarrays werden ignoriert,
also für x = 1 bis Ende (
Delphi-Quellcode:
buchstabe[i][x]
)

DeddyH 11. Apr 2011 15:59

AW: Mehrdimensionales, dynamisches Array speichern
 
Dass das bei dynamischen Arrays keinen Unterschied macht, weiß ich auch. Aber erstens ist das so verständlicher, da es ja um die Länge geht und zweitens sollte man sich das gleich richtig angewöhnen, sonst bekommt man bei statischen Arrays, die nicht 0-indiziert sind, später Probleme.

Dunkelbunt27 11. Apr 2011 17:01

AW: Mehrdimensionales, dynamisches Array speichern
 
Zitat:

Aber erstens ist das so verständlicher, da es ja um die Länge geht und zweitens sollte man sich das gleich richtig angewöhnen, sonst bekommt man bei statischen Arrays, die nicht 0-indiziert sind, später Probleme.
Das ist ein guter Einwand, ich persönlich finde es so verständlicher.

Wo wir gerade beim Thema sind, könnte mir jemand mal diese Zeile erklären:
Zitat:

Datei.Read(buchstabe[i][0].Zeichen, y*SizeOf(TBuchstabe));
TBuchstabe ist ja ein Typ (Record aus Zeichen, Attribut) was liefert denn SizeOf(TBuchstabe) zurück?
X ist die Länge in beide dimensionen, oder wird automatisch nur die x Dimension genommen?
Y ist dann die Länge für die Y Dimension, wenn X=0, richtig?

Ich versteh nicht ganz wo die Attribute und Zeichen gespeichert werden.

FG Dunkelbunt

Bummi 11. Apr 2011 22:29

AW: Mehrdimensionales, dynamisches Array speichern
 
Der Record wird als ganzes gespeichert, dies geht bei allen Recordstrukturen die nur aus Elementen einer "fixen Größe" bestehen als z.B. String[33] statt String beinhalten.
SizeOf liefert bei Deiner Definition 4 Byte bei der Definition
Delphi-Quellcode:
  TBuchstabe = packed record
                      Zeichen : char;
                      attribut : byte;
                    end;
3 Byte ....aehaem, ab 2009 da dort Char=2Byte


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:34 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