【问题标题】:End of File in C++C ++中的文件结尾
【发布时间】:2009-09-29 19:01:59
【问题描述】:

我有一个 n X 2 矩阵按原样存储在一个文本文件中。我尝试用 C++ 阅读它

nb_try=0;
fin>>c_tmp>>gamma_tmp;
while (!fin.eof( ))      //if not at end of file, continue reading numbers
{
  // store
  cs_bit.push_back(c_tmp);
  gammas_bit.push_back(gamma_tmp);
  nb_try++;

  // read
  fin>>c_tmp;
  assert(!fin.fail( )); // fail at the nb_try=n   
  if(fin.eof( ))break;
  fin>>gamma_tmp; // get first number from the file (priming the input statement)
  assert(!fin.fail( ));    

}

当 nb_try==n 时,第一个断言失败,即 fin.fail( ) 为真,这发生在它尝试读取第一个不存在的数字时。但是为什么 fin.eof( ) 在读完最后一个数字后不是真的呢?这是否意味着只有在读取第一个不存在的数字时它才成为真的? fin.fail( ) 和 fin.eof( ) 是否同时变为 true 是真的吗?

感谢和问候!

【问题讨论】:

    标签: c++ eof


    【解决方案1】:

    这是读取文件的错误方式:

    while (!fin.eof( ))
    {
          // readLine;
          // Do Stuff
    }
    

    标准模式是:

    while(getlineOrValues)
    {
        // Do Stuff
    }
    

    所以快速查看您的代码,我认为将其编写为:

    while(fin>>c_tmp>>gamma_tmp)
    {
        // loop only eneterd if both c_tmp AND gamma_tmp
        // can be retrieved from the file.
    
        cs_bit.push_back(c_tmp);
        gammas_bit.push_back(gamma_tmp);
        nb_try++;   
    } 
    

    问题在于 EOF 仅在您尝试阅读它之后之后才为真。在文件中没有留下要读取的字符与 EOF 为 true 不同。所以你读了最后一行并得到了值,没有什么要读的了,但 EOF 仍然是假的,所以代码重新进入循环。当它尝试读取 c_tmp 时,EOF 被触发并且你的断言变成梨形。

    解决方案是将读取作为while条件。读取的结果是流。但是,当流用于布尔上下文(例如 while 条件)时,它会转换为可以像 bool 一样使用的类型(从技术上讲,它是一个 void*,但这并不重要)。

    【讨论】:

    • 谢谢!究竟什么时候 fin.eof() 变成了真的?在读取文件中的最后一个数字或尝试读取不存在的第一个数字之后? fin.fail() 也有同样的问题?
    • EOF 在您尝试阅读过去 EOF 时为真。读取到文件末尾不会改变状态。因此,当您读取文件末尾不存在的第一个值时,EOF 变为 true。
    • 再次感谢!这澄清了EOF。对于 ifstream::fail(),是否像 eof() 一样在第一次读取文件末尾时变为 true?在我的例子中,这似乎是真的。但我从cplusplus.com/reference/iostream/ios/fail 了解到“如果设置了故障位或坏位,则该函数返回 true。当在输入操作期间发生除到达文件结尾之外的某些错误时,至少设置了这些标志中的一个”。是不是说 fail() 仅仅因为 EOF 发生才成为真的?
    • ifstream::fail() 并不暗示 eof,请参阅此处了解状态标志的说明:cplusplus.com/reference/iostream/ios_base/iostate
    • 如果最后一次操作失败,则设置失败位。在这种情况下,fail 和 eof 将同时变为真。但这并不意味着 fail 和 eof 是一回事。请注意,如果您尝试使用运算符 >> 等将非数字字符串读入 int 变量,则会设置失败。此时失败位为真,但 eof 仍然为假。
    【解决方案2】:

    IIRC,直到您实际尝试读取文件末尾之后,才会设置 eofbit。也就是说,一旦你到达文件的末尾,你必须再读一次才能设置该标志。

    【讨论】:

      【解决方案3】:

      如果文本文件包含这个序列,不带引号,“12345 67890”,那么 #3 将返回 false,但 #4 将返回 true,因为最后一个数字后没有空格:

      int i;
      bool b;
      
      fin >> i;
      
      b = fin.fail();  // 1
      b = fin.eof();   // 2
      
      fin >> i;
      
      b = fin.fail();  // 3
      b = fin.eof();   // 4
      
      fin >> i;
      
      b = fin.fail();  // 5
      b = fin.eof();   // 6
      

      但是,如果序列是“12345 6789”(注意最后一个数字后面的空格),那么#3 和#4 都会返回false,但#5 和#6 会返回true。

      您应该同时检查 eof() 和 fail(),如果两者都是 true,则您没有更多数据。如果 fail() 为真,但 eof() 为假,则文件有问题。

      【讨论】:

      • 我试过第一种情况,“#4会返回true”是不正确的。
      猜你喜欢
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多