使用 seekg() C++ 从文件末尾搜索字符

Searching for char from end of file using seekg() 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;

}

问题是,当我为文件调用这个方法时,没有任何反应。当我单步执行它时,减量只是继续减一,远远超出了 '\n' 的范围。举一个文本文件的例子,它看起来像这样:

垃圾

垃圾

跳过这一行

这就是我们要查找的行!

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

你需要做的是:

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

这会将输入位置放在 \n,使用 seekg 的第二个重载。

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

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

这会将文件定位在末尾。

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

好吧,这是第 1 个问题。当您在文件末尾时,peek() 总是 returns EOF.

    decrement--;

你写:

When I step through it, the decrement just keeps on subtracting one,

那么,您期望发生什么,因为这是循环所做的唯一事情? for 循环所做的唯一一件事就是从 decrement 中减去 1。这就是发生的事情。

这是一个常见问题:计算机只执行您告诉它执行的操作,而不是执行您希望它执行的操作。

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

但这对您来说仍然不够。大多数文本文件以换行符结尾。也就是说,换行符是文件中的最后一个字符。因此,即使您将缺失的 seek() 添加回去,在几乎所有情况下,您的代码最终都会找到文件中的最后一个字符,即最后的换行符。

我对你的建议是暂时停止编写代码,而是想出一个逻辑过程来做你想做的事情,并用通俗易懂的语言描述这个过程。然后,discuss your proposed course of action with your rubber duck。只有在你的橡皮鸭同意你的建议可行之后,然后将你的简单语言描述翻译成代码。

你的循环实际上只是递减 "decrement" 而不是用它来进行下一次搜索。

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

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