Schreibbefehl ersetzt zu wenig



  • Hallo zusammen,
    folgendes Problem:
    Ich habe dieses Template geschrieben:

    template <class X> void dateischreiber (X datensatz, int zeigerPosition) {
        fstream songstream ("Song.txt",ios::out|ios::in);
        songstream.seekp (zeigerPosition, ios::beg);
            if (songstream.good()) {
            songstream << datensatz;
            } else {
                cerr << "Bibliothek beschädigt oder nicht auffindbar! \n";
                system("PAUSE");
            }
            songstream.close();
    }
    

    Das ganze soll einfach nur den übergebenen Datensatz (meist ein Array of Char) in die angegebene Datei schreiben.
    Soweit funktioniert das auch, nur falls in der Datei schon etwas an der übergebenen Stelle vorhanden ist, wird nicht aller ersetzt.
    Vielleicht ein kleines Beispiel zu Verständnis:
    Ich übergebe im 1. Durchlauf ein Char [100] mit dem Inhalt "Testtext" und den Zeiger schicke ich einfach mal an die Stelle null.
    Im 2. Durchlauf schicke ich ebenfalls ein Char [100] mit dem Text "Hallo" rein (Zeiger wie eben).
    In einer später abgefragten Ausgabe kommt nun für die ersten 100 Stellen der Datei "Halloext" raus.

    Wie bekomme ich es hin, dass tatsächlich die vollen 100 Stellen überschrieben werden und nicht nur die tatsächlich gefüllten ?

    Gruß Jörg



  • bei "songstream << datensatz" wird dein char[100] in einen char* auf das erste Element aufgelöst.
    Der Stream interpretiert den Zeiger als Beginn einer Null-terminierten Zeichenkette und schreibt daher nur den Text bis (ausschließlich) zum Null-Byte.

    Was du möchtest erreichst du nicht mit den Streaming-Operatoren (<<).
    Dafür benötigst du die write-Methode (http://www.cplusplus.com/reference/iostream/ostream/write/)



  • Naja, alternativ kannst Du Dein Array ja vorher mit der entsprechenden Anzahl von Leerzeichen auffüllen, so dass es immer 99 Zeichen und ein 0-Byte hat.



  • Vielen Dank ! Das war's !

    Aber vielleicht noch die Frage:
    Warum macht es keinen Unterschied, wenn ich dem übergebenen Datensatz im Konstruktor seiner Classe lauter Leerzeichen zuweise ? Dann müsste doch eigentlich erst an Stelle 100 die 0 sein, oder?

    Gruß Jörg



  • Ja so ist es ja auch.
    Ein Leerzeichen ist wenn du so willst nichts anderes wie ein Buchstabe oder eine Zahl. Die ganzen string funktionen wie strlen, strcmp, strcpy gehen immer von Null-terminierten chars aus. Philosphie anderer Programmiersprachen früher war, dass am Anfang die Größe des Strings stand und darauf die Zeichen kamen.

    Es hat sich halt so eingebürgert, dass man entweder die Länge eh schon weiß oder 😃 es eben nicht auf die Länge drauf ankommt. Also ein strcpy liest immer ein Zeichen, kopiert es. Wenn es 0 war fertig, ansonsten nächstes Zeichen lesen. Uninteressant wie lang der string ist.

    Bei Dateien kannst du alle Zeichen abspeichern, auch 0 Bytes. Denn das Filesystem arbeitet mit Längen. Wenn du aber aus C++ ein write aufrufst mit Angabe des chars, muss dieser Null-terminiert sein, oder du gibst die gewünschte Länge mit an und es wird in die Datei die gesamte Länge geschrieben.

    Überleg mal was die Ausgaben hier wohl sein werden:

    cout << sizeof("Hallo")<<endl;
    cout << strlen("Hallo")<<endl;
    

    Hier eine Lösung:

    template <class X> void dateischreiber (X datensatz, size_t size, int zeigerPosition) {
        fstream songstream ("Song.txt",ios::out|ios::in);
        songstream.seekp (zeigerPosition, ios::beg);
            if (songstream.good()) {
            songstream.write(&datensatz, size);
            } else {
                cerr << "Bibliothek beschädigt oder nicht auffindbar! \n";
                system("PAUSE");
            }
            songstream.close();
    }
    
    char hallo[100] = "Hallo"; // Hallo\0\0\0\0\0\0...
    char x[100] = "x"; // x\0\0\0\0\0\0...
    
    dateischreiber(hallo, sizeof(hallo), 0); // schreibt 100 Zeichen
    dateischreiber(x, sizeof(hallo), 0); // schreibt auch 100 Zeichen
    // File: x\0\0\0\0\0\0\0...
    
    dateischreiber(hallo, sizeof(hallo), 0); // schreibt 100 Zeichen
    dateischreiber(x, strlen(hallo), 0); // schreibt 1 Zeichen
    // File: xallo\0\0\0\0\0\0...
    

    Der << Operator wurde ungefähr so überschrieben:

    ostream &operator<<(ostream &stream, const char *string)
    {
       stream.write(string, strlen(string));
       return stream;
    }
    

Anmelden zum Antworten