Lesen aus Textdatei bis EOF letzte Zeile wiederholt [duplicate]

Lesezeit: 4 Minuten

Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
Ashwin Nanjappa

Die folgende C++ Code verwendet a ifstream Objekt, um ganze Zahlen aus einer Textdatei (die eine Zahl pro Zeile hat) zu lesen, bis es trifft EOF. Warum wird die Ganzzahl in der letzten Zeile zweimal gelesen? Wie kann man das beheben?

Code:

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream iFile("input.txt");    // input.txt has integers, one per line

    while (!iFile.eof())
    {
        int x;
        iFile >> x;
        cerr << x << endl;
    }

    return 0;
}

Eingabe.txt:

10  
20  
30

Ausgabe:

10  
20  
30  
30

Notiz: Ich habe den gesamten Fehlerprüfcode übersprungen, um das Code-Snippet klein zu halten. Das obige Verhalten wird unter Windows (Visual C++), Cygwin (gcc) und Linux (gcc) beobachtet.

Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
wilhelmell

Folgen Sie einfach genau der Kette der Ereignisse.

  • Schnapp dir 10
  • Schnapp dir 20
  • Schnapp dir 30
  • Schnapp dir EOF

Sehen Sie sich die vorletzte Iteration an. Sie haben 30 genommen und sind dann weitergefahren, um nach EOF zu suchen. Sie haben EOF nicht erreicht, weil die EOF-Markierung noch nicht gelesen wurde (“binarisch” gesprochen, liegt ihre konzeptionelle Position direkt nach der 30-Zeile). Daher fahren Sie mit der nächsten Iteration fort. x ist immer noch 30 von der vorherigen Iteration. Jetzt lesen Sie aus dem Stream und erhalten EOF. x bleibt 30 und das ios::eofbit wird ausgelöst. Sie geben an stderr x aus (was 30 ist, genau wie in der vorherigen Iteration). Als nächstes prüfen Sie die Schleifenbedingung auf EOF, und dieses Mal sind Sie aus der Schleife heraus.

Versuche dies:

while (true) {
    int x;
    iFile >> x;
    if( iFile.eof() ) break;
    cerr << x << endl;
}

Übrigens gibt es einen weiteren Fehler in Ihrem Code. Haben Sie jemals versucht, es auf einer leeren Datei auszuführen? Das Verhalten, das Sie erhalten, hat genau den gleichen Grund.

  • Verwenden Sie ‘while (iFile >> x)’. Dies liest die Ganzzahl und gibt den Stream zurück. Wenn ein Stream als Bool-Wert verwendet wird, prüft es, ob der Stream gültig ist. Gültig bedeutet, dass eof() und bad() beide falsch sind. siehe stackoverflow.com/questions/21647/…

    – Martin York

    23. September 2008 um 7:48 Uhr

  • Gleicher Geist wie oben Kommentar: statt while(true)scheint es besser zu schreiben while(file.good())

    – PHF

    13. April 2012 um 15:14 Uhr

  • Wenn Sie nicht sicher sind, wie Sie die Datei bis zum Fehler oder Dateiende lesen sollen, lesen Sie diesen Artikel (sehr schöne Erklärung) gehrcke.de/2011/06/…

    – sfelber

    8. Oktober 2015 um 6:49 Uhr

Ich mag dieses Beispiel, das vorerst die Prüfung weglässt, die Sie in den While-Block einfügen könnten:

ifstream iFile("input.txt");        // input.txt has integers, one per line
int x;

while (iFile >> x) 
{
    cerr << x << endl;
}

Ich bin mir nicht sicher, wie sicher es ist …

  • Was ist, wenn 0 ein gültiger Wert ist, wie x==0?

    – harryngh

    4. Juli 2014 um 11:21 Uhr

  • @harryngh Wenn ich das richtig verstehe, iFile >> x gibt den Stream selbst zurück, nicht x. Der Stream wird dann implizit konvertiert in booldie auf EOF testet.

    – Waschen

    2. Mai 2015 um 3:22 Uhr

Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
wilhelmell

Dazu gibt es einen alternativen Ansatz:

#include <iterator>
#include <algorithm>

// ...

    copy(istream_iterator<int>(iFile), istream_iterator<int>(),
         ostream_iterator<int>(cerr, "\n"));

Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
Solostaran14

Ohne zu viele Änderungen des ursprünglichen Codes könnte es werden:

while (!iFile.eof())
{  
    int x;
    iFile >> x;
    if (!iFile.eof()) break;
    cerr << x << endl;
}

aber ich bevorzuge im Allgemeinen die beiden anderen Lösungen oben.

Das EOF-Muster benötigt einen primären Lesevorgang, um den EOF-Prüfprozess zu „booten“. Bedenken Sie, dass die leere Datei ihren EOF zunächst nicht bis zum ersten Lesen gesetzt hat. Der primäre Lesevorgang fängt in diesem Fall den EOF ab und überspringt die Schleife ordnungsgemäß vollständig.

Was Sie hier beachten müssen, ist, dass Sie das EOF erst beim ersten Versuch erhalten, die verfügbaren Daten der Datei zu lesen. Das Lesen der genauen Datenmenge wird das EOF nicht kennzeichnen.

Ich sollte darauf hinweisen, dass Ihr angegebener Code gedruckt worden wäre, wenn die Datei leer gewesen wäre, da der EOF verhindert hätte, dass ein Wert beim Eintritt in die Schleife auf x gesetzt wird.

  • 0

Fügen Sie also einen Prime-Read hinzu und verschieben Sie den Read der Schleife an das Ende:

int x;

iFile >> x; // prime read here
while (!iFile.eof()) {
    cerr << x << endl;
    iFile >> x;
}

1647113411 494 Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
Benutzer1384482

int x;
ifile >> x

while (!iFile.eof())
{  
    cerr << x << endl;        
    iFile >> x;      
}

1647113412 229 Lesen aus Textdatei bis EOF letzte Zeile wiederholt duplicate
Raff

Am Ende der letzten Zeile haben Sie ein Zeilenumbruchzeichen, das vom >>-Operator nicht gelesen wird und kein Dateiende ist. Bitte machen Sie ein Experiment und löschen Sie die neue Zeile (das letzte Zeichen in der Datei) – Sie erhalten keine Duplizierung. Um einen flexiblen Code zu haben und unerwünschte Effekte zu vermeiden, wenden Sie einfach eine beliebige Lösung an, die von anderen Benutzern gegeben wurde.

995010cookie-checkLesen aus Textdatei bis EOF letzte Zeile wiederholt [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy