2012-03-26 12 views
1

C++でテキストファイルからデータを入力しようとしています。 テキストファイルはその形式である:ファイルを初期状態にリセットする必要はありますか?

4 15 
3 516 
25 52 etc. 

各行には2つの整数を含んでいます。私は十分なメモリをバインドすることができますので、私は、ファイルの行数を知らない、これは私がそれを解決する方法として、ようになってきているものです:

ifstream filein; 
filein.open("text.txt",ios::in); 
int count=0; 

while (!filein.eof()) 
    { 
     count++; 
     filein>>temporary; 
    } 
count=count/2; // This is the number of lines in the text file. 

私の問題は、私は理解できないということです入力ストリームを閉じ、再び開く以外の(私ができ、実際に入力データをファイルのbegginingに)初期状態に

filein

をリセットする方法。それを行うための他の方法はありますか?

+1

あなたは(私の記憶が正しければ)seekgを使用することができるはずです:あなたはのようなものを使用することができ、上記pointクラスを使用して(例えば)ので、データの読み出しが成功したことを確認したいです。あなたはただベクトルを使用して考えましたか? – Corbin

+0

「データを入力する」とは、値をこのファイルに書き戻すことを意味していますが、適切な権限で開いた出力ストリームが必要になります。 – AJG85

+0

@Corbin - 'seekg'は' eofbit'をクリアしません。 –

答えて

5

よりもむしろあなたは私はあなたがすなわち、要求していない質問に答えるつもりです、尋ねた質問に答える:

Q:私ドン場合、私は、ファイルのすべての行を読み込むことができますどのようにそこにはいくつの行があるのか​​知りませんか?

A:std::vector<>を使用してください。

あなたは数字のすべてをで読みたい場合は、関係なく、ペアリングの:

// all code fragments untested. typos are possible 
int i; 
std::vector<int> all_of_the_values; 
while(filein >> i) 
    all_of_the_values.push_back(i); 

あなたは異なるデータ構造に交互に数字を入れて、数字の全てに読み込みたい場合:

int i, j; 
std::vector<int> first_values; 
std::vector<int> second_values; 
while(filein >> i >> j) { 
    first_values.push_back(i); 
    second_values.push_back(j); 

あなたがデータ構造のいくつかの並べ替えに格納、数字のすべてをで読みたい場合:

int i, j; 
struct S {int i; int j;}; 
std::vector<S> values; 
while(filein >> i >> j) { 
    S s = {i, j}; 
    values.push_back(s); 
} 

最後に、あなたがファイルを一度にラインを読みたい場合は、それぞれの行から最初の2つの数値を維持する各ラインの残りの部分を破棄し、それらをユーザー定義のデータ構造を格納:

std::vector<MyClass> v; 
std::string sline; 
while(std::getline(filein, sline)) { 
    std::istringstream isline(sline); 
    int i, j; 
    if(isline >> i >> j) { 
    values.push_back(MyClass(i, j)); 
    } 
} 


脇に:決してループ条件で eof()または good()を使用しないでください。あなたのケースでそうであるように、そうすることはほとんど常にバグのコードを生成します。代わりに、私が上で行ったように、条件で入力関数を呼び出すことを好む。

+0

ベクトルの使用経験はあまりありませんが、配列のサイズを知らなくても、読み込んだ値を渡すことはできますか?これらの配列のメモリを最初にバインドすることはできませんか? –

+0

配列のサイズを最初に知っている値を配列に渡すことはできません。あなたが新しいC++プログラマーであれば、配列**を使わないでください。配列は、高度な使用のみを考慮してください。より安全で使いやすい 'std :: vector'を使い始めましょう。 –

+0

ヒントや助けをありがとうございました。すぐにベクトルを調べます。 –

2

機能は次のとおりです。filein.seekg (0, ios::beg);

ここでは、あなたがそれをこの方法を行う場合にも、ファイルにeofビットをリセットするためにfilein.clear()を使用する必要がありますReference

です。

もちろん、あなたが最終的にやろうとしていることのための最良の方法を望むなら、Robᵩの答えは、はるかに優れています。

+0

しかし、それは 'eofbit'セットを残します。彼が 'seekg'を使っているなら、おそらく' ios :: clear() 'を最初に呼び出すべきです。また、ファイルが空白で終わっていると、あなたのコード(と彼の)は 'count'を1回多くインクリメントします。 –

+0

@Robᵩ:自分の答えを修正しました。 –

+0

@ Rob file filein >> temporary >> wcを呼び出すと気がつきました。余分な白線を読むことに関しては、ファイルを読むのに問題はありません。 –

2

私は@ Rob prettyが正しいアイデアを持っていると思っています。ちょうどすべてのデータを読み取って行の数を数えるだけでなく、std::vectorのようなものを使って、 std::deque)が必要に応じて展開されます。

しかし、典型的な例では、1つの行の2つの数値は互いに関連していて、通常はその関連を直接示す方法で格納します。例えば、彼らはあなたがポイントを読みたい、その場合にはポイントのXとY座標であるかもしれない:

class point { 
    int x, y; 
}; 

std::istream &operator>>(std::istream &is, point &p) { 
    return is >> p.x >> p.y; 
} 

std::ifstream in("myfile.txt"); 

// create the vector from the data in the file: 
std::vector<point> points((std::istream_iterator<point>(in)), 
          std::istream_iterator<point>()); 

少し別のノートで:あなたは、明示的なループを使用したい決定した場合でも、ください。while (!whatever.eof())を使用しないでください。失敗することはほとんどありません。

point p; 
while (infile >> p) 
    points.push_back(p); 
+1

+ 'std :: istream_iterator <>'とカスタム '演算子>>'のデータを読み取るための正しいイディオムを表示するための+1。 –

関連する問題