2016-08-04 34 views
0
// Print the last n lines of a file i.e implement your own tail command 
#include <iostream> 
#include <fstream> 
#include <string> 
int main() 
{ 
    std::ifstream rd("D:\\BigFile.txt"); 
    int cnt = 0;char c; 
    std::string data; 
    rd.seekg(0,rd.end); 
    int pos=rd.tellg(); 

    while(1) 
    { 

    rd.seekg(--pos,std::ios_base::beg); 

     rd.get(c); 
     if(c=='\n') 
     { 
      cnt++; 
     // std::cout<<pos<<"\t"<<rd.tellg()<<"\n"; 

     } 

     if(cnt==10) 
     break; 

} 
     rd.seekg(pos+1); 
     while(std::getline(rd,data)) 
    { 
     std::cout<<data<<"\n"; 
    } 



    } 

Also schrieb ich dieses Programm, um die letzten 10 Zeilen einer Textdatei zu drucken. Es druckt jedoch nur die letzten 5, aus irgendeinem Grund gibt jedesmal, wenn es ein tatsächliches '\ n' trifft, das nächste get() auch ein \ n, was zu einer inkorrekten Ausgabe führt. Hier ist meine Eingabedatei:Ungewöhnliches Verhalten von get() (Lesen aus einer Datei in C++)

Hello 
Trello 
Capello 
Morsello 
Odello 
Othello 
HelloTrello 
sdasd 
qerrttt 
mkoilll 
qwertyfe 

I Notizblock auf Windows verwenden und das ist meine Ausgabe:

HelloTrello 
sdasd 
qerrttt 
mkoilll 
qwertyfe 

ich kann nicht herausfinden, warum dies geschieht, Bitte helfen.

+0

Ich werde eine Vermutung geben (obwohl ich mir nicht sicher bin), dass "bekommen" sowohl '\ n' und' \ r' als '\ n' liest. Auf meinem Computer funktioniert es gut mit '\ n' für das Ende der Zeile, kompilieren mit g ++. – elyashiv

+0

Die ** einzige ** sichere Suche nach einem Textfilestream ist entweder '0', oder ein Wert, der von einem vorherigen Aufruf von 'tellg 'zurückgegeben wurde, man rumort mit' pos 'und sucht dann nach einem technisch undefinierten Verhalten. Warum nicht einen 'std :: vector ' Puffer für n Zeilen erstellen, durch die Datei gehen, ältere Zeilen durch 'getline' ersetzen, während du gehst, und dann rauslassen, was übrig ist, wenn die Datei fertig ist? – user657267

Antwort

3

Verwenden Sie keine Arithmetik für Dateipositionen, wenn die Datei im Textmodus geöffnet wird. Es wird Ihnen kein korrektes Ergebnis geben.

Wenn die Datei im Textmodus geöffnet wird, bedeutet 1 Zeichen nicht immer 1 Byte. Und wie die Dateiposition implementiert wird (wenn sie auf ein bestimmtes Zeichen oder Byte zeigt) ist nicht spezifiziert.

In Ihrem Fall Problem ist, dass unter Windows ein Newline-Symbol zwei Bytes lang ist. Text Streams konvertiert es in Single-Byte-Symbol '\n', so dass Sie sich keine Gedanken über den Unterschied zwischen Plattformen und tatsächlichen Byte-Sequenzen machen müssen.

Ihr erster Lesevorgang liest das letzte Byte des Zwei-Byte-Endzeilensymbols, das denselben Wert wie '\n' in ASCII hat. Als nächstes lese Länder am Anfang des Zwei-Byte-Endzeilensymbols und der Strom wandelt es korrekt in '\n' um.