【问题标题】:Searching for char from end of file using seekg() c++使用 seekg() c++ 从文件末尾搜索字符
【发布时间】:2016-05-18 01:02:09
【问题描述】:

我有一个文件,我只想将最后一行输出到控制台。

这是我对如何做的想法。使用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' 的位置。举一个文本文件的例子,它看起来像这样:

垃圾

垃圾

跳过这一行

这是我们正在寻找的线路!

【问题讨论】:

    标签: c++ file seekg


    【解决方案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。只有在您的橡皮鸭同意您的建议可行之后,然后将您的简单语言描述翻译成代码。

    【讨论】:

    • 您的几乎所有积分都是有效的。但是,我确实从 -1 开始搜索,因此从 NEXT 到最后一个字符开始搜索。
    • 在来SO之前,我也会确保在未来咨询我的橡皮鸭。
    • 我必须检查一下我的眼睛,抱歉。我发誓我在代码中看到了joke.seekg(0, ios::end);,里面有一个大的零,而不是-1。而且,-1 会将文件指针放在文件中的最后一个字符上,而不是最后一个字符的下一个。
    • @JeffreyDilley 以防万一。千万不要把它当作侮辱。这是具有 10 年以上实践经验的开发人员使用的良好做法。
    • 我已经工作了 25 年。前几天我不得不换掉我的橡皮鸭。可怜的东西已经破烂了。
    【解决方案2】:

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

    你需要做的是:

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

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

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

    【讨论】:

      【解决方案3】:

      您的循环实际上只是递减“递减”,而不是使用它进行下一次搜索。

      while (joke.peek() != '\n')
      
      {
          joke.seekg(decrement, std::ios::end);
          decrement--;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-01
        • 2015-10-10
        • 1970-01-01
        • 2012-06-16
        • 2011-10-19
        • 2019-01-10
        相关资源
        最近更新 更多