到达文件末尾后如何读取文件开头?

How to read beginning of a file after reaching its end?

让我的文件包含:(文件 name:PROFILE.txt)

1 2 3 4 5`

我使用下面的代码读取并获取数据

#include <iostream>
#include <fstream>
using namespace std;
fstream profile;
int n;
int main()
    {
        profile.open("PROFILE.txt",ios::app|ios::in|ios::out); // file name is PROFILE.txt
        long start = profile.tellg(); //marks the point of beginning of the file
        a:
        profile>>n;
        long p = profile.tellg(); //marks the current point of the file cursor
        cout<<n<<" "<<p<<endl;
        if(n==5)profile.seekg(start); // or if(p==-1)profile.seekg(start);
        goto a;
        return 0;
    }

输出为:

1 1
2 3
3 5
4 7
5 -1
5 -1 
5 -1
5 -1
..
...
.... //so on

但是,预期输出(或我想要的输出):

1 1
2 3
3 5
4 7
5 9
1 1
2 3
3 5
4 7
5 9
1 1
2 3
3 5
4 7
5 9
.
..
... //so on

问题: 问题是在它到达文件末尾之后!它无法转到文件的开头!并且不遵守 seekg();!但是假设如果它没有到达终点,它应该可以正常工作!

我的错误是什么以及如何解决!代码应该是什么?

请注意:我是c++初学者!所以请尝试用简单的C++程序代码回答我,请尝试一步步回答我!

希望你能理解我的程序和我的问题!

PICTURE of my CODE,OUTPUT,FILE

After Serge Ballesta code fix

请注意以下代码和输出来自 CODE:BLOCKS(最新版本)运行 in Windows 10(64 位) PC (其他信息: i7 处理器, RAM: 16GB,GPU: 4GB)

我用 if (n == 5) ... 测试时无法重现。我什至无法想象你的系统是如何给你那个结果的!

这是我的系统上发生的事情:

  • 读取数字 1 到 4 并在数字后立即在文件中定位
  • 读取第 5 个位置并位于第 9 个位置 紧接在文件结尾之前
  • 由于到目前为止没有检测到错误,因此执行 seekg 并倒带文件

所以我得到(就像@user3286661 那样)1 1 2 3 3 5 4 7 5 9 1 1 2 3 ...(为简洁起见省略了新行)。按照标准,那是正常输出。

但是如果我使用 if (p == -1) ... 我(几乎)得到了你的输出,因为现在发生了以下情况

  • 读取第 1 到 5 个数字,并定位到文件末尾之前的第 9 个位置
  • 下一次读取到达文件末尾。从那一刻起,每次访问 profile 都会出错,因为我们现在已经过了文件末尾
  • p = profile.tellg()returns-1
  • profile.seekg(0)因为文件结束错误而没有执行
  • profile >> n 不会改变 n 的值,它保持在 5

所以我得到(按照标准规定):1 1 2 3 3 5 4 7 5 9 5 -1 5 -1 ...(仍省略换行符)

如何修复:只需清除错误条件:

if (p == -1) {
    profile.clear();
    profile.seekg(0);
}

但是这种编程调用下面的语句:

  • 你使用 goto,而 while 循环会好得多。 goto 不应该用于循环,只能用于非常特殊的用例,因为它不会使结构明显
  • 您永远不会在任何操作后测试流的状态。这是你问题的真正原因。如果您这样做了,那么很明显 profile 流在 seekg 之后仍处于 eof 模式并且必须清除不良条件

固定码:

    #include <iostream>
    #include <fstream>
    using namespace std;
    fstream profile;
    int n;
int long count_numbers ( int long num) //to count no of digits stored or entered in an int
 {
   int count =0;
   while (num !=0)
    {
      count++;
      num/=10;
    }
   return count;
 }

int main()
        {
            profile.open("PROFILE.txt",ios::app|ios::in|ios::out);
            a:
            long past= profile.tellg(); 
            profile>>n;
            long p= profile.tellg();
           if (p == -1) //thanks to Serge Ballesta
            {
                        profile.clear();
                        profile.seekg(0);
                   p=past+count_numbers(n)+1; // +1 to add space
            }
                cout<<n<<" "<<p<<endl;
            goto a;
            return 0;
        }

程序输出:

特别感谢 Serge Ballesta(感谢他的帮助和他的代码段)

如果有比这更好更简单的方法,请告诉我。