こちらのエントリとコメントを読みながら、「ふだんはgood関数を使ってるけど、どんなときに『good』なんだろう?」と調べはじめたら。予想以上に知らないことが多かった。
>>
演算子から始まって、わかったことを少しまとめてみました。
ストリームの状態を示す値について
フラグ | 内容 |
---|---|
eofbit |
ファイルの終端に達した |
failbit |
内部動作が原因で入力操作が失敗した |
badbit |
ストリームバッファの入出力操作が失敗した |
goodbit |
エラーなし(値としてはゼロ) |
入力の失敗ではfailとbadがありうるようです。これは知らなかった。
実際に入力された文字列が、取り出そうとした型(変数の型)の値に変換できない場合はfailになるようです。
ストリームバッファは[http://cplusplus.com/reference/iostream/streambuf/:title=streambuf]
を基底にするクラスで、実際にバイト列としてデータの読み書きをするところ(のはず)。
ストリームの状態を知る方法について
メンバ関数 | 動作 |
---|---|
good |
eofbit、failbit、badbitのすべてが0ならばtrue、そうでなければfalse |
bad |
badbitが1ならばtrue、0ならばfalse |
fail |
failbit、badbitのどちらかあるいは両方が1ならば、両方が0ならばfalse |
operator ! |
failbit、badbitのどちらかあるいは両方が1ならば、両方が0ならばfalse |
operator void* |
failbit、badbitの両方が0ならば非0、どちらかあるいは両方が1ならば0 |
fail
関数と!
演算子は同じ動作です。
void*
演算子は戻り値を真偽値と見たばあい、fail
関数や!
演算子の戻り値を反転した値になっています。
きちんと理解していないまま終端の検出にgood
関数を使ってました。結果的には正しい使い方だったけれど知らずにいたらどこかではまっていそう。
ストリームの入出力が失敗したときに例外を投げる方法について
で。ストリームの入出力が失敗したばあいに例外を投げる方法もありました。
以下、サンプル。
#include <iostream> #include <string> int main(int, char* []) { // failbitが1になったとき例外を投げるように設定 std::cin.exceptions(std::ios::failbit); try { std::string name; int age; std::cin >> name; std::cin >> age; std::cout << "name :" << name << ", age :" << age << "\n"; } catch(const std::ios::failure& e) { std::cerr << "エラーった\n"; } return 0; }
実行結果。例外が投げられないばあい(「sample
」は上記のコードの実行ファイル名です)。
$ ./sample hoge 20 name :hoge, age :20 $
実行結果。例外が投げられた場合。
$ ./sample 20 hoge エラーった