Zapisywanie tablic dynamicznych

0

Mam pytanie w jaki sposób można zapisa tablicę o niezdefiniowanej wielkości (w moencie kompilacji) do pliku w trakcie działania programu (po ustaleniu wielkości tej tablicy w trakcie wykonywania programu rzecz jasna)

Chodzi mi o sytuacje gdy tablica ta jest częścią jakiejś klasy którą zapisuje do pliku.

0

Możesz spróbowac zapisac sobie wielkosć tablicy a potem dane, a przy odczycie pierwsze odczytujesz wielkośc a potem w pęlti po kolei czytasz kolejne wartości i tak aż do tej wartości wcześniej odczytanej.

// ale dużo słów: "odczytujesz"' ;)

0

Gdyby się tak dało zrobi to by nie było problemu...

Moja sytuacja wygląda następująco:
(przykładowy schemat, który jedbynie obrazuje mój problem :D)

THistory=object
klub:string;
point:integer;
end;

TPlayer=object
history:array of history;
///bleble
end;

Potrzebuje zapisac do pliku ileśtam tych obiektów player i każdy z inna ilościa pól history;

0

Ani obiektów ani stringów (samych czy stanowiących pola rekordu) nie da się tak zapisać do pliku bo zapiszą się tylko wskaźniki. Albo trzeba samemu obsłużyć zapis stringu (z uzwględnieniem długości) albo uzyć krótkich łańcuchów lub array of char.

Zapis kompletnej tablicy dynamicznej do pliku jest prosty.

x:array of TCostam
F: file of TCostam
[...]
BlockWrite(F,x[0],Length(x));

Podobnie można zapisać string

s:string;
f:file of byte;
[...]
BlockWrite(F,s[1],Length(s)); //zwróć uwagę na inne indeksowanie

Odczyt:
SetLength(x,FileSize(F));
BlockRead(F,x[0],FileSize(F));
analogicznie string

to zadziała gdy plik sklada się wyłącznie z 1 tablicy lub 1 stringa. W przeciwnym wypadku musisz zapisywac pole z długością, bo nie bedziesz wiedział ile odczytać.

0

Troche się rozpędziłem bo myślałem że to już wszystko jasne.
Rzeczywiście jeśli jest tylko jedna dynamiczna to jest luzik, ale jesli jest wiecej to w jakiej kolejnosci mam odczytywac to z pliku? Troche sie zamotałem... :P

Proisłbym o schematyczne rozwiązanie do przykładu który podałem wcześcniej.

0

Swoją drogą, jak na sztywno ustawi się string'a np.:

s:string[80];

a będzie on częścią rekordu, to nie będzie traktowany jako wskaźnik na jakiś obszar pamięci, tylko tablica zawarta wewnątrz rekordu. Wadą jest maksymalna długość 255 znaków.

0
Szczawik napisał(a)

Swoją drogą, jak na sztywno ustawi się string'a

Tom miał na myśli pisząc o krótkich łańcuchach. Deklaracja:
S:ShortString;
jest równoważna
S:string[255];

t4iglo napisał(a)

ale jesli jest wiecej to w jakiej kolejnosci mam odczytywac to z pliku?

W tej samej w której zapisałeś. Musisz obmyślić sobie jakąś strukturę pliku, np:
DługośćTablicy1, Tablica1, DługośćTablicy2, Tablica2 itd

jeszcze jedna porada: jesli masz dane różnych typów (np długość to LongInt [nie używaj Integer i Cardinal w plikach, bo ich wielkość może sie zmienić w przyszłych wersjach kompilatora, poza tym zawsze rób rekordy jako packed record bo wyrównywanie pól też się może zmienić], pierwsza tablica jest of TRecord1, druga of TRecord2) wtedy zrób plik nietypowany lub of Byte i zapisuj np tak

BlockWrite(F,Tablica1[0], Length(Tablica1)*SizeOf(TRecord1));

0

Wielkie dzięki za pomoc, ale mam jeszcze jedno małe pytanko. Rozumiem że gdyby doszło jeszcze coś takiego:

type
bazagraczy=array of tplayer;

tstore=object
baza:bazgraczy;
//inne rzeczy do zapisu
end;

//....

p:file of tstore;

To sposób zapisu i odzczytu byłby taki sam jak to przedstawiłeś tylko jeszcze bradziej skompkowany (bo kolejna dynamiczna tablica, wewnątrz kórej znajduje się kolejna dynamiczna tablica, wewnątrz której...)

To już moja ostatnia wątpliwośc, pozdrawiam

0

Można dodać w rekordzie jedno pole będące długością stringa.

0

Ale zrozumcie, że moim problemem nie jest tutaj string!!! (niepotrzebnie ustawiłem go jako dynamiczną tablice :( ) Chodzi o zapis do pliku jednego obiektu typu TSTORE który ma w sobie wiele różnych rzeczy w tym DYNAMICZNĄ TABLICE graczy, natomiast każdy gracz ma w sobie rożne pola i DYNAMICZNĄ TABLICĘ objectu THistory.

hehehehe, troche zamotałem... :p

0

No to "nie ma bata na pirata", nie da sie tego zrobic automatycznie :(
jedynie:

type
TMyFile = file of byte;
THistory = object
  klub:string;
  point:integer;
  end;
TPlayer = object
  history:array of THistory;
  history_count: integer;
  imie, nazwisko: string;
  procedure Zapisz(var File: TMyFile);
end;
TPlayer_poor = record //dane statyczne
  imie, nazwisko: string;
end;
TStore = object
  baza: array of TPlayer;
  baza_count:integer;
  imie_kota: string;
  procedure Zapisz(nazwa: string);
end;
TStore_poor = record // dane statyczne
  imie_kota: string;
end;

procedure TPlayer.Zapisz(var File: TMyFile);
var i: integer;
      Tmp: TPlayer_poor;
begin
Tmp.imie := imie;
Tmp.nazwisko := nazwisko;
BlockWrite(File, Tmp, SizeOf(Tmp)); // zapis dodatkowych danych
BlockWrite(File, history_count, SizeOf(history_count)); // zapis wielkosci tablicy
 for i:=0 to history_count-1 do
  BlockWrite(File, history[i], SizeOf(THistory)); // zapis poszczegolnych historii
end;

procedure TStore.Zapisz(nazwa: string);
var File: TMyFile;
      Tmp: TStore_poor;
      i: integer;
begin
AsignFile(File, nazwa);
rewrite(File);
Tmp.imie_kota := imie_kota;
BlockWrite(File, Tmp, SizeOf(Tmp)); // zapis dodatkowych danych
BlockWrite(File, baza_count, SizeOf(baza_count)); // zapis wielkosci bazy

 for i:=0 to baza_count-1 do
  baza[i].Zapisz(File);
CloseFile(File);
end;

var
 Store: TStore;
.........................

Store.Zapsiz('c:\export.dat');

Jak sie gdzies nie kropnolem, to powinno dzialac :P

0

Uprzejmie dziękuje!!!

1 użytkowników online, w tym zalogowanych: 0, gości: 1