Strukturen, Arrays und Pointer...



  • Hallo

    erstmal ein bißchen code zum reinlesen:

    struct LandTileData
    {
      unsigned long flags;
      unsigned short texID;
      char tilename[20];
    }; // 26 byte
    
    struct LandTileGroup
    {
      unsigned long junk;
      LandTileData data[32];
    }; // 836 byte
    
    struct StaticTileData
    {
      unsigned long flags;
      byte weight;
      byte quality;
      unsigned short unkn1;
      byte unkn2;
      byte quantity;
      unsigned short animID;
      byte unkn3;
      byte hue;
      unsigned short unkn4;
      byte height;
      char tilename[20];
    }; //dieses struct ist 37 byte groß
    
    struct StaticTileGroup
    {
      unsigned long junk;
      StaticTileData data[32];
    };  //1188 byte
    

    Genau richtig, das sind einfach nur 4 Structs. 2 Der Structs enthalten wiederum andere Structs. Soweit ist das auch kein Problem. Doch leider will ich ein Array aus den LandTileGroup und den StaticTileGroup machen und diese mittels fread() vollschreiben.

    fread(LandGroups, 428032, 1, handle);
       fread(StaticGroups, 608256, 1, handle);
    
    StaticTileGroup *StaticGroups = new StaticTileGroup[512];
       LandTileGroup *LandGroups = new LandTileGroup[512];
    

    Jetzt hab ich aber ein kleines Problem:

    sizeof(*StaticGroups) und sizeof(*LandGroups) geben mir jeweils 1188 und 836 byte zurück obwohl ich doch ein Array mit 512 Einträgen erstellt habe.

    Dh ich hätte doch 1188*512 und 836*512 byte herausbekommen sollen.

    zugreifen auf einen Wert des Arrays tue ich ja so:
    zB: &StaticGroups[0-511].data[0-31].tilename

    das klappt aber nur wenn im 1. eine 0 steht, also die erste Gruppe gelesen werden soll.

    Ich hoffe ich habe mein Problem einigermaßen klar geschildert. Falls ich noch zusätzlichen Code posten soll dann sagts einfach.

    Gruß,
    Buhmann



  • Das kann so auch nicht gehen. Mit * dereferenzierst du lediglich den Zeiger (Im Falle ienes Arrays ist das das Selbe wie ArrayXY[0]). Grundsätzlich ist es sowieso besser, wenn man einen sizeof(<Datentyp> ) macht und ihn einfach mit der Anzahl Elemente multipliziert.

    -junix



  • C++!?

    <edit>Jo, hast recht... wenn auch eigentlich C (ausser new) ich muss wohl gepennt haben... ->Verschoben</edit>

    [ Dieser Beitrag wurde am 12.12.2002 um 14:05 Uhr von junix editiert. ]



  • Gefährliche Sache die du da machst....
    Das grundlegende Problem wurde ja schon von Junix gelüftet
    (sizeof(*pointer) != anzahl_elemente * sizeof(array_typ))

    Aber was du da machst:
    fread(LandGroups, 428032, 1, handle);

    ist sackgefährlich, weil die Grösse der Struktur ungleich der Summe aller
    Teilgrössen sein kann!
    (Compiler muss die Elemente nicht aneinanderreihen)

    Also
    fread(LandGroups,n*sizeof(Dein_Typ), 1, handle);

    Dein zweites Problem

    das klappt aber nur wenn im 1. eine 0 steht, also die erste Gruppe gelesen
    werden soll

    Kann glaub nur beantwortet werden, wenn du den Code schreibst, wie das Objekt
    erzeugt wurde, oder du genau definierst, was "klappt nicht" bedeutet...



  • #include <iostream>
    
    struct StaticTileData
    {
      unsigned long flags; // 4
      short int weight;    // 2
      char tilename[5];    // 5
    };                     // = 11 ?
    
    int main()
     {
      int einzel_elemente = sizeof(short int) + sizeof(unsigned long) + sizeof(char[5]);
      int ganzer_typ      = sizeof(StaticTileData);
      std::cout << einzel_elemente << " " << ganzer_typ;
      return 0;
     }
    

    Ergibt als Ausgabe "11 12".. (Windoof, Dev-Cundund)
    Soviel zum Thema "wir rechnen die Grösse von Hand aus...."



  • Ok, vielen Dank schonmal!

    @Solaris'dUKe:
    ich weiß zwar nicht warum genau der compiler das macht, aber er scheint auf den nächsten 4er-pack auf zu runden.

    ich hab das problem durch
    #pragma pack(n) // n=1 oder 2;4;8;16
    lösen können

    Zu meinem anderen Problem:

    Ich hoffe ich hole nicht zu weit aus wenn ich euch jetzt mein ganzes Problem erkläre. Fall doch dann antwortet mir bitte einfach nur auf ein Tutorial in dem mir beschrieben wird binäre Dateien elegant und effektiv zu schreiben, lesen und zu editieren.

    Ersteinmal der Aufbau der Dateien die ich lesen will:

    512 Blöcke der LandTileGroup
    512 Blöcke der StaticTileData

    LandTileGroup
    DWORD unknown
    32 Blöcke [Land Tile Data]

    StaticTileGroup
    DWORD unknown
    32 Blöcke [Static Tile Data]

    (wer's gern genauer haben will liest hier: http://dkbush.cablenet-va.com/alazane/file_formats.html#3.19)

    Dafür habe ich diese Structs geschrieben. Ich möchte also mit diesen beiden Arrays die ganze Datei auf einmal lesen, dann das nötige in den Arrays ändern und dann die beiden Arrays wieder in die Datei schreiben.

    Zu meinem Programm:

    StaticTileGroup StaticGroups = new StaticTileGroup[512];
       LandTileGroup LandGroups = new LandTileGroup[512];
    
       if ((handle = fopen("tiledata.mul", "rb")) == NULL)
       {
       }
       rewind(handle);
    
       fread(LandGroups, 428032, 1, handle); // ja Solaris'dUKe, ich ändere das noch :P
       fread(StaticGroups, 608256, 1, handle); 
       fclose(handle);
    
       return *StaticGroups;
    

    das ist ein teil der Funktion read(), die offensichtlich den Rückgabewert StaticTileGroup hat. Das klappt auch alles ganz toll soweit wenn da nicht noch ein Problem wäre:

    int main(int argc, char* argv[])
    {
      int gruppe, nummer;
    
      StaticTileGroup *x = new StaticTileGroup[512];
    
      if (argc==2)
      {
    
        gruppe = GetGroupNumber(StrToInt(argv[1]));
        nummer = StrToInt(argv[1]) - gruppe * 32 - 1;
    
        *x = read(StrToInt(argv[1]));
        printf("Tilename %s\n", &(x[gruppe].data[nummer].tilename));
      }
    (...)
    }
    

    Zu "gruppe" und "nummer": Ich hab ja 512 Gruppen habe mit je 32 Untergruppen. Um von einer explizit angegebenen Nummer (in Form des argv) die Gruppe und Untergruppe zu finden benutze ich eben diese Formel.

    Leider bekomme ich nur eine Ausgabe wenn ich Zahlen zw. 1 und 32 als Argument beim Programmstart angebe. Dh "gruppe" ist dann 0 und "nummer" zwischen 0 und 31. Es ist also bildlich gesprochen als wär das Array nur 1 Feld Groß, also
    StaticTileGroup *x = new StaticTileGroup[1];

    Ich hoffe ich habe euch mein Problem etwas näherbringen können 😉


Anmelden zum Antworten