2012-04-05 4 views
0

私は、テキストファイルから一連のintを2次元配列に読み込むプログラムを開発中です。
ファイルには、空白を含まない81行の40行が含まれています。ループの後の乱数を返すfile.get()C++

問題は、ループが終了した後に配列を書き出すと、予想される出力の前にarray[0][0]array[0][1]に2つの乱数が出力されているということです。私はそれが改行文字/改行文字と関係していると思います。ループの最初の反復は完全に実行されます。ここでは、コードは次のとおりです。あなたは関係なく、あなたがgrid[i][j]に書き込むかどうかのjをインクリメントするので

#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; 
} 
+0

あなたの入力ファイルはどのように見えますか? –

+0

1) 'file.get()'が成功するかどうかを調べることはありません。 2)「n」が数字でなくても「j」をインクリメントし、3)**あなたが持っているエラーを示す短い完全なプログラムを提供してください。 http://sscce.org/を参照してください。 –

+0

@ KornelKisielewiczそれはそれらの間にスペースを持たない81個の数字からなる40行のファイルです – adohertyd

答えて

1

ランダムな数字が表示されます。

であなたの内側のループを交換してみてください:

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; 
} 
+0

それは私が働いているプログラムを含んでいた価値があるもののためにRob – adohertyd

+0

それは多額の価値があった。私は私の答えを編集しました。今すぐ正しい解決策を提供します。 –

1

eofは、ファイルの最後に到達したときに、読み取りが失敗した後、それはセットの設定ではありません。その最後の読み込みからのデータは、もちろん失敗したため無効です。あなたの現在のコードはfile != eof()が間違ったのすべての種類で、無効なデータ...その向こう


を使用しています。 ::eof()関数がないのでコンパイルすべきではなく、iostream::eof()にはオブジェクトが必要です。 file != EOFがコンパイルされる可能性がありますが、fileはboolに変換され、intに昇格されます(0または1)。EOF-1)になることはありません。あなたが意味していたのは!file.eof()でしたが、それは上記の理由で間違っています。

+0

あなたの声明は当然のことです。しかし、バグは彼の苦情を説明していません。すなわち、 'array [0] [0]'と 'array [0] [1]'の2つの乱数です。 –

+0

@Rob:確かに、彼は 'eof()'をチェックする前に 'file.get()'を何度も呼びます。 –

+0

@Rob数字を消費するよりも速く索引を進めるので、外側のループを2回取って、前の数字のいくつかを上書きしてしまいます。 –

2

私は外側ループの目的を全く理解していません。まず、file は決してeof()と等しくないでしょうか。eof()とは何ですか? 第2に、実際にwhile (!file.eof())と書かれている場合、これは が要素のいくつかが上書きされるという事実を説明することができます。 は、最後の 桁の後にいくつかの末尾の文字(少なくとも新しい行)がある可能性があるので、ループを再度入力します。

あなたが読む文字が でない場合でも、インデックスを増やしています。データが9桁の9行である場合、初期化されていないgridの9 セルで終了し、 を完了すると の9文字がファイルから読み込まれます反復。したがって、外側のループに再び入り、 の文字を読み込みます。いくつかは数字になりますので、 のセルをgridに上書きすると、—と書いてあります。これはおそらくあなたが観察している の効果です。また、ファイルの末尾に達すると、 file.get()は、EOF —(通常は-1)を返します。確かに'\n''\r'のテストがうまくいかなかった理由は、 です。

これらは正しくフォーマットされたファイルの問題です。 正しくフォーマットされたファイルの場合は、を使用し、char 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()を使用して、一度に で1つの文字を読むにはあまりにも難しいことではないだろうが、あなたはまだ読ん各後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"); 
} 
関連する問題