【问题标题】:Can't get ios::beg to go back to the beginning of the file无法让 ios::beg 回到文件开头
【发布时间】:2013-04-05 07:21:45
【问题描述】:

似乎总是应该没问题的事情对我造成问题。我不明白。 :/

所以我试图确保我了解如何操作文本文件。我有两个文件,“infile.txt”和“outfile.txt”。 “infile.txt”里面有六个数字,没有别的。这是我用来操作文件的代码。

#include<fstream>
using std::ifstream;
using std::ofstream;
using std::fstream;
using std::endl;
using std::ios;

int main()
{
ifstream inStream;
ofstream outStream;//create streams

inStream.open("infile.txt", ios::in | ios::out);
outStream.open("outfile.txt");//attach files

int first, second, third;
inStream >> first >> second >> third;
outStream << "The sum of the first 3 nums is " << (first+second+third) << endl;
//make two operations on the 6 numbers
inStream >> first >> second >> third;
outStream << "The sum of the second 3 nums is " << (first+second+third) << endl;

inStream.seekg(0); //4 different ways to force the program to go back to the beginning of the file
//2. inStream.seekg(0, ios::beg);
//3. inStream.seekg(0, inStream.beg);
//4. inStream.close(); inStream.open("infile.txt");
//I have tried all four of these lines and only #4 works. 
//There has got to be a more natural option than just 
//closing and reopening the file. Right?

inStream >> first >> second >> third;
outStream << "And again, the sum of the first 3 nums is " << (first+second+third) << endl;

inStream.close();
outStream.close();
return 0;
}

也许我不太了解流的工作原理,但我看到一些消息来源说 seekg(0) 应该将索引移回文件的开头。相反,这就是我从中得到的。

前3个数字之和为8

后3个数字之和为14

同样,前 3 个数字的总和是 14

它回来了,但几乎不像我希望的那样。知道为什么会这样吗?为什么我的前 3 次尝试都失败了?

【问题讨论】:

  • 什么是infile.txt?具体来说,数字是多少?
  • @Tushar 更重要的是,除了数字之外,它的内容是什么。必须有更多,因为您需要空格来分隔数字。如果文件以'\n' 结尾(如果它是文本文件,则应该这样),那么除了他使用的第一种方法外,其他所有方法都受到标准的保证(第一种方法也可以在实践中使用)。
  • 他使用的编译器/库也很重要。 C++11 对seekg 的定义与 C++03 不同。
  • infile.txt: 1\n 2\n 5\n 4\n 1\n 9 使用 MS Visual C++ 2010

标签: c++ text file-io


【解决方案1】:

正如 Bo Persson 所说,可能是因为您的输入 遇到文件结尾;它不应该,因为在 C++ 中,文本 文件被定义为由'\n' 终止,但实际上 说起来,如果你在 Windows 下工作,有很多方法 生成文件将省略这个最后的'\n'——尽管它 是正式要求的,实际考虑将意味着 即使最终的'\n' 是 失踪。而且我想不出任何其他原因 seekg's 不起作用。 inStream.seekg( 0 ) 当然是 未定义的行为,但在实践中,它几乎可以工作 到处。 inStream.seekg( 0, ios::beg ) 保证 工作 if inStream.good(),恕我直言,比 第一种形式。 (seekg 的单参数形式通常是 仅与 tellg 的结果一起用作参数。) 当然,它只有在实际输入源支持的情况下才有效 寻求:如果您从键盘阅读或 一个管道(但大概"infile.txt" 两者都不是)。

一般情况下,您应该在每个之后检查inStream 的状态 阅读,在使用结果之前。但如果唯一的问题是 文件不以'\n' 结尾,可能是状态 最终阅读后会好的 (!fail()),即使你已经 遇到文件结尾。在这种情况下,您需要clear() 无论如何。

请注意,上述 cmets 适用于 C++-03 和先例。 C++11 改变了单参数形式的规范 seekg,并要求它重置 eofbit 之前任何东西 别的。 (为什么这种变化只适用于单参数形式 seekg,而不是两个参数形式?监督?)

【讨论】:

  • 太完美了。我忘了包括一个尾随的 '\n',但 MSVC++ 认为这不值得警告。此外, inStream.clear() 也有效。谢谢大家的提示。
  • @anthony Windows 世界中'\n' 的问题在于,对于 CRLF 是分隔符还是终止符似乎没有任何一致意见。 VC++ 库将其视为终止符,但大多数其他程序将其视为分隔符。 (如果它在逻辑上是一个分隔符,filebuf 应该在到达文件末尾时自动生成一个'\n',并且对于您输出的最终'\n' 应该不输出任何内容。当然,仅在文本文件中。实际上,唯一要做的就是期待最终的'\n' 丢失;它发生(即使在 Unix 下)。
【解决方案2】:

第二个输入到达流的文件结尾。该状态一直存在,直到您调用 inStream.clear() 来清除其状态(除了查找之外)。

使用符合 C++11 的编译器,选项 4 也应该像关闭和重新打开一样工作,现在将清除以前的状态。较旧的编译器可能不会这样做。

【讨论】:

  • 在 c++11 中,seekg 清除 eofbit。不过,可能还设置了其他错误标志。
  • 实际上,尚不清楚他是否已到达文件末尾。如果文件中六个数字后面有空格,他就没有。 (从逻辑上讲,由于它是一个文本文件,因此在最后一个数字之后应该至少有一个'\n'。)
  • @jrok 只有一个参数形式会重置eofbit。但是,如果使用整数常量调用,则一种参数形式是未定义的行为。如果输入文件确实包含 6 个数字,eofbit 是唯一可能的问题。
【解决方案3】:

试试:

inStream.seekg(0, ios_base::beg);

【讨论】:

  • 实际上,我从未尝试过。这和 (0, ios::beg) 有什么区别?
猜你喜欢
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多