Binärdaten unbestimmter Größe einlesen



  • µngbd schrieb:

    es wird ein string objekt übergeben.

    Was ist denn das?

    mmmmmmmmmh schmeckt lecker mutti! einfach mal probieren.



  • ;fricky schrieb:

    falls es noch ums einlesen von dateien unbestimmter grösse geht, hier was aus meiner snippet-sammlung

    Danke für den Code. Das Problem ist aber mittlerweile mehr, dass die Daten in einem bestimmten Format vorliegen müssen und nicht nur, dass sie unbestimmten Länge sind. Aber das hab ich glaube ich vorerst gelöst, da ich einfach den Code des Autor in C nachgebaut hab.

    ;fricky schrieb:

    µngbd schrieb:

    es wird ein string objekt übergeben.

    Was ist denn das?

    ich nehme an es ist ein typedef für irgendeine struktur. kann man hier nicht sehen, da der code wohl ziemlich gekürzt wurde.
    🙂

    string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...

    Kleiner Nebengedanke. Woher weiß die fread-Funktion von C eigentlich von wo aus sie im Dokument lesen soll. Fängt die von vorne an und merkt sich dann was schon gelesen wurde und macht da dann weiter, oder muss ich das selber festlegen? Ich kümmere mich darum bisher nämlich nicht, der Autor des C++-Codes tut dies aber auch nicht.



  • Antoras schrieb:

    Kleiner Nebengedanke. Woher weiß die fread-Funktion von C eigentlich von wo aus sie im Dokument lesen soll. Fängt die von vorne an und merkt sich dann was schon gelesen wurde und macht da dann weiter, oder muss ich das selber festlegen?

    das merkt sich fread in der FILE-struct, die es dir bei fopen gibt.
    mit 'fseek' kannste den filepointer selber hin und herschieben.
    🙂



  • string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...
    

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern.!!



  • sorry wegn meiner fahrgelässigen formattierung, wollt törlich so machen:

    string ist ein typedef auf einen Pointer auf einen char. Ich hab leider nicht genau gewusst welcher Code hier wichtig ist und welcher nicht. Der Code funktioniert beim ersten Mal ja, nur beim zweiten Mal eben nicht...

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern tun!!
    mfg



  • besser0r schrieb:

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern.!!

    ^^geht doch, musste nur in c++ das #include<string.h> weglassen.
    🙂



  • noch besser0r schrieb:

    besser das nicht machen, sonst kann man den code nicht in c++ benutzern tun!!
    mfg

    Vielleicht will ich ja gar nicht, dass der Code von C++ benutzt wird. 😉
    Ehrlich gesagt hab ich daran noch gar nicht gedacht. Werde mir angewöhnen für eine Zeichenkette was anderes zu benutzen, vielleicht cstring oder so. Danke für den Hinweis!

    ;fricky schrieb:

    das merkt sich fread in der FILE-struct, die es dir bei fopen gibt.
    mit 'fseek' kannste den filepointer selber hin und herschieben.

    Ok, gut zu wissen.

    Ich bin jetzt auch bei meinem Hauptproblem weitergekommen. Hab in der Funktion Text3D_readFile einfach

    fread(buffer, sizeof(buffer), size, f);
    

    in

    fread(buffer, sizeof(char), size, f);
    

    umgeändert. Anders wäre es auch Blödsinn.

    Allerdings bekomme ich jetzt nur hässliche Grafikfetzen angezeigt. Aber den Fehler dürfte ich noch finden. Hab höchstwahrscheinlich nur was falsch portiert...



  • Antoras schrieb:

    Vielleicht will ich ja gar nicht, dass der Code von C++ benutzt wird.

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Antoras schrieb:

    fread(buffer, sizeof(char), size, f)

    für 'sizeof(char)' kannste auch immer 1 hinschreiben.
    🙂



  • ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wenn ich das mache, dann nur um eine C-Library mit C++ ansprechen zu können. Mehr auch nicht.

    ;fricky schrieb:

    für 'sizeof(char)' kannste auch immer 1 hinschreiben.

    Hmm, stimmt. 🙂



  • ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wie kommst du denn auf das schmale Brett 😕
    Man kann 1A sauber ANSI C Programmieren und in C++ Code einbinden.



  • besser0r schrieb:

    ;fricky schrieb:

    das sollteste auch garnicht erst in erwägung ziehen. würdest du's tun, dann käme völlig grausames C dabei raus.

    Wie kommst du denn auf das schmale Brett

    deswegen z.b.

    int* new = malloc (100*sizeof(int));  // gleich zwei dinge die c++ nicht will
    

    und dieses gefummel mit #ifdef __cplusplus ist auch recht blöd.
    auch weil c++ allgemein immer mehr an bedeutung verliert, braucht man's eigentlich nicht mehr zu beachten.
    🙂



  • Ich hab mir den Code nochmal durchgeschaut, aber leider keinen Fehler gefunden. Die einzige Möglichkeit bei der ich den Fehler noch vermute ist eine Klassentemplate:

    template<class T>
    class auto_array {
        private:
            T* array;
            mutable bool isReleased;
        public:
            explicit auto_array(T* array_ = NULL) :
                array(array_), isReleased(false)
            {
            }
    
            auto_array(const auto_array<T> &aarray)
            {
                array = aarray.array;
                isReleased = aarray.isReleased;
                aarray.isReleased = true;
            }
    
            ~auto_array()
            {
                if (!isReleased && array != NULL) {
                    delete[] array;
                }
            }
    
            T* get() const
            {
                return array;
            }
    
            T &operator*() const
            {
                return *array;
            }
    
            void operator=(const auto_array<T> &aarray)
            {
                if (!isReleased && array != NULL) {
                    delete[] array;
                }
                array = aarray.array;
                isReleased = aarray.isReleased;
                aarray.isReleased = true;
            }
    
            T* operator->() const
            {
                return array;
            }
    
            T* release()
            {
                isReleased = true;
                return array;
            }
    
            void reset(T* array_ = NULL)
            {
                if (!isReleased && array != NULL) {
                    delete[] array;
                }
                array = array_;
            }
    
            T* operator+(int i)
            {
                return array + i;
            }
    
            T &operator[](int i)
            {
                return array[i];
            }
    };
    

    Codeauszug der C++-Library:

    unsigned short numVerts = toUShort(buffer);
    auto_array<float> verts(new float[2 * numVerts]);
    float* verts2 = verts.get();
    for (int j = 0; j < numVerts; j++) {
        input.read(buffer, 2);
        verts2[2 * j] = scale * ((int) toUShort(buffer) - 32768);
        input.read(buffer, 2);
        verts2[2 * j + 1] = scale * ((int) toUShort(buffer) - 32768);
    }
    

    Mein Code:

    float *verts;
    unsigned short numVerts;
    // ...
    numVerts = toUShort(buffer);
    {
        float vertsTmp[2 * numVerts];
        verts = vertsTmp;
        for (j = 0; j < numVerts; ++j) {
            Text3D_readFile(f, buffer, 2);
            verts[2 * j] = scale * ((int) (toUShort(buffer) - BYTES_15));
            Text3D_readFile(f, buffer, 2);
            verts[2 * j + 1] = scale * ((int) (toUShort(buffer) - BYTES_15));
        }
    }
    

    Passt das so, oder kann da jemand einen Fehler erkennen?



  • ^^wie gross wird 'numVerts'? ist vielleicht zu gross für ein array auf dem stack.
    tip: lass es single-step im debugger laufen und schau dir genau an was passiert, dann findeste bestimmt schnell wo was nicht stimmt.
    🙂



  • Also, ich hab mein Programm und das Tutorialprogramm jetzt mehrmals mit dem Debugger abgesucht und glaube den Fehler jetzt endlich lokalisiert zu haben. Ich glaub, dass ich auch keine Probleme haben sollte ihn zu beseitigen, nur wollte ich nochmal nachfragen, da ich den C++-Quelltext nicht vollständig verstanden habe.

    Erstmal zum Fehler: Die Klasse T3DFont enthält ein Array, das die einzelnen Fontpunkte aufnehmen soll.

    class T3DFont {
        private:
            float spaceWidth;
            float widths[94];
            GLuint displayListId2D;
            GLuint displayListId3D;
        public:
            //Loads the specified font file into a new T3DFont object
            T3DFont(ifstream &input)
            {
                // ...
            }
    }
    

    Meine Struktur sieht ist an sich genau gleich:

    typedef struct _Text3D_ {
        float spaceWidth;
        float widths[94];
        GLuint displayList2D;
        GLuint displayList3D;
    } Text3D;
    

    Im ctor meines Programms wird das Array auch richtig befüllt. Der Unterschied beider Programme ist aber, dass beim TutProg laut eclipseCDT-Debugger ein Array existiert, das nicht nur einen Punkt, sondern auch die anderen drei Variablen beinhaltet. Sozusagen wie wenn ich eine Liste von T3DFont hätte. Diese wird aber beim Aufruf dessen ctor erstellt, was allerdings unlogisch ist:

    T3DFont* font = NULL;
    
    void t3dInit()
    {
        if (font == NULL) {
            ifstream input;
            input.open("charset", istream::binary);
            font = new T3DFont(input);
            input.close();
        }
    }
    

    Hier wird keine Liste angelegt. Die Liste des C++-Programms macht Sinn, ich verstehe deren Allokierung aber nicht. Kann der C++-Compiler hier etwas, das ich nicht weiß? Kann mir hier jemand weiterhelfen?



  • ^^ du musst dir genau ansehen, was dieser konstruktor 'T3DFont(input)' macht.
    das hier:

    T3DFont* font = NULL;
    void t3dInit()
    {
        if (font == NULL) {
            ifstream input;
            input.open("charset", istream::binary);
            font = new T3DFont(input);
            input.close();
        }
    }
    

    wäre in C etwa

    T3DFont* font = NULL;
    ...
    void T3DFont_create_from_file (T3DFont* font, FILE *fp)
    {
       // hier code rein, um den 'font' zu laden
       // und die listen aufzubauen, etc.
       // so wie's der cpp konstruktor macht
       ...
    }
    ...
    void t3dInit()
    {
       if (font == NULL) 
       {
         FILE *fp = fopen ("charset", "rb");
         font = malloc (sizeof(T3DFont));
         T3DFont_create_from_file (font, fp);
         fclose (fp);
       }
    }
    

    🙂



  • Das hatte ich so weit schon. Das Problem ist, dass beim Aufruf des Konstruktors die Liste angelegt wird und nicht erst im Konstruktor. Das ist ja gerade das seltsame. Kann aber auch sein, dass der Debugger mir hier was falsches anzeigt. Werde das jetzt noch mit einem anderen überprüfen. Und den Code schreib ich am besten auch gleich auf die Erstellung einer Liste um. Und gucke dann mal ob es geht...


Anmelden zum Antworten