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].tilenamedas 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 sollKann 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önnenZu 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 StaticTileDataLandTileGroup
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