Anfängerproblem - Lesefunktion gibt falschen Wert zurück



  • Nein, das ios::binary bzw. ios_base::binary benötigst Du nicht.
    Wenn es sich um eine 'lesbare Datei' handelt, so ist 'datei_1 >> var' die richtige Wahl. Dein Template könnte etwa so aussehen:

    template<class T>
    bool lese( T& var, char *dateiname ) // T& liefert die Referenz; die Funktion liefert 'true' falls das Lesen ok ging
    {
             ifstream datei_l(dateiname);
             if(!datei_l.is_open())
             {
                 cerr << datei_l << " Error" << endl;
                 return false;
             }
             datei_l >> var;  // genau so sollte es gehen
            // datei_l.read(reinterpret_cast<char*>(&var), sizeof(var)); // geht nicht, da die Datei lesbaren Text enthält und kein Speicherabbild
             if( datei_1 )
                  return true;
             return false;
    }
    

    Und der Aufruf:

    int main()
    {
        // char einlesen[100]; string ist immer besser als char[]
        string einlesen;
        string quelle;
    
        cout << "Quelle: ";
        cin >> quelle;
    
        if( lese(einlesen, quelle) )
            cout << "datei: " << einlesen << endl;
        //for (int i=0; i < einlesen.size(); ++i) {cout << einlesen[i];}  (-> ausgabe für "einlesen" (wenn "einlesen" ein string wäre))
    
        system("pause");
    }
    

    :xmas2: Werner



  • Ah, mein Profil geht wieder (-> Ich bin fast_schon_noob)
    Vielen Dank für die Mühe, Werner Salomon, leider ist das Problem so noch immer nicht gelöst,
    Fehlermeldung des Compilers:"31 C:\Dokumente(...) cannot convert `std::string' to `char' for argument `2' to `bool lese(T&, char*) [with T = std::string]' "*
    wenn ich in Z.7 string statt char einsetze, kommt das gleiche heraus, wenn ich den Zeiger bei "Dateiname"(Z.7) auch noch entferne,
    Fehlermeldung:"31 C:\Dokumente (...) instantiated from here".Trotzdem, nice Try 🙂



  • Einige Anmerkungen zum Code von Werner:

    Werner Salomon schrieb:

    template<class T>
    // Es heißt „lies“, nicht „lese“.
    // 'string' statt 'char*'
    bool lies(T& var, string const& dateiname)
    {
             ifstream datei_l(dateiname.c_str()); // Da wir Strings verwenden …
             if(!datei_l.is_open())
             {
                 cerr << datei_l << " Error" << endl;
                 return false;
             }
             datei_l >> var;  // genau so sollte es gehen
             // Was soll denn folgender Code?
             // if( datei_1 )
             //     return true;
             //return false;
             // Besser:
             return datei_l.good();
    }
    

    Außerdem finde ich by-ref-out-Parameter immer ein wenig mittelmäßig furchtbar. Parameter haben gefälligst Eingabeparameter zu sein, die Ausgabe erledigt der Rückgabwert. Man kann ja ein 'std::pair' zurückgeben.



  • AAHHH! Jetzt lässt es sich kompilieren 👍 . Stimmt, das mit dem ".c_str()" hätte mir auch auffallen müssen. Danke Konrad Rudolph!
    EDIT1: Wäre es eigentlich möglich jetzt eine ganze Zeile einzulesen, also dass man nur noch schreiben muss: lese(var, quelle, 3); und man bekommt den wert von Zeile 3 in eine Variabe übergeben?
    EDIT2:

    // Es heißt „lies“, nicht „lese“.

    Die Funktion "lese" sollte schon "lese" heißen und nicht "lies" (ich kanns mir so besser merken);)



  • double *T schrieb:

    Vielen Dank für die Mühe, Werner Salomon, leider ist das Problem so noch immer nicht gelöst,
    Fehlermeldung des Compilers:"31 C:\Dokumente(...) cannot convert `std::string' to `char' for argument `2' to `bool lese(T&, char*) [with T = std::string]' "*

    stimmt - das kommt davon, wenn man den geposteten Code vorher nicht selber übersetzt.

    double *T schrieb:

    AAHHH! Jetzt lässt es sich kompilieren 👍 . Stimmt, das mit dem ".c_str()" hätte mir auch auffallen müssen. Danke Konrad Rudolph!

    Ja so isses richtig.

    Konrad Rudolph schrieb:

    Einige Anmerkungen zum Code von Werner:

    Werner Salomon schrieb:

    // Was soll denn folgender Code?
             // if( datei_1 )
             //     return true;
             //return false;
             // Besser:
             return datei_l.good();
    }
    

    Das 'return datei_l.good();' ist schlicht falsch. Korrekt wäre

    return !datei_l.fail();
    

    oder

    return bool( datei_l );
    

    was dasselbe ist und das wiederum ist funktional genau der gleiche Code wie am Anfang. Und ich hätte in meinem Code geschrieben

    return bool( datei_l >> var );
    

    bzw. die Funktion 'lese' würde es so gar nicht geben ... aber das ist eine andere Geschichte.

    Der Unterschied zwischen good() und !fail() liegt im EOF-bit. Ist dies gesetzt, so ist good()==false. Das heißt aber nicht, das ein vorher durchgeführter Leseversuch schiefgegangen ist, sondern zunächst nur, dass das Lesen bei EOF aufgehört hat, was völlig ok sein kann. Wenn z.B. außer dem interessierenden Wert nichts in der Datei steht.

    Konrad Rudolph schrieb:

    Außerdem finde ich by-ref-out-Parameter immer ein wenig mittelmäßig furchtbar. Parameter haben gefälligst Eingabeparameter zu sein, die Ausgabe erledigt der Rückgabwert. Man kann ja ein 'std::pair' zurückgeben.

    .. bin ich gänzlich Deiner Meinung; nur ist es immer schwierig, bei solchem newbie-code das richtige Mass der Antwort zu finden.

    :xmas2: Werner



  • Pff gibt soviele Möglichkeiten (operator void*, !operator!, fail, usw.) ... und

    if(!datei_l.is_open())
    

    kann auch durch

    if (!datei)
    

    ersetz werden ...

    template<class T>
    bool read(std::string const& file_name, T& data)
    {
        std::ifstream file_stream(file_name.c_str());
        return (!file_stream ? false : !!(file_stream >> data));    
    }
    

    Aber das nur für die, die auf nen bissel komischen code stehen 😉



  • (D)Evil_loggedoff schrieb:

    template<class T>
    bool read(std::string const& file_name, T& data)
    {
        std::ifstream file_stream(file_name.c_str());
        return (!file_stream ? false : !!(file_stream >> data));
    }
    

    Aah, dann hättest Du die letzte Zeile auch gleich richtig schreiben können (Achtung, ich benutze 'not' statt '!', ändert aber nix):

    return not (not file_stream or not (file_stream >> data));
    


  • doch ändert was 😉 Du nutzt operator void*, ich operator! 😃



  • (D)Evil schrieb:

    doch ändert was 😉 Du nutzt operator void*, ich operator! 😃

    Nein, ich benutze 'operator not', das ist dasselbe wie 'operator !'. '!' == 'not'.

    So, ich gehe jetzt schlafen.



  • Ah sorry hab übersehen, dass davor noch ein not stand ... sonst wäre der Rückgabewert ja falsch 😉 Okay hast recht ^^


Anmelden zum Antworten