Datei in einen vector lesen



  • Hallo zusammen,

    habe hier http://www.c-plusplus.net/forum/p2391664#2391664 etwas gelesen, das ich nicht ganz verstehe. Wäre sehr nett, wenn mir jemand diese zweite Zeile kurz und knackig, aber noch verständlich erklären könnte:

    std::ifstream stream{"Pfad.txt"};
    std::vector<int> numbers{ std::istream_iterator<int>{stream},std::istream_iterator<int>{} };
    

    Anscheinend ist das die Kurzform für

    int x;
    while(stream >> x)
        numbers.push_back(x);
    

    verstehe aber nicht wie und wieso?

    Vielen Dank im Voraus



  • std::vector hat einen Konstruktor, der zwei Iteratoren entgegen nimmt.
    Der macht in etwa folgendes:

    for (; begin != end; ++begin)
      push_back(*begin);
    

    Initialisiert also anhand eines Range.
    std::istream_iterator ist ein spezieller Iterator, der beim Dereferenzieren ein Objekt vom Typen aus dem Templateargument aus dem übergebenen Stream liest. Siehe: http://en.cppreference.com/w/cpp/iterator/istream_iterator
    Man erzeugt nun einen Iterator auf den Anfang der Datei und einen eins hinters Ende (der ohne Argument). Um den Rest kümmert sich der Range-Konstruktor.



  • Hallo,

    Vielen Dank für deine Antwort, Nathan.

    Vorallem das ein Iterator kein Argument hatte, hat mich etwas verwirt. Aber jetzt kapier ichs soweit ich es im Moment kapieren muss 👍

    LG


  • Mod

    Vorallem das ein Iterator kein Argument hatte, hat mich etwas verwirt.

    Das funktioniert folgendermaßen.

    Nathan hat folgende Pseudo-Schleife gezeigt:

    for (; begin != end; ++begin)
      push_back(*begin);
    

    Zwei Dinge fallen auf: Die Schleife bricht ab, sobald der erste gleich dem zweiten Iterator ist, und in jedem Durchgang wird der erste Iterator inkrementiert. Außerdem muss ein Iterator bei mehrfachem Dereferenzieren denselben Wert zurückliefern (was hier allerdings nicht benötigt wird).

    istream_iterator kapselt die oben beschriebenen Eigenschaften wie folgt: Initialisierst du den istream_iterator mit einer Referenz auf einen Stream, so speichert er einen Verweis auf diesen Stream, extrahiert den ersten Wert und speichert ihn in seiner Membervariable.

    Inkrementierst du nun den Iterator, extrahiert er einen neuen Wert aus dem Stream und speichert dessen Wert in seiner Membervariable.

    Dereferenzierst du ihn, gibt er den Wert der Membervariable zurück.
    War das nicht möglich, und der Stream geht in den Fehlerzustand, dann geht der Iterator in den "Leerzustand" und gleicht beim Vergleich dem leeren Iterator - nämlich std::istream_iterator() (also einem, der ohne Konstruktorargumente initialisiert wurde.). Sobald dieser Fall eintritt, bricht Nathans Schleife ab - genau dann, wenn es nichts mehr zu extrahieren gibt.

    Das heißt, sehr grob geschieht folgendes in der Schleife

    for (; begin != end /* während die Extraktionsoperation erfolgreich war */ ; ++begin /* Extrahiere nächsten Wert und speichere ihn */ )
      push_back(*begin); // Füge den gespeicherten Wert des Iterators in den Container ein
    


  • Aah, jau jetzt ergibt alles einen Sinn 💡
    vielen Dank noch für den Zusatz Arcoth

    LG


Anmelden zum Antworten