get()(从C++中的文件读取)的不寻常的行为

问题描述:

// 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"; 
    } 



    } 

所以,我写这个程序打印文本文件的最后10行。然而,它仅打印最后5个,由于某种原因,每次遇到实际的'\ n'时,下一个get()也会导致\ n导致错误的输出。这里是我的输入文件:get()(从C++中的文件读取)的不寻常的行为

Hello 
Trello 
Capello 
Morsello 
Odello 
Othello 
HelloTrello 
sdasd 
qerrttt 
mkoilll 
qwertyfe 

我使用Windows记事本,这是我的输出:

HelloTrello 
sdasd 
qerrttt 
mkoilll 
qwertyfe 

我无法弄清楚为什么发生这种情况,请帮助。

+0

我会给出一个猜测(尽管我不确定)'get'将'\ n'和'\ r'读为'\ n'。在我的电脑上,使用'\ n'作为行结束符,使用g ++编译。 – elyashiv

+0

在文本文件流上的** only **安全查找要么是'0',要么是之前调用'tellg'返回的值,您正在'pos'中搞乱,然后寻找哪一个是技术上未定义的行为。为什么不给'std :: vector <:string>'缓冲n行,循环遍历文件,用'getline'替换旧行,然后转储文件完成时留下的内容? – user657267

如果在文本模式下打开文件,请不要对文件位置使用算术运算。它不会给你正确的结果。

如果在文本模式下打开文件,则1个字符并不总是表示1个字节。以及如何实现文件位置(如果它指向特定的字符或字节)未指定。

在你的情况下,问题是在Windows上换行符号是两个字节长。文本流将其转换为单字节符号'\n',因此您不必担心平台与实际使用的字节序列之间的差异。

因此,您的第一次读取会读取ASCII字符中与'\n'值相同的双字节结束符号的最后一个字节。接下来在两字节结束符号开始处读取土地,并将其正确地转换为'\n'