简体   繁体   English

使用seekg()c ++从文件末尾搜索char

[英]Searching for char from end of file using seekg() c++

I have a file and I want to only output the last line to the console. 我有一个文件,我只想将最后一行输出到控制台。

Here's my thoughts on how I would do it. 这是我对如何操作的想法。 Use file.seekg(0, ios::end) to put myself at the end of file. 使用file.seekg(0, ios::end)将自己放在文件末尾。

Then, I could create a decrement variable int decrement = -1; 然后,我可以创建一个减量变量int decrement = -1; and use a while loop 并使用while循环

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

 }

and get the starting position for my final line (going backwards from the end). 并获得我最后一行的起始位置(从末尾开始倒退)。

Knowing this, joke.seekg(decrement, ios::end); 知道这一点, joke.seekg(decrement, ios::end); should set me to the beginning of the final line, and assuming I previously declared string input; 应该将我设置为最后一行的开头,并假设我之前声明了string input; I would think that 我认为

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

would output it to the console. 会将其输出到控制台。

Full code 完整代码

 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;

}

The problem is, when I go to call this method for the file, nothing happens. 问题是,当我为文件调用此方法时,什么也没发生。 When I step through it, the decrement just keeps on subtracting one, far beyond where a '\\n' would be. 当我逐步执行时,减量只会继续减一,远远超过'\\n'所在的位置。 To give an example of a text file, it would look something like this: 举一个文本文件的例子,它看起来像这样:

junk 垃圾

garbage 垃圾

skip this line 跳过这一行

This is the line that we're looking for! 这是我们正在寻找的线!

peek does not move the file pointer, it reads the character without extracting it. peek不会移动文件指针,它会读取字符而不将其提取。 So, you are constantly peeking the same value (character) and ending up in an infinite loop. 因此,您一直在偷看相同的值(字符)并最终陷入无限循环。

What would you need to do is something like: 您需要执行以下操作:

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

That would put the input position at the \\n , using the 2nd overload of seekg . 这将使用seekg的第二个重载将输入位置置于\\n

Please note that this is not a perfect solution. 请注意,这不是一个完美的解决方案。 You need to check for errors and boundary conditions, but it explains your observed behaviour and gives you something to start fixing your code. 您需要检查错误和边界条件,但这可以解释您观察到的行为,并为您提供一些开始修复代码的方法。

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

This positions the file at the end. 这会将文件放置在末尾。

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

Well, here's problem #1. 好吧,这是问题1。 When you're at the end of the file, peek() always returns EOF . 在文件末尾时, peek()始终返回EOF

    decrement--;

You write: 你写:

When I step through it, the decrement just keeps on subtracting one, 当我逐步执行时,减量会一直减一,

Well, what did you expect to happen, since that's the only thing that the loop does? 那么,您期望发生什么,因为那是循环唯一要做的事情? The only thing your for loop does is subtract 1 from decrement . for循环的唯一作用是从decrement减去1。 So that's what happens. 就是这样。

This a common problem: a computer does only what you tell it to do, instead of what you want it to do. 这是一个常见的问题:计算机只执行您要执行的操作,而不执行您要执行的操作。

Although this is not optimal, your missing step is that before you peek() , you need to seek() back by one character. 尽管这不是最佳选择,但您缺少的步骤是在peek()之前,您需要向后搜索一个字符seek() Then, peek() shows you the character at the current cursor position. 然后, peek()向您显示当前光标位置的字符。 Then, seek() back by one more character, and check peek() again, and so on. 然后,将seek()返回一个字符,然后再次检查peek() ,依此类推。

But that still will not be sufficient for you. 但这还不足以满足您的需求。 Most text files end with a newline character. 大多数文本文件以换行符结尾。 That is, a newline is the last character in the file. 也就是说,换行符是文件中的最后一个字符。 So, even if you add back the missing seek() , in nearly all cases, what your code will end up doing is finding the last character in the file, the final newline character. 因此,即使在几乎所有情况下都添加了丢失的seek() ,您的代码最终要做的就是找到文件中的最后一个字符,最后一个换行符。

My recommendation for you is to stop writing code for a moment, and, instead, come up with a logical process for doing what you want to do, and describe this process in plain words. 我对您的建议是暂时停止编写代码,而是想出一个逻辑过程来做您想做的事情,并用简单的文字来描述这个过程。 Then, discuss your proposed course of action with your rubber duck . 然后, 与橡皮鸭讨论您提议的行动方案 Only after your rubber duck agrees that what you propose will work, then translate your plain language description into code. 只有在橡皮鸭同意您的建议会起作用之后,然后将您的简单语言描述转换为代码。

Your loop is actually only decrementing "decrement" and not using it to make the next search. 您的循环实际上只是减少“减少”,而不使用它进行下一个搜索。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM