使用 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--;
}
我有一个文件,我只想将最后一行输出到控制台。
以下是我的想法。使用 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--;
}