file.get()在循环C ++之后返回随机数

时间:2012-04-05 16:22:26

标签: c++ file-io for-loop

我正在研究一个从文本文件到2D数组中读取一系列整数的程序。
该文件包含40行81个数字,它们之间没有空格。

问题在于,当我在循环结束后输出数组时,它会在预期输出之前在array[0][0]array[0][1]中输出2个随机数。我认为它与换行/回车字符有关。循环的第一次迭代运行完美。这是代码:

#include <cstring>
#include <cstdlib>
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
  int array[9][9];

  //Open file:

  fstream ifile;

  ifile.open("numbers.txt", ios::in);
  if (ifile.fail())
    {
      cout << "Could not open numbers.txt" << endl;
      return -1;
    }

   while (!ifile.eof())
    {
      for(int i=0; i<9; i++)
      {   
    for(int j=0; j<9; j++)
    {
       int n = ifile.get();
              if(isdigit(n)) 
            {
                  array[i][j] = n - '0';
        }

          cout<<"array ["<<i<<"]["<<j<<"] is "<<array[i][j]<<endl;
      } 
      } cout<<"This is a test"<<endl;
    }

  return 0;
}

3 个答案:

答案 0 :(得分:2)

我根本不了解外循环的目的。首先,file 永远不会等于eof(),或者...... eof()是什么? 其次,如果你真的写过while ( !file.eof() ),那就可以了 解释一些元素被覆盖的事实。这里将 在最后一个之后可能是一些尾随字符(至少是一个新行) 数字,所以你将再次重新进入循环。

即使您阅读的字符是,您也在递增索引 不是数字。如果数据是9行9位数,那么最终会得到9 grid中尚未初始化的单元格,以及9个字符 一旦完成内部两个,就没有从文件中读取 迭代。因此,您将再次进入外循环,阅读这些内容 字符。其中一些是数字,所以你最终会被覆盖 您已经写过的grid中的单元格 - 这可能是 影响你观察。此外,一旦你到达文件的末尾, file.get()将开始返回EOF - 通常为-1。那是 毫无疑问,为什么'\n''\r'的测试不起作用。

这些只是正确格式化文件的问题。为一个 格式正确的文件,只需使用file >> nchar n;即可 几乎工作; operator>>跳过空格。但是你仍然会进入 最外面的循环第二次,因为file.eof()直到将是不可靠的 输入失败。你说“我必须使用它”,但你的代码不能 除非你改变它,否则必须工作。

就个人而言,我赞成使用大量错误检查的强大解决方案。 ID 使用std::getline(),我会验证每行包含9个 数字。类似的东西:

std::string line;
int i = 0;
while ( i < 9 && std::getline( file, line ) ) {
    if ( line.size() != 9 ) {
        throw FormatError( "wrong line length" );
    }
    for ( int j = 0; j != 9; ++ j ) {
        if ( ! isdigit( static_cast<unsigned char>( line[j] ) ) ) {
            throw FormatError( "illegal character" );
        }
        grid[i][j] = line[i] - '0';
    }
}
if ( i != 9 || std::getline( file, line ) ) {
    throw FormatError( "wrong line count" );
}

使用file.get()并阅读一个字符并不难 在时间,但你仍然想在每次阅读后检查EOF

for ( int i = 0; i != 9; ++ i ) {
    for ( int j = 0; j != 9; ++ j ) {
        int ch = file.get();
        if ( ch == EOF ) {
            throw FormatError( j == 0 
                                ? "line too short" 
                                : "too few lines" );
        }
        if ( !isdigit( ch ) ) {
            throw FormatError( "illegal character" );
        }
        grid[i][j] = ch - '0';
    }
    int ch = file.get();
    if ( ch != '\n' ) {
        throw FormatError( ch == EOF ? "too few lines" : "line too long" );
    }
}
if ( file.get() != EOF ) {
    throw FormatError( "too many lines" );
}

答案 1 :(得分:1)

随机数会显示,因为无论您是否写入j,都会增加grid[i][j]

尝试用以下内容替换内循环:

for(int j=0; j<9; )
{
  int n = file.get();
  if(!file) break;
  if(isdigit(n))
  {
    array[i][j] = n - '0';
    cout<<"array ["<<i<<"]["<<j<<"] is "<<array[i][j]<<endl;
    j++;
  }
  cout<<"grid ["<<i<<"]["<<j<<"] is "<<grid[i][j]<<endl;
} 

答案 2 :(得分:1)

到达文件末尾时未设置

eof,它在读取失败后设置。而上次读取的数据当然是无效的,因为它失败了。您当前的代码使用无效数据...


除此之外,file != eof()是各种错误的。它甚至不应该编译,因为没有::eof()函数,iostream::eof()需要一个对象。 file != EOF可能会编译,但file会转换为bool并提升为int(01),它永远不会等于EOF-1)。你的意思是!file.eof(),但由于上面给出的原因,这也是错误的。