簡體   English   中英

file.get() 循環后返回隨機數 C++

[英]file.get() returning random numbers after a loop C++

我正在開發一個程序,該程序將文本文件中的一系列整數讀取到二維數組中。
該文件包含 40 行,每行 81 個數字,它們之間沒有空格。

問題是當我在循環完成后計算數組時,它在預期的 output 之前在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;
}

我根本不明白外循環的目的。 首先, file永遠不會等於eof() ,或者......什么是eof() ,無論如何? 其次,如果您實際上已經編寫while (.file.eof() ) ,這可以解釋某些元素被覆蓋的事實。 在最后一個數字之后可能會有一些尾隨字符(至少是一個新行),因此您將再次重新進入循環。

即使您讀取的字符不是數字,您也會增加索引。 如果數據是 9 行 9 位數字,那么在完成內部兩次迭代后,網格中將有 9 個單元grid尚未初始化,並且還有 9 個字符尚未從文件中讀取。 所以你將再次進入外循環,讀取這些字符。 其中一些將是數字,因此您最終會覆蓋您已經寫入的grid中的單元格——這可能是您觀察到的效果。 此外,一旦到達文件末尾, file.get()將開始返回EOF通常為 -1。 這無疑就是為什么您對'\n''\r'的測試不起作用的原因。

這些只是格式正確的文件的問題。 對於格式正確的文件,只需使用file >> nchar n; 幾乎可以工作; operator>>跳過空格。 但是你仍然會第二次進入最外層的循環,因為file.eof()在輸入失敗之前是不可靠的。 你說“我必須使用這個”,但除非你改變它,否則你的代碼無法工作。

就個人而言,我喜歡強大的解決方案,並進行大量錯誤檢查。 我會使用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" );
}

出現隨機數是因為無論您是否寫入grid[i][j] ,您都會遞增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;
} 

當您到達文件末尾時不會設置eof ,它會在讀取失敗后設置。 最后一次讀取的數據當然是無效的,因為它失敗了。 您當前的代碼使用了無效數據...


除此之外, file != eof()是各種錯誤。 它甚至不應該編譯,因為沒有::eof() function,而iostream::eof()需要一個 object。file file != EOF可能會編譯,但隨后file將被轉換為 bool 並提升為 int(要么01 ),它永遠不會等於EOF-1 )。 您的意思是.file.eof() ,但由於上述原因,這也是錯誤的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM