Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » String per \0-Zeichen einlesen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
07.03.2005, 20:23 Uhr
Oliver
S2-Pixelgeneral


Hi,

bin grade ziemlich durcheinander, die Funktion soll bis zu einem 0-Zeichen, einen String aus einer Binärdatei lesen. In szTemp steht auch ein gültiger "String" drinnen, aber bei der Zuweisung von sStr stürtzt das Programm ab. Weiß jemand woran das liegen könnte?


C++:
void ReadString(FILE*fFile,string &sStr)
{
    list<char> lChars;
    char cTemp;

    while(cTemp!='\0')
    {
        fread(&cTemp,sizeof(char),1,fFile);
        lChars.push_back(cTemp);
    }

    char*szTemp = new char[lChars.size()];

    unsigned i=0;
    for(list<char>::iterator it=lChars.begin();it!=lChars.end();++it)
        szTemp[i++]=*it;

    sStr=szTemp;

    delete[]szTemp;
}


--
Demokratie ist die Diktatur der Mehrheit.

www.siedler25.org/ ( Siedler2 - Remake )
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
07.03.2005, 20:38 Uhr
enno-tyrant
Frag nicht!


war das nicht so:

C++:
fread(&cTemp,1,sizeof(char),fFile);


selbstverständlich kann ich mich auch irren
--
...um etwas zu verstehen muß man wissen wie es funktioniert...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
08.03.2005, 09:53 Uhr
Th



Also das ist jawohl die komplizierteste Routine zum Einlesen eines Strings, die ich je gesehen hab (list -> array -> string)!

Und auch noch fehlerhaft: cTemp ist uninitialisiert (vor der while-Schleife).

Mein Vorschlag:

C++:
void ReadString(FILE*fFile,string &sStr)
{
    char cTemp;

    sStr.clear();
    while(fread(&cTemp,sizeof(char),1,fFile), cTemp != '\0')
       sStr += cTemp;
}


 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
08.03.2005, 12:41 Uhr
0xdeadbeef
Gott
(Operator)


Am einfachsten wärs so:

C++:
#include <fstream>
#include <string>

using namespace std;

// ...

ifstream in("foo.dat", ios::binary);
string s;

getline(in, s, '\0');


...und am sinnvollsten, weil man gleich C++-Datentypen kriegt. Was hat FILE* eigentlich in C++-Code zu suchen?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 08.03.2005 um 12:41 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
08.03.2005, 13:41 Uhr
Oliver
S2-Pixelgeneral


Ich dachte nur: Wenn ich die einzelnen Zeichen an den String hänge, muss aber jedes mal ne temp variable angelegt werden, dann der String rüberkopiert werden und wieder den Speicher um 1 mehr belegen.
--
Demokratie ist die Diktatur der Mehrheit.

www.siedler25.org/ ( Siedler2 - Remake )
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
08.03.2005, 14:01 Uhr
Th



Die String-Klasse reserviert sich Speicher in Blöcken (z.B. 32, 64, 256, 1024, ...), d.h. erst wenn diese Blockgröße überschritten wird, wird neuer (größerer) Speicher allokiert und dann die Daten kopiert. Die list-Klasse reserviert sich für jeden Eintrag (d.h. bei dir je char), einen Block (meistens mind. 8 Bytes) und das ist viel ineffizienter als einen zusammenhängenden Block zu verwalten.

Verwende wie 0xdeadbeef geschrieben hat, am besten nur noch STL-Klassen. Die Entwickler haben diese Klassen schon hochoptimiert, besser als es jeder von Hand schreiben könnte.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
08.03.2005, 14:36 Uhr
Oliver
S2-Pixelgeneral


Die Streamklassen waren mir bisher immer nur ein bisschen unheimlich. Na werd ich's mal so machen.
--
Demokratie ist die Diktatur der Mehrheit.

www.siedler25.org/ ( Siedler2 - Remake )
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
08.03.2005, 17:40 Uhr
0xdeadbeef
Gott
(Operator)


Naja - gerade die Stringklassen sind performancetechnisch nicht so unglaublich schnell. Der Vorteil ist eher, dass sie typsicher sind, und dir die Speicherverwaltung abnehmen können (wenn du weitere STL-Klassen wie z.B. std::string benutzt). Wos um jeden CPU-Takt geht, würde ich sie nicht benutzen, aber wo das nicht der Fall ist, sparst du dir mit iostream jede Menge Zeit und Nerven, weil du nicht nach 20.000 Speicherlecks, buffer overflows und ähnlichen Gemeinheiten suchen musst.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
08.03.2005, 18:19 Uhr
Oliver
S2-Pixelgeneral


So hab's umgeschrieben, stürzt aber immernoch ab . Ich hab 2 Funktionen Load und Save. Wenn getline[...] kommt, passiert es.



C++:
bool Geraete_DB::Load()
{
    ifstream ifs("gp_db.bin",ios::binary);
    unsigned Anz_Plaetze;
    unsigned Anzahl_Geraete;

    if(!ifs)
        return 0;

    ifs.read((char*)&Anz_Plaetze,sizeof(unsigned));

    for(unsigned i=0;i<Anz_Plaetze;++i)
    {
        getline(ifs,m_vPlaetze[i].m_sName,'\0');
        getline(ifs,m_vPlaetze[i].m_sInhaber,'\0');
        getline(ifs,m_vPlaetze[i].m_sStrasse,'\0');
        getline(ifs,m_vPlaetze[i].m_sAdresse,'\0');
        getline(ifs,m_vPlaetze[i].m_sSteuernummer,'\0');
        getline(ifs,m_vPlaetze[i].m_sPlatzNummer,'\0');

        ifs.read((char*)&Anzahl_Geraete,sizeof(unsigned));

        for(unsigned z=0;z<Anzahl_Geraete;++z)
        {
            getline(ifs,m_vPlaetze[i].m_vGeraete[z].m_sGeraeteBezeichnung,'\0');
            ifs.read((char*)&m_vPlaetze[i].m_vGeraete[z].m_uGeraeteNummer,sizeof(unsigned));
            ifs.read((char*)&m_vPlaetze[i].m_vGeraete[z].m_uMWSteuer,sizeof(unsigned char));
            ifs.read((char*)&m_vPlaetze[i].m_vGeraete[z].m_uProzent,sizeof(unsigned char));
        }
    }

    ifs.close();

    return 1;
}



void Geraete_DB::Save()
{
    ofstream ofs("gp_db.bin",ios::binary);

    unsigned Anzahl_Geraete;
    unsigned Anz_Plaetze


    Anz_Plaetze=m_vPlaetze.size();
    ofs.write((char*)&Anz_Plaetze,sizeof(unsigned));

    for(unsigned i=0;i<Anz_Plaetze;++i)
    {
        ofs.write(m_vPlaetze[i].m_sName.c_str(),m_vPlaetze[i].m_sName.length()+1);
        ofs.write(m_vPlaetze[i].m_sInhaber.c_str(),m_vPlaetze[i].m_sInhaber.length()+1);
        ofs.write(m_vPlaetze[i].m_sStrasse.c_str(),m_vPlaetze[i].m_sStrasse.length()+1);
        ofs.write(m_vPlaetze[i].m_sAdresse.c_str(),m_vPlaetze[i].m_sAdresse.length()+1);
        ofs.write(m_vPlaetze[i].m_sSteuernummer.c_str(),m_vPlaetze[i].m_sSteuernummer.length()+1);
        ofs.write(m_vPlaetze[i].m_sPlatzNummer.c_str(),m_vPlaetze[i].m_sPlatzNummer.length()+1);

        Anzahl_Geraete=m_vPlaetze[i].m_vGeraete.size();
        ofs.write((char*)&Anzahl_Geraete,sizeof(unsigned));

        for(unsigned z=0;z<Anzahl_Geraete;++z)
        {
            ofs.write(m_vPlaetze[i].m_vGeraete[z].m_sGeraeteBezeichnung.c_str(),m_vPlaetze[i].m_vGeraete[z].m_sGeraeteBezeichnung.length()+1);
            ofs.write((char*)&m_vPlaetze[i].m_vGeraete[z].m_uGeraeteNummer,sizeof(unsigned));
            ofs.write((char*)&m_vPlaetze[i].m_vGeraete[z].m_uMWSteuer,sizeof(unsigned char));
            ofs.write((char*)&m_vPlaetze[i].m_vGeraete[z].m_uProzent,sizeof(unsigned char));
        }
    }



    ofs.close();

}


--
Demokratie ist die Diktatur der Mehrheit.

www.siedler25.org/ ( Siedler2 - Remake )
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
09.03.2005, 14:01 Uhr
Oliver
S2-Pixelgeneral


Achja, die Konstante "npos" von basic_string hat einen komischen hohen Wert, also anscheined uninitialisiert:


C++:
_Myt& erase(size_type _P0 = 0, size_type _M = npos)
        {if (_Len < _P0) // hier Absturz!!
            _Xran();
        _Split();
        if (_Len - _P0 < _M)
            _M = _Len - _P0;
        if (0 < _M)
            {_Tr::move(_Ptr + _P0, _Ptr + _P0 + _M,
                _Len - _P0 - _M);
            size_type _N = _Len - _M;
            if (_Grow(_N))
                _Eos(_N); }
        return (*this); }



--
Demokratie ist die Diktatur der Mehrheit.

www.siedler25.org/ ( Siedler2 - Remake )

Dieser Post wurde am 09.03.2005 um 14:02 Uhr von Oliver editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: