要約
入力は世界がプログラムに入ってくる境界であり、世界は仕様を守らない。このレッスンでは、信用せずに読むことを学ぶ。すなわち、std::getline で行全体を読み、それを >> と混ぜたときに現れる空行を避けること。ストリームの状態を問い合わせ、それによって、レッスン 入力・出力・エラー では混同されたままだった三つの状況(無効なデータ、収まらない数、データの終わり)を区別すること。clear と ignore で失敗した読み取りから回復すること。そして、最も安全なやり方として、各データをテキストとして読み、std::from_chars で変換して、変換がテキスト全体を消費した場合にだけそれを受け入れることである。最後に、契約つきの関数 readInt を示す。これはコースの残りの部分で再利用できる。
学習目標
std::getlineで行全体を読み、>>による読み取りの後に続くgetlineがなぜ空行を返すのかを説明し、それをstd::wsで避けることができる。- 読み取りの後に
fail()とeof()でストリームの状態を問い合わせ、それによって無効なデータ、型に収まらない数、入力の終わりを区別することができる。 - 無効な入力から
clearとignoreで回復し、入力が尽きれば終了する読み取りのループを書くことができる。 - テキストとして読んだ数を
std::from_charsで検証し、エラーがないことと文字列全体が消費されることを要求し、検証を契約つきの関数にまとめることができる。
もう一度、境界
レッスン 入力・出力・エラー は std::cin >> n について三つの事実を確立した。読み取りは、数を続けられない最初の文字で、それを消費せずに止まる。一文字も読めなければ、ストリームはエラー状態になり、その後の読み取りはすべて何もしない。そして、if (std::cin) によって何かが失敗したかどうかを知ることができる。レッスン ループ は、条件 while (std::cin >> value) が、入力が尽きた場合にも無効なデータが来た場合にも終了することを付け加えた。しかし、これらの道具では、プログラムは何かがうまくいかなかったことには気づくが、それが何なのかはわからず、あきらめる以外に何もできない。
このレッスンは、ある設計原理、すなわち境界での防御的プログラミングから出発する。入ってくるデータはすべて使う前に検証し、それを検証するプログラムは、訂正の余地がある無効なデータ(もう一度求める、飛ばす、報告する)と、訂正の余地がないデータの終わりとを区別する。そうであれば、必要なものは三つある。データを書かれたとおりに、つまり一行として読むこと。読み取りがなぜ失敗したかを知ること。そして、ストリームに読む能力を取り戻させることである。
コンテンツを読み込んでいます…