Odczyt rekordów z pliku kończy się błędem "Runtime error 100"

0

Witam. Przygotowuje sie do kolejnego projektu na studia i mam ciekawy problem. Chcialem teraz przetestować odczyt rekordów z pliku do listy. Jednak ciekawe rzeczy sie dziają i wyskakuje mi runtime error 100 który oznacza brak/koniec pliku. Plik utworzylem wczesniej rewritem. Procedura zapisz normalnie dziala i dopisuje rekordy. Jednak nie moge ich odczytac z pliku. Nawet przy wczytywaniu ograniczylem sie tylko do jednego elementu i ustawilem wskaznik na 0 czyli z tego co wiem pierwszy element. Przed odczytem są już tam rekordy wprowadzone.
Co ciekawe. Gdy zmienilem hauto2 ze wskaznika na element typu auto to udalo sie wczytac rekord do tej zmiennej. Dziwne.

wiem, że kod jest strasznie "brzydki" ale to tylko kod do wstepnej fazy nauki list i plikow z rekordami.

program listytescik;

uses crt;

  type str24 = string[24];
       pauto = ^auto;
       auto = packed record
               model : str24;
               rok : integer;
               wer : str24;
               cena : real;
               next : pauto;
              end;

  var hauto : pauto;
      hauto2: pauto;






procedure zapisz(hauto:pauto);
    var plik: file of auto;
    begin
      assign(plik,'auta.bin');
          reset(plik);
      while hauto <> NIL do
        begin
          Seek(plik, FileSize(plik));
          write(plik,hauto^);


          hauto:=hauto^.next;
        end;
      close(plik);
     end;
procedure wczytaj(hauto2:pauto);
  var plik: file of auto;
begin
   assign(plik,'auta.bin');

   reset(plik);
   seek(plik,0);
   read(plik, hauto2^);

   close(plik);
end;

procedure wstawauto(var hauto:pauto);
  var nowy:pauto;

    begin
      new(nowy);

      readln(nowy^.model);
      readln(nowy^.rok);
      readln(nowy^.wer);
      readln(nowy^.cena);

      nowy^.next:=hauto;
      hauto:=nowy;

      zapisz(hauto);
end;

procedure dodajauto(var hauto:pauto);
 begin

 end;



  procedure wyswietl(hauto:pauto);
  begin
   while hauto <> NIL do
     begin
       writeln(hauto^.model);
       writeln(hauto^.rok);
       writeln(hauto^.wer);
       writeln(hauto^.cena:5:2);

       hauto:=hauto^.next;
     end;
  end;

  begin
    filemode:=2;
    ClrScr;
    hauto:=NIL;
    hauto2:=NIL;

  wstawauto(hauto);

    writeln('---------');

    wczytaj(hauto2);
    wyswietl(hauto);
    readln;
    readkey;
  end.

poprawienie tytułu wątku + dodanie znacznika <code class="pascal"> - fp

0
  1. Formatowanie
  2. Znaczniki
  3. Zły dział (powinno być newbie).
  4. Nie można zapisać wskaźnika do pliku (znaczy można ale po wczytaniu go z pliku nie będzie wskazywał poprawnego miejsca tylko jakieś z d**y wzięte).
  5. Implementacja listy jednokierunkowej z zapisem/odczytem do/z pliku. Przejrzyj kod powinno Ci pomóc. http://4programmers.net/Forum/984740
0

Szczerze mowiac pierwsze widze takie zasady formatowania. Przy kolejnym projekcie bede sie ich trzymal ale teraz szkoda mi czasu na przepisywanie wszystkiego. Chodzi mi tylko o tą jedną rzecz. Nie zapisuje wskaznikow do pliku tylko rekordy. I nie mam pojecia dlaczego one sie nie chca wczytać. Co jest zle w kodzie ?

0
begin
// (...)
  write(plik,hauto^);
// (...)
end;

var
  hauto : pauto;

type
  pauto = ^auto
  auto = packed record
    model : str24;
    rok : integer;
    wer : str24;
    cena : real;
    next : pauto; // <- O TUTAJ
  end;

Jak linijka zaznaczona powyżej nie jest wskaźnikiem który zapisujesz do pliku poleceniem write(plik,hauto^); To od teraz zwracaj się do mnie Ojcze święty.

Podałem Ci link. wystarczy że, w niego klikniesz i przeczytasz ze zrozumieniem metody SaveToFile i LoadFromFile a zobaczysz gdzie robisz błąd i jak go poprawić. Dostałeś GOTOWCA!

0

Przegladam to od godziny, rozbilem u siebie ten rekord tak jak w tym gotowcu. Ale to dalej nie dziala. A mam wszystko tak jak tam. Nie wiem czemu ten blad wywala...

0

@Bluu - nie możesz w ten sposób zapisywać listy do pliku, bo struktura zawiera wskaźnik na kolejny element; Po zapisie adresu na jaki wskazuje ten wskaźnik do pliku i ponownym jego wczytaniu adres ten najprawdopodobniej zmieni się na zupełnie inny, więc całą listę lekko pisząc szlag trafi;

Procedury Zapisz i Wczytaj musisz zmodyfikować tak, aby zapisywane były po kolei wszystkie pola do pliku z pominięciem wskaźnika na kolejny element; Wykorzystaj do tego celu pliki amorficzne, posiłkując się artykułami na temat ich używania;

Przy zapisie każde pole struktury zapisuj osobno, po czym przechodź do kolejnych węzłów listy i rób to samo; Przy odczycie twórz dynamicznie kolejne węzły i uzupełniaj je w dane pobrane z pliku (także dla każdego pola struktury osobno), a wskaźnik na kolejny węzeł listy ustawiaj sam;

Dodatkowo - nie wiem czy zauważyłeś - nigdzie nie zwalniasz listy z pamięci po jej utworzeniu i użyciu, więc masz niesamowity wyciek pamięci; Napisz sobie procedurę zwalniającą z pamięci wszystkie węzły listy i wywołaj ją pod koniec programu.


PS: @babubabu - póki co Ojciec Święty nam się nie zmieni :]

0

Dzieki ! Wiem wiem, faktycznie zapisalem tam wskaźniki i był to duży błąd. Kod wlasciwie od nowa napisalem. Trzymajac sie czytelnych oznaczeń. I chyba wszystko dziala :) Przynajmniej na razie nie widze bledow. Tylko nie wiem czy dobrze mam to zwalnianie pamieci.

program listytescik;
{------------------------------------------------------------------------------}
uses crt;
{------------------------------------------------------------------------------}
  type CarVer = (cheap,med,lux,sport);
       TStr24 = string[24];
       PCarRec = ^TCarRec;

       TCarData =   packed record
               model : TStr24;
               year : integer;
               ver : CarVer;
               price : real;

              end;
         TCarRec = record
               cont:TCarData;
               next:PCarRec;
       end;
{------------------------------------------------------------------------------}
  var FirstCar : PCarRec;
      FirstCar2: PCarRec;
{==============================================================================}

procedure SaveToFileCarList(var FirstCar:PCarRec; directory:TStr24);
    var CarFile: file of TCarData;
        Tmp:PCarRec;
    begin
      assign(CarFile,directory);
      rewrite(CarFile);
      Tmp:=FirstCar;
      while FirstCar <> NIL do
        begin
          Seek(CarFile, FileSize(CarFile));
          write(CarFile,FirstCar^.cont);

          FirstCar:=FirstCar^.next;
        end;
      close(CarFile);
      FirstCar:=Tmp;
     end;
{------------------------------------------------------------------------------}
 procedure LoadFromFileCarList(var FirstCar:PCarRec);
    var CarFile: file of TCarData;
        NewCar:PCarRec;
    begin
      assign(CarFile,'auta');
      reset(CarFile);

      while not eof(CarFile) do
        begin
          new(NewCar);
          read(CarFile,NewCar^.cont);

          writeln(NewCar^.cont.Model);

          NewCar^.next:=FirstCar;
          FirstCar:=NewCar;

        end;
      close(CarFile);
     end;
{------------------------------------------------------------------------------}
procedure DestroyCarList(var FirstCar:PCarRec);
var ToDelete:PCarRec;
begin
    while FirstCar<>NIL do
    begin
    ToDelete := FirstCar;
    FirstCar := FirstCar^.next;
    Dispose(ToDelete);
    end;
end;
{------------------------------------------------------------------------------}
procedure AddCar(var FirstCar:PCarRec; Model:TStr24; Year:integer; Ver:CarVer; Price:real);
  var NewCar:PCarRec;

    begin
      new(NewCar);

      NewCar^.cont.model:=Model;
      NewCar^.cont.year:=Year;
      NewCar^.cont.ver:=Ver;
      NewCar^.cont.price:=Price;

      NewCar^.next:=FirstCar;
      FirstCar:=NewCar;

      //SaveCar(FirstCar);
end;
{------------------------------------------------------------------------------}
procedure IAddCar(var FirstCar:PCarRec);
 var Model:TStr24;
     Year:integer;
     Ver:CarVer;
     Price:real;
 begin
   Writeln('Podaj model: ');
    readln(Model);
    Writeln('Podaj rok: ');
    readln(Year);
    Writeln('Podaj wersje: ');
    readln(Ver);
    Writeln('Podaj cene: ');
    readln(Price);

    AddCar(FirstCar,Model,Year,Ver,Price);

 end;
{------------------------------------------------------------------------------}
procedure PrintCarList(var FirstCar:PCarRec);
 var Tmp:PCarRec;
 begin
    Tmp:=FirstCar;
   while FirstCar <> NIL do
     begin
       writeln(FirstCar^.cont.model);
       writeln(FirstCar^.cont.year);
       writeln(FirstCar^.cont.ver);
       writeln(FirstCar^.cont.price);
       writeln('-----------------------------------');

       FirstCar:=FirstCar^.next;
     end;
   FirstCar:=Tmp;
  end;
{==============================================================================}

  var k,directory:TStr24;
  begin
    filemode:=2;
    ClrScr;
    FirstCar:=NIL;
    FirstCar2:=NIL;
    directory:='auto2';

      {
    repeat
    Writeln('Dodac kolejne auto ?');
    readln(k);
    if k='stop' then continue
    else
    IAddCar(FirstCar);

    until k='stop' ;        }

    LoadFromFileCarList(FirstCar);

    writeln('---------');
    //PrintCarList(FirstCar);
    SaveToFileCarList(FirstCar,directory);

    DestroyCarList(FirstCar);
    DestroyCarList(FirstCar2);
    readkey;
  end.
 

Dzieki za pomoc ! :D

0
 
procedure LoadFromFileCarList(var FirstCar:PCarRec);
var
  CarFile  : file of TCarData;
  NewCar : PCarRec;
begin
  assign(CarFile,'auta');
  reset(CarFile);
  while not eof(CarFile) do
  begin
    new(NewCar);
    read(CarFile,NewCar^.cont);
 
    writeln(NewCar^.cont.Model);
 
    NewCar^.next:=FirstCar;
    FirstCar:=NewCar;
 
  end;
  close(CarFile);
end;

Na mój gust masz tu gigantycznego memleaka. Przy każdym obrocie pętli tworzysz nowy wskaźnik i tym samym tracisz referencję do poprzedniego który zostaje w pamięci. A na dodatek jeszcze przy końcu procedury nie zwalniasz wskaźnika tymczasowego. Moim zdaniem to powinno wyglądać tak:

procedure LoadFromFileCarList(var FirstCar:PCarRec);
var
  CarFile  : file of TCarData;
  NewCar : PCarRec;
begin
  assign(CarFile,'auta');
  reset(CarFile);
  new(NewCar);
  while not eof(CarFile) do
  begin
    read(CarFile,NewCar^.cont);
 
    writeln(NewCar^.cont.Model);
 
    NewCar^.next:=FirstCar;
    FirstCar:=NewCar;
 
  end;
  close(CarFile);
  dispose(NewCar);
end
0

Raczej nie. Przecież tą pamięć zwalnia przez DestroyCarList przechodząc po każdym elemencie. Twoim sposobem tworzy rekord i zaraz go zwalnia - jaki ma to sens? Musiał by przed zwolnieniem skopiować go co mija się z celem bo właśnie z nich tworzy sobie listę.
Ogólnie nie podoba mi się tutaj nazewnictwo zmiennej np. FirstCar - ja użył bym tu raczej czegoś w stylu SelectedCarPtr lub ActiveCarPtr natomiast zachować nazwę FirstCar lub (ListHead) na oznaczenie elementu startowego całej listy w klasie, bo aż prosi się o to żeby zrobić z tego klasę a nie operować na zmiennej globalnej.
Kolejna sprawa zamiast

    NewCar^.next:=FirstCar;
    FirstCar:=NewCar;

zrobiłbym:

    FirstCar^.next:=NewCar;
    FirstCar:=NewCar;

Lepiej do ostatniego elementu dodać nowy niż nowemu wskazać w polu next na poprzedni (znów nazwa nieadekwatna do tego co sobą prezentuje)

(var FirstCar:PCarRec)

Po kiego grzyba to var? Jeśli w ciele funkcji nie zamierzasz zmieniać wskaźnika to odpuść sobie go - będziesz miał już "lokalną kopię wskaźnika" którą możesz modyfikować a po wyjściu z funkcji i tak zostanie olana - nie musiał byś tworzyć tej nieszczęsnej zmiennej tmp.

0

No wlasnie co do nazwy FirstCar. To nie jest losowy wskaznik z listy tylko z zamiaru ma być głową listy, stąd ta nazwa. A jeśli chodzi o przekazanie FifstCar przez VAR to nie rozumie jak to ma działać bez niego. Jeśli chodzi Ci o procedure LoadFromFileCarList, to przecież ja tworze daną liste, więc jaki sens ma jej utworzenie na kopii i usunięcie ze stosu ? Zostałbym z niczym.

I jeszcze takie ogólne pytanie. Jeśli coś mam tutaj źle, brzydko, nieściśle to prosze zwracajcie uwagę, bo będe musiał stworzyć i tak program z listami podwieszanymi. Więc jeśli tutaj narobie marasu to w kolejnym etapie będzie ciężko.

0

przypuśćmy dla uproszczenia, że mamy taki program:

uses
  SysUtils;

procedure TryChangePointer(var DataPtr: PByte);
begin
  Inc(DataPtr, $30);
end;

procedure TryChangePointer2(DataPtr: PByte);
begin
  Inc(DataPtr, $30);
end;

var
  Data: Byte;
  DataPtr: PByte;
begin
  DataPtr := @Data; //pobranie adresu wskaźnika
  WriteLn('Oryginalnie pobrany adres DataPtr: ' + IntToHex(Integer(DataPtr), 8));

  //Jak zachowa się procedura po przekazaniu wskaźnika jako referencja
  TryChangePointer(DataPtr);
  WriteLn('Adres DataPtr po uzyciu TryChangePointer: ' + IntToHex(Integer(DataPtr), 8));

  //A tutaj jak zachowa się procedura po przekazaniu wskaźnika jako kopia
  TryChangePointer2(DataPtr);
  WriteLn('Adres DataPtr po uzyciu TryChangePointer2: '  + IntToHex(Integer(DataPtr), 8));
end.

Wynik:
Oryginalnie pobrany adres DataPtr: 0040A798
Adres DataPtr po uzyciu TryChangePointer: 0040A7C8
Adres DataPtr po uzyciu TryChangePointer2: 0040A7C8

Wniosek z tego taki, że pierwsza procedura modyfikuje oryginalny wskaźnik, który został do niej przekazany a druga operuje sobie na kopii wskaźnika.
PrintCarList niepotrzebnie na początku zapamiętuje oryginalny wskaźnik w celu przywrócenia go przed wyjściem z procedury.

0

Jakoś dziwnie wygląda to wczytywanie z pliku - takie mam wrażenie;

To nie jest losowy wskaznik z listy tylko z zamiaru ma być głową listy, stąd ta nazwa.

Nazwij go Root i nie będzie nieporozumień; Poza tym musisz pamiętać, że jeśli przekazujesz jako parametr głowę listy to musi być ona utworzona w pamięci, bo w procedurze LoadFromFileCarList (nazwij to raczej LoadCarsListFromFile - brzmi sensowniej) tego nie sprawdzasz; Według mnie jeśli ładujesz listę z pliku to powinieneś robić wszystko w tej procedurze, a nie tworzyć głowę listy osobno, a wczytywać resztę listy osobno;

A jeśli chodzi o przekazanie FifstCar przez VAR to nie rozumie jak to ma działać bez niego.

Nijak, albo uzupełnisz listę biorąc globalną zmienną (co nie jest dobre), albo ustaw sobie parametr nie jako var, a jako out i zwróć jedynie wskaźnik na głowę listy, który utworzysz wewnątrz tej procedury:

procedure LoadCarsListFromFile(out ARoot: PCarRec);
begin
  // utworzenie głowy listy i przypisanie do argumentu ARoot

  // wczytanie listy iterując od utworzonej głowy do końca listy
  // już bez zwracania wskaźnika
end;

dzięki temu będziesz wczytywał i tworzył całą listę w jednej procedurze;

Ponadto zobacz na co będzie wskazywać parametr po załadowaniu listy - nie na pierwszy element listy, a na ostatni, bo na koniec nie przypisujesz wskazania da głowę listy, a z pętli pozostaje wskaźnik na ogon.

0

Mialem sporą przerwe ale wracam do projektu :) W kodzie wszystko uporzadkowane. Listy zapisują się w dobrą strone. Dodałem juz listy podwieszane. Tylko nie mam pojecia jak je zapisac do pliku. Plik rekordowy np TDlrRec ( rekord salonu samochodowego w ktorym znajduje sie lista samochodów). Przy deklaracji pliku musze wskazać file of (rekord). I nie mam jak tego dodać, bo to są różne typy rekordowe. Jedyna opcja to wpisywanie po linijce ale wydaje mi sie ze musi byc cos sprytniejszego.

tutaj są te recordy:

  type DlrSize = (small,normal,big);
       DlrFreq = (low, usual, high);
       CarVer = (cheap,med,lux,sport);
       TStr24 = string[24];
       PDlrRec = ^TDlrRec;
       PCarRec = ^TCarRec;

       TDlrData = packed record
             City: TStr24;
             Size: DlrSize;
             Freq: DlrFreq;
             CarList: PCarRec;
       end;

       TCarData =   packed record
               model : TStr24;
               year : integer;
               ver : CarVer;
               price : real;

              end;
         TDlrRec = record
                 cont:TDlrData;
                 next:PDlrRec;
         end;

         TCarRec = record
               cont:TCarData;
               next:PCarRec;
       end;   
0

Napisz może dokładnie jaką bazę danych chcesz zrobić i co dokładnie ma się w niej znajdować. Bo na mój gust źle to sobie zaprojektowałeś i dlatego masz problemy.

0
Bluu napisał(a)

Plik rekordowy np TDlrRec ( rekord salonu samochodowego w ktorym znajduje sie lista samochodów). Przy deklaracji pliku musze wskazać file of (rekord). I nie mam jak tego dodać, bo to są różne typy rekordowe. Jedyna opcja to wpisywanie po linijce ale wydaje mi sie ze musi byc cos sprytniejszego.

Wyjściem jest skorzystanie z plików amorficznych - dzięki temu typ i rozmiar struktur nie będzie musiał być taki sam; Poczytaj artykuł spod tego linku i popróbuj takiego rozwiązania.

0

Ma to polegać na tym że w plikach znajdują się akutalne stany Salonów tzn ilość konrektnych aut w kazdym z nich osobna. Gdzie lista salonow i lista samochodów będzie ciągle się zmieniała. Czasem pojawią się nowe, czasem stare zostaną usunięte. Ma to być taka symulacja rynku samochodowego. DOdatkowo będzie całkiem osobna lista - ciężarówka. Która będzie zawierała auta które ostatnio zostały sprzedane ( musi uzupełniać braki w salonach). Cykl będzie się ciągle powtarzał. Co do plików amorficznych to niby jest to rozwiązanie ale chyba najmniej sprytne i ostateczne. Nie ma sposobu na upakowanie tego jakos do pliku ? Czy plik moze zawierać rekordy 2 różnych typów ?

0

Tak może. PLIKI AMORFICZNE.

0

Co do plików amorficznych to niby jest to rozwiązanie ale chyba najmniej sprytne i ostateczne.

A no tak, bo pliki amorficzne wymyślono tylko po to, by się z nimi użerać i męczyć;

Nie ma sposobu na upakowanie tego jakos do pliku ? Czy plik moze zawierać rekordy 2 różnych typów ?

Właśnie do tego celu się nadają - do zapisu czegokolwiek, co ma nieregularną budowę i nie można tego łatwiej zapisać (łatwiej jeśli chodzi o wbudowane mechanizmy, jak pliki typowane); Ty masz dwa rekordy o różnych budowach i różnym rozmiarze, więc nie możesz ich upakować do pliku rekordowego - zrozum to raz a porządnie;

Zapis do pliku amorficznego jest banalny, więc nie ma najmniejszego sensu kombinować, aby tylko wykorzystać te nieszczęsne pliki typowane; Do tego możesz skorzystać ze strumienia TFileStream, przez co będziesz miał dostępne takie metody jak WriteBuffer i ReadBuffer, w zupełności wystarczające do tego celu;

Jak chcesz kombinować to droga wolna, choć IMHO będzie to tylko strata czasu - nic na tym nie zyskasz, a dodatkowo niepotrzebnie zobfuskujesz sobie kod.

0

Nigdy nie mialem klas i troche mnie to przeraza... Używam plików amorficznych i teraz została mi jedna porcedura i będe mógł zacząc bawić się pierdołami i kończyć projekt.

Mianowicie nie do konca mam pomysl jak odczytac z tego pliku Liste listy. Są tam zapisane rekordy w kolejnosci

Dane Salonu
Dane Auta
Dane Auta
...
Dane Auta
Dane Salonu
Dane Auta
Dane Auta
...
Dane Auta
itd...

Napisalem sobie jakąś wstępną procedure ale jest tam taki moment, że gdybym chciał rozróżnić kolejną porcje danych czy sa ta dane salonu czy auta to musze je najpierw gdzieś wczytać. I Tutaj wlasnie jest ten problem...

Kolejny problem....
Chciałem jakos wykorzystać parametr z funckcji BlockRead ktory zwraca ilosc przeczytanych bajtów. Tylko nie wiem dlaczego zwraca mi to ciągle zero... a dane się normalnie przypisują.
! Wlasnie przed chwilą udało mi sie uzyskać z tego wartość, ale tylko przy pierwszej komendzie BlockRead. Potem dalej przybiera wartosc =0.

procedure LoadFromFileDlrList( var ActiveDlr:PDlrRec; directory:TStr24);
   var DlrFile: file;
       NewDlr:PDlrRec;
       NewCar:PCarRec;
       TmpDlr:TDlrData;
       TmpCar:TCarData;
       Bytes:integer;
   begin
     DestroyDlrList(ActiveDlr);

     {$i-}
     assign(DlrFile,directory);
     reset(DlrFile,1);
     {$i+}
     if IOResult<>0 then
         begin
           writeln('Brak Pliku');
         end


     else
      begin       // pierwszy element jak zawsze wyjątkowy
       new(NewDlr);
       BlockRead(DlrFile,NewDlr^.cont,SizeOf(NewDlr^.cont),Bytes);
       ActiveDlr:=NewDlr;
       NewDlr^.next:=NIL;
        if Bytes<>0 then writeln('kupa');

       repeat

         new(NewCar);  // tutaj tez wyjątek
        BlockRead(DlrFile,NewCar^.cont,SizeOf(NewCar^.cont),Bytes);
        NewDlr^.cont.CarList:=NewCar;
        NewCar^.next:=NIL;

         repeat         // zczytywane kolejnych aut

         BlockRead(DlrFile,TmpCar,SizeOf(TmpCar),Bytes);

         AddCar(NewDlr^.cont.CarList,TmpCar.Model,TmpCar.Year,TmpCar.Ver,TmpCar.Price);

        until  Bytes<>SizeOf(TCarData);

         // zczytywanie kolejnych salonów
         BlockRead(DlrFile,TmpDlr,SizeOf(TmpDlr),Bytes);
        AddDlr(ActiveDlr,TmpDlr.City,TmpDlr.Size,TmpDlr.Freq);

       until Bytes=0;
      end;
     close(DlrFile);
    end;   
0

Nigdy nie mialem klas i troche mnie to przeraza...

To raczej jest mały problem - wystarczy spojrzeć do artykułu Delphi - OOP i poczytać, potestować; Podstawy obiektowości łykniesz bardzo szybko, a do obsługi strumienia TFileStream potrzebna Ci wiedza dotycząca tworzenia instancji klasy, zwalniania jej z pamięci na koniec oraz używania jej metod, nic więcej;

Mianowicie nie do konca mam pomysl jak odczytac z tego pliku Liste listy.

Najpierw zastanów się jak ma wyglądać struktura pliku po zapisie, tak aby odwrotną drogą można było wczytać dane z pliku i zbudować w pamięci identyczną strukturę, jaka była przed zapisem; Jeśli tego nie wiesz to nawet nie idź dalej, bo stracisz tylko czas;

Napisalem sobie jakąś wstępną procedure ale jest tam taki moment, że gdybym chciał rozróżnić kolejną porcje danych czy sa ta dane salonu czy auta to musze je najpierw gdzieś wczytać.

O tym właśnie napisałem wyżej - nie zabieraj się za coś, czego nie masz przemyślanego i nie masz pewności, że będzie odwracalne;

Jeżeli zapisujesz dane dwóch różnych struktur to musisz przed każdym zapisywanym rekordem zapisać informację o jego typie; Przeznacz na to jeden bajt - jeśli ma poprzedzać dane salonu to wpisz 0, a jeśli dane samochodu to wpisz 1 (lub dowolną inną, z góry ustaloną wartość); Przed zapisem każdego rekordu najpierw wpisujesz ten prefiks (0 lub 1), a po nim dane jednego rekordu; Następnie znów prefiks i znów dane rekordu;

Przy odczycie robisz odwrotnie - odczytujesz najpierw bajt informujący o typie rekordu, sprawdzasz jego wartość i na jego podstawie tworzysz nowy węzeł, który uzupełniasz danymi wczytanymi z pliku; Potem kolejny prefiks i kolejne dane - tak do końca pliku;


Kodu póki co analizować nie będę, bo skoro nie wiesz jak wykonać zapis i odczyt tak, aby dało się to odwrócić to kod na pewno jest błędny; Poza tym nie posłuchałeś i nie wykorzystałeś strumienia TFileStream; Klasa ta ma metody, dzięki którym łatwo zapiszesz i łatwo odczytasz blok danych (bardzo podobne do BlockWrite i BlockRead); Możesz wykorzsytać metody Write i Read lub WriteBuffer i ReadBuffer - jak wolisz;

0

Wielkie dzięki ! Miałem wlasnie pisać o tym że chciałem dodac do pliku takie "identyfikatory" liczbowe ale uznałem, że to za bardzo łopatologiczne, ale jak widać potrzebne :)

A co do tych strumieniowych to ciekawiej to wyglada :) Poczytam poćwicze :)

Tylko szczerze mowiąc nie widze za bardzo jakichś wielkich zalet tego zapisywania strumieniowego. Kod ładniej wygląda ale jest taka funkcja która np pozwala pominąć tą metodę z wstawianiem 0,1 ? Bo czytałem sporo ale nie widzialem nic co by sie nadawało.

0

Nie potrzebujesz Id. Za Id może działać wskaźnik na strukturę. Id potrzebujesz tylko podczas zapisu/odczytu.

0
Bluu napisał(a)

Tylko szczerze mowiąc nie widze za bardzo jakichś wielkich zalet tego zapisywania strumieniowego.

Jest wiele zalet w korzystaniu ze strumieni - wykorzystaj je a sam je zobaczysz;

Bluu napisał(a)

Kod ładniej wygląda ale jest taka funkcja która np pozwala pominąć tą metodę z wstawianiem 0,1 ?

Skoro miałbyś je pomijać podczas odczytu to po co w ogóle je zapisywać? Musisz taki bajt odczytać i sprawdzić jaką wartość zawiera, po to by wiedzieć jaką strukturę utworzyć w pamięci dla nowego węzła; Jeśli tego nie zrobisz to nie będziesz mógł poprawnie ani zbudować listy w pamięci, ani tym bardziej poprawnie odczytać danych z pliku;

Bluu napisał(a)

Bo czytałem sporo ale nie widzialem nic co by sie nadawało.

Klasa TFileStream ma właściwość Position, która określa pozycję kursora - możesz tę pozycję dowolnie zmienić; Dodatkowo masz właściwość Size, która zawiera rozmiar strumienia w bajtach.

0

Kod ładniej wygląda ale jest taka funkcja która np pozwala pominąć tą metodę z wstawianiem 0,1 ?

Skoro miałbyś je pomijać podczas odczytu to po co w ogóle je zapisywać? Musisz taki bajt odczytać i sprawdzić jaką wartość zawiera, po to by wiedzieć jaką strukturę utworzyć w pamięci dla nowego węzła; Jeśli tego nie zrobisz to nie będziesz mógł poprawnie ani zbudować listy w pamięci, ani tym bardziej poprawnie odczytać danych z pliku;

W tym momencie chodziło mi ogolnie o zapis/odczyt do/z pliku :)

Dzieki za pomoc ! Zaraz zabieram sie za pisanie tego z wykorzystaniem TFileStream :)

0

W tym momencie chodziło mi ogolnie o zapis/odczyt do/z pliku

W przypadku strumieni obie operacje są bardzo proste - musisz tylko wiedzieć ile bajtów chcesz odczytać i jak je wczytywać do zmiennych;

Poczytaj sobie o tej klasie co nieco i spróbuj jej użyć a zobaczysz, że bardzo wygodnie się z nich korzysta.

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