Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C++/Pascal] Odczyt z pliku rekordów struct

Piter_mg 19 Lut 2012 11:34 1839 6
  • #1 19 Lut 2012 11:34
    Piter_mg
    Poziom 9  

    Witam.

    Swojego czasu stworzyłem w Pascalu grę - klon Boulder Dasha. Obecnie postanowiłem przenieść go do C++ (kompilator MingW). Program już działa całkiem nieźle, ale napotkałem problem z przeniesieniem moich starych poziomów z wersji w TP.

    W wersji Pascalowej poziomy były zapisywane do pliku składającego się z takich rekordów - co pozwalało w prosty sposób (seek/read) się po nim poruszać i wczytywać porządany etap.

    Zdefiniowane to było tak:

    Kod: pascal
    Zaloguj się, aby zobaczyć kod


    W C++ odpowiednik opisałem tak:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Do odczytania takiego pliku stworzyłem następującą funkcję:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    No i niestety nie działa to tak, jak powinno. O ile przy pierwszym rekordzie część wartości pobierana jest poprawnie, to im dalej - tym gorzej. Z drugiej strony - jeśli tworzę w C++ nowy plik z taką strukturą, to dane są zapisywane i pobierane tą funkcją prawidłowo.

    Podejrzewam, że problem tkwi gdzieś w sposobie w jaki Pascal i C++ tworzą pliki tego typu - być może w opisie tej mojej struktury. Porównywałem je w edytorze hex i pliki faktycznie się nieco różnią.

    I tutaj pytanie do Was - czy to ja robię błąd w opisie mojej struktury w C++, czy też błąd wynika z różnicy w zapisie plików przez Pascal i C++? Będę wdzięczny za jakąś wskazówkę. Na razie jedyne rozwiązanie (siłowe) jakie chodzi mi po głowie, to skonwertowanie w Pascalu tego formatu zapisu do pliku binarnego i import do struktury w C++.

    0 6
  • #2 19 Lut 2012 13:24
    PDT
    Poziom 24  

    Zapewne chodzi o różnice w 'alignment' tj wyrównywaniu do okrągłej wartości adresów elementów rekordu/struktury. Kompilator Pascal-a i C może różnie to realizować.
    Zamieść przykładowe zapisy pliku z Pascal-a i C do porównania.

    0
  • #4 19 Lut 2012 19:44
    Piter_mg
    Poziom 9  

    Ok, wyłączyłem. Niestety nie pomogło. Oba pliki (w załączeniu) powstały dla zadanych wartości (poniżej dla C++) :

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    I teraz tak. Pliki różnią się o 4 Bajty - zauważyłem, że :

    1) Pascal dodaje coś na samym początku pliku - jednobajtowa wartość, niewiadomego pochodzenia.

    2) C++ dziwnie zapisuje wartość 10 - wszędzie zamiast zapisać po prostu 0A zapisuje ciąg 0D 0A (jak znak powrotu karetki). Jeśli zmieniłbym na 20 - będzie zapisane zwyczajnie (HEX) 14.

    Obawiam się, że ciężko będzie przeskoczyć ten problem.

    0
  • Pomocny post
    #5 19 Lut 2012 22:01
    krru
    Poziom 32  

    string[20] w pascalu i char[20] w C to nie to samo.
    Pascal zapisuje długość w dodatkowym bajcie(to pewnie o nim pisałeś), no i nie kończy napisu 0.

    jeśli chodzi o to 0A 0D to otwieraj plik w trybie binarnym ("rb").

    0
  • #6 19 Lut 2012 22:54
    Piter_mg
    Poziom 9  

    krru napisał:
    Pascal zapisuje długość w dodatkowym bajcie(to pewnie o nim pisałeś), no i nie kończy napisu 0.

    Masz rację. C++ potrzebuje tego zera, ponieważ napis jako taki nie ma normalnie zdefiniowanej długości. Pascal przy deklaracji np. n:string jeśli się nie określi inaczej przyjmuje długość na 255 - czyli bajt. Właśnie, ten dodatkowy bajt faktycznie może określać długość łańcucha. Dzięki!

    krru napisał:
    jeśli chodzi o to 0A 0D to otwieraj plik w trybie binarnym ("rb").

    W sumie to się tyczy przede wszystkim zapisu - bo wtedy jest tworzony ten zapis. To może być dobry trop, sprawdzę to.

    0
  • #7 26 Lut 2012 09:25
    Piter_mg
    Poziom 9  

    Dla porządku chcę napisać, że faktycznie przestawienie trybu odczytu na plik binarny rozwiązało prawie do końca problem.

    Pojawił się po drodze jeszcze jeden problemik dot. różnic między tym w jaki sposób zapisywał pliki rekordów Turbo Pascal, a czynią to Free Pascal i gcc.

    Jedna ze zmiennych w rekordzie to integer. Turbo Pascal zapisywał go na 2B - czyli tradycyjnie, 15-bitów + znak.

    Z kolei zarówno Free Pascal jak i gcc napotykając na integer (smallint w gcc) zapisywały go na 3B.

    Ponieważ de facto format plików z TP interesował mnie wyłącznie do odczytu rozwiązałem to bardzo prosto - wczytując po prostu integer jako dwa kolejne Bajty. I tyle wystarczy.

    Co ciekawsze - jak się zrobi zarówno w FP jak i TP plik typu file of integer, to zapis jest normalnie na 2B - jak jest rekord, to dochodzi dodatkowy Bajt. Dziwne. Być może jest to związane z tym, o czym pisaliście wcześniej - czyli wyrównywaniem struktur... ale tak czy siak udało się pokonać problem. Jeszcze raz dzięki za pomoc i naprowadzenie mnie na właściwy tor!!

    0