到达文件末尾后如何读取文件开头?
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(感谢他的帮助和他的代码段)
如果有比这更好更简单的方法,请告诉我。
让我的文件包含:(文件 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-1profile.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(感谢他的帮助和他的代码段)
如果有比这更好更简单的方法,请告诉我。