2016-05-18 84 views
0

我有一个文件,我只想输出最后一行到控制台。使用seekg()从文件末尾搜索char C++

这是我的想法,我该怎么做。使用file.seekg(0, ios::end)将自己置于文件的末尾。

然后,我可以创建一个递减变量int decrement = -1;和使用while循环

while (joke.peek() != '\n') 
{ 
    decrement--; 

} 

,并得到了首发位置我的最后一行(从最终倒退)。

认识到这一点,joke.seekg(decrement, ios::end);应该设置我到最后一行的开头,并假设我先前声明string input; 我认为

getline(joke, input); 
cout << input << endl; 

将其输出到控制台。

的完整代码

void displayLastLine(ifstream &joke) 
{ 
    string input; 
    int decrement = -1; 


    joke.clear(); 
    joke.seekg(0, ios::end); 


    while (joke.peek() != '\n') 
    { 
     decrement--; 

    } 
    joke.clear(); 

    joke.seekg(decrement, ios::end); 

    getline(joke, input); 
    cout << input << endl; 

} 

的问题是,当我去呼吁文件这种方法,没有任何反应。当我逐步浏览它时,递减只是减去1,远远超出'\n'的位置。举一个文本文件的例子,它会是这个样子:

垃圾

垃圾

跳过此行

这就是我们要找的就行了!

回答

1
joke.seekg(0, ios::end); 

这将文件定位在最后。

while (joke.peek() != '\n') 

那么,这里的问题#1。当你在文件末尾时,peek()总是返回EOF

decrement--; 

你写:

当我通过它一步,减量只是不断减一,

嗯,你是怎么想到的事情发生,因为这是唯一的事情循环呢?您的for循环所做的唯一一件事是从decrement中减去1。所以就是这样。

这是一个常见问题:计算机只做你告诉它做的事情,而不是你想做的事情。

虽然这不是最佳的,但是您的缺失步骤是在您之前peek(),您需要将seek()退回一个字符。然后,peek()向您显示当前光标位置处的字符。然后,再输入seek()一个字符,然后再次检查peek(),依此类推。

但这仍然不足以满足您的需求。大多数文本文件以换行符结尾。换句话说,换行符是文件中的最后一个字符。因此,即使您在几乎所有情况下都添加了缺失的seek(),您的代码最终会执行的操作是找到文件中的最后一个字符,即最终的换行符。

我对你的建议是暂时停止编写代码,而是想出一个做你想做什么的逻辑过程,并用简单的语言描述这个过程。然后,discuss your proposed course of action with your rubber duck。只有在你的橡皮鸭认同你的建议才会起作用之后,再将你的简单语言描述翻译成代码。

+0

几乎所有的观点都是有效的。但是,我的确从-1开始,因此我开始用下一个字符开始搜索。 – Podo

+0

在来到SO之前,我还会确保在未来咨询我的橡皮鸭。 – Podo

+0

我必须检查我的眼睛,对不起。我发誓我在代码中看到了'joke.seekg(0,ios :: end);',其中有一个很大的零,而不是-1。而且,-1会将文件指针放在文件中的最后一个字符上,而不是最后一个字符的下一个字符。 –

1

peek不移动文件指针,它读取字符而不提取它。所以,你不断地偷看相同的值(字符)并最终陷入无限循环。

你需要做的是一样的东西:

while (joke.peek() != '\n') 
{ 
    joke.seek(-1, ios::cur); 
} 

这将使输入位置在\n,使用seekg第二超载。

请注意,这不是一个完美的解决方案。你需要检查错误和边界条件,但它解释了你观察到的行为,并给你一些东西来开始修复你的代码。

0

您的循环实际上只是递减“递减”,并没有使用它来进行下一个搜索。

while (joke.peek() != '\n') 

{ 
    joke.seekg(decrement, std::ios::end); 
    decrement--; 
}