2011-01-16 4 views
1

Lets sagen, ich speichere Header in irgendeiner Datei, sondern ein Teil des Headers ist dynamisch Länge, so etwas wie dies es aussehen würde:C++: Wie man dynamische Daten elegant in eine Struktur liest?

struct HeaderTest { 
    int someparam; 
    int more; 
    int arrsize;  // how big array, read arrsize elements into arr: 
    int arr[arrsize]; // not valid 
}; 

Gibt es eine elegante Möglichkeit, dynamische Daten in eine Struktur zum Lesen?

+2

Welche Daten? von wo willst du lesen? Was meinst du mit * "dynamischen Daten" *? – Nawaz

+1

Wären Sie nicht besser dran mit z.B. ein 'std :: vector' als letztes Mitglied? Ihre Frage scheint genauso zu sein, "dynamische" Daten wie die Deserialisierung zu speichern. –

+0

Kann einen Vektor von Ints anstelle von einem Array verwenden, ohne arsize zu kennen. – DumbCoder

Antwort

2

Nun, wenn Sie keine Containerklasse verwenden möchten (nicht sicher, warum Sie das nicht tun würden), können Sie arr als Zeiger auf int deklarieren und es dem Client überlassen, den Zeiger auf einen gültigen Speicherort zu initialisieren sowie richtig initialisieren arrsize.

Das heißt, Sie sollten nur einen Vektor verwenden. Warum Dinge schwieriger machen als sie sein müssen?

6

Statt mit arr und arrsize Variablen in der Struktur, können Sie Ihre Struktur wie folgt definieren:

struct HeaderTest 
{ 
    int someparam; 
    int more; 
    std::vector<int> data; 
} 

Kein arr, keine arrsize. Verwenden Sie einfach std::vector und std::vector::size(). Das ist elegant!

Und wenn Sie binäre Daten aus einer Datei lesen möchten, dann können Sie so schreiben:

struct HeaderTest 
{ 
    int someparam; 
    int more; 
    int size; 
    char *data; 
} 

Andernfalls gehen mit der ersten Struktur!


Ein Hinweis:

Ihre Kommentare überall Lesen, ich fühle, dass ich Ihnen vorschlagen, ein gutes Buch zu bekommen, und es zuerst studieren. Hier ist die Liste von wirklich guten Büchern:

The Definitive C++ Book Guide and List

+1

Wie lesen Sie die Dateidaten in diese Struktur, wenn Sie die Länge der Daten nicht kennen? – Newbie

+0

-1 Sie können Binärdaten nicht in einen Vektor einlesen. –

+0

@Newbie: Sie können Dateidaten lesen und push_back in den Vektor wie folgt: 'data.push_back (file_data_int)'. – Nawaz

0

Ich glaube nicht, dass es eine sehr elegante Art und Weise ist. Sie sollten dieses dynamische Element wahrscheinlich zu einem Zeiger machen, dann zuerst alle anderen Elemente lesen, Speicher für den letzten zuweisen und dann den Rest der Daten lesen.

Da Sie in C++ sind, können Sie dieses in einer Klasse kapseln, so dass Sie sich in Ihrem Code keine Gedanken mehr um dieses Detail machen müssen. Wie auch andere gesagt haben, wäre ein std::vector ein C++ - ähnlicher Ansatz als ein einfacher Zeiger und manuell zugeordneter Speicher. Es wäre auch resistenter gegen Speicherlecks.

+0

"Sie können dies in einer Klasse schön kapseln", ich weiß nicht, was du meinst, aber meinst du ich könnte irgendwie mit 1 Codezeile den Header lesen und es würde automatisch den Vektor für Arrsize Elemente zuordnen und die Elemente dort lesen? und das würde auch für andere Strukturen funktionieren (mit wenig oder gar keiner Arbeit)? Können Sie ein Beispiel für diese Klassenmethode zeigen? – Newbie

+0

Warum ist "eine Zeile Code" eine Voraussetzung? –

+0

mit einer Zeile meine ich eine Methode, die mich nicht zwingt, meine Reader-Funktion manuell für jede Struktur aufzuteilen. Ich dachte, wenn es eine Möglichkeit gibt, nur struct zu schreiben und dann fread() aufzurufen, würde es alle notwendigen Zuordnungen machen und meine Struktur wäre bereit zu verwenden. – Newbie

1

Diese Antwort ist mehr C als C++, aber Sie können leicht realloc() verwenden, um die Größe eines Puffers so groß wie nötig zu ändern. Wie in diesem Pseudocode gezeigt.

struct HeaderTest { 
    int someparam; 
    int more; 
    int arrsize; 
    int arr[]; 
}; 

HeaderTest* pkt = (HeaderTest*)malloc(sizeof(HeaderTest)); 
read(&pkt,sizeof(pkt)); 
pkt = (HeaderTest*)realloc(pkt,sizeof(HeaderTest)+sizeof(pkt->arr[0])*pkt->arrsize); 
read(pkt->arr,sizeof(int)*pkt->arrsize); 
+0

Ist 'int arr [];' erlaubt? – Nawaz

+3

ja. [] gibt ein Array an, dessen Größe nicht bekannt ist, und es kann das letzte Element in jeder Struktur sein. –

0

Niemand konnte Ihnen die Lösung geben, die Sie wollten, aber ich habe es für Sie entwickelt. Diese Funktion nimmt einen C-String-Dateinamen, öffnet die Datei und liest den Inhalt für Sie. Es gibt ein int * zurück, das t.container zugewiesen werden kann. Genießen.

int* read(char* filename) 
{ 
    // open file 
    ifstream f; 
    f.open(filename, ios::binary); 
    // get file size 
    f.seekg (0, ios::end); 
    int length = f.tellg(); 
    f.seekg (0, ios::beg); 
    // allocate new int* 
    length = (length -(sizeof(int)*2))/sizeof(int); 
    int* buf = new int[length]; 
    for(int i = 0; i < length; ++i) 
    { 
     // create byte array to hold bytes 
     unsigned char* temp = new char[sizeof(int)]; 
     stream.read((char*)temp, sizeof(int)); 
     // convert byte array to int 
     for(int j = 0; j < sizeof(int); ++j) 
     { 
      buf[i] = buf[i] + (temp[j] << (j*8)); 
     } 
     delete[] temp; 
    } 
    f.close(); 
    return buf; 
}