あなたが説明したよりも簡単です。最初の 2 つの手順は問題ありません (ただし、残りのアドバイスに従えば、2 番目の手順は必要ありません)。次に、抽出を試みる必要がありますが、抽出をループまたはif
ステートメントの条件として使用します。たとえば、ファイルがすべて同じ形式の一連の行 (またはその他の区切られたシーケンス) としてフォーマットされている場合、次のようにすることができます。
std::string line;
while (std::getline(i, line)) {
// Parse line
}
ループの本体は、行抽出が機能する場合にのみ実行されます。もちろん、ループ内の行の有効性を確認する必要があります。
ストリームで特定の一連の抽出またはその他の操作を行う場合は、次のif
ような条件に配置できます。
if (i >> some_string &&
i.get() == '-' &&
i >> some_int) {
// Use some_string and some_int
}
この最初の抽出が失敗した場合、 のi.ignore()
短絡評価により は実行されません&&
。ステートメントの本文は、if
両方の抽出が成功した場合にのみ実行されます。2 つの抽出が一緒にある場合は、もちろんそれらを連鎖させることができます。
if (i >> some_string >> some_int) {
// Use some_string and some_int
}
最初の抽出が失敗した場合、チェーンの 2 番目の抽出は行われません。抽出が失敗すると、ストリームは後続のすべての抽出も自動的に失敗する状態になります。
このため、ストリーム操作を条件の外に配置して、ストリームif
の状態を確認することも問題ありません。
i >> some_string >> some_int;
if (i) {
// Use some_string and some_int
}
どちらの方法でも、ストリームに関する特定の問題をチェックする必要はありません。ストリームをチェックしてeof()
も、必ずしも次の読み取りが失敗するわけではありません。一般的なケースは、人々が次の誤った抽出ループを使用する場合です。
// DO NOT DO THIS
while (!i.eof()) {
std::getline(i, line)
// Do something with line
}
ほとんどのテキスト ファイルは、テキスト エディタが隠している余分な改行で終わります。テキスト ファイルから行を読み取っている場合、最後の反復では、読み取るファイルがまだあるため、まだファイルの終わりに達していません\n
。そのため、ループが続き、存在しない次の行を抽出しようとして失敗します。多くの場合、これは「ファイルの最後の行を 2 回読む」と見なされます。