10.8 User-defined output operators
- 自前の << を作る事自体は実は簡単
- 難しいのは、どう表現するのか?というところ
- 2011/03/05なのか 2011-03-05なのか Mar 5th 2011なのか・・・
- 誰もが納得できる表示と言うのは難しいですね
- しかしそれでもとりあえず作っておくのは役に立ちます。特にデバッグ時や開発初期など
-
- LL言語では classに to_s, repl, __str__などなどそれ相当のものがたいていありますね
- コンソールで直接いじれるのでよけいに重要と思うです
- 後からキレイに清書すれば良いし、それでもダメなら普通にメンバにアクセスして表示するヘルパー作れば良いのだ
- Dateクラスでは (2011,03,05) てな感じに表示している。こういう単なるリスト表示ってのはメンバが少なくて、他に良いのが見つからないときとかによく使います
- 演算子のオーバーロードって要するに対応する関数が呼ばれるだけなんだけど、cout << "hoge" のような二項演算子の場合は (左辺値, 右辺値)という並びで呼び出されます
- operator << ()は返り値として ostream& を返すので、cout << "hoge" << "moge" のようにチェインが可能です.
- (cout << "hoge") << "moge" ---> (ostream = cout) << "moge" .....
10.9 User-defined input operators
- 自前の >> はエラーの処理が結構大変
- Dateの場合はどうなるかって言うと
istream& operator >>(istream& is, Data& dd)
{
int y,m,,d;
char ch1, ch2, ch3, ch4;
is >> ch1 >> y >> ch2 >> m >> ch3 >> d >> ch4;
if (!is) return is;
if (ch1 !='(' || ch2 1= ',' ......)
is.clear(ios_base::failbit);
return is;
}
dd = Date(y, Data::Month(m), d);
return is;
}
-
-
- ・・・・・ぽかーん。。。。。ここまでやるなら sscanf()、、、いや scanf()で良いじゃん。。。
- いやいや、、、
- いやいや、、、
std::istream& operator>>(std::istream& is, const char& c)
{
char ch;
is >> ch;
if (c != ch) {
is.unget();
is.clear(std::ios::failbit);
}
return is;
}
-
- なぜにこーゆーのが標準ライブラリに無いんだろう? だれかおしえて
- 気を取り直して・・・
- これだけでも厄介なのですが(自分で厄介にしているだけな気も)エラーがあった場合は目も当てられません
- 理想的には、使わなかった文字は消費すべきではないんだけど、、、
- 実際には本書のプログラムだといらんところまで捨ててしまう(もろcharに読んでるので・・・)
- まあそうでなくても(2011,3,5} とか最後の文字だけ間違ってる場合、 } を読むまでは進んでしまうので(入力を消費してしまうので)リカバリは非常に困難
- unget()が保証しているのは一文字までのロールバックなので、これはちょっと無理ゲー
- 値がおかしかった場合、Dateのコンストラクタが例外発してくれるはず
- ほんま? monthのエラーには脆弱だと思うケド(実はDateのコードはdayに関しては閏年まで考慮しているが、monthのvalidateは enumに頼っている(コンパイル時情報のみに頼っている))
10.10 A standard input loop
- データ列をリードする場合の入力ループについての考察
- 全行読めると言う前提で書いていたけど良いのか?
- OK。なぜなら読めるところまで読んでみて、そこで終端かどうか確かめれば済むから
- 大抵は各行のフォーマットチェックと、終端部分のチェックは独立してやるのでオKなのです
- で、あらためて istream::exceptions()の話とかで input loopをリファクタリングしていくんだけど、、、
- 終端文字、というのを用意しておくのは便利なことが多いとか。データ構造がネストしてて、内部レベルで止めたい場合とか。。。
-
- 個人的には反対。帯域外データというのは帯域内データと混同しては行けない、というのが僕の考え。ネスト構造は構造をちゃんと追うべき。適当に文字列処理するのはイクナイ
10.11 Reding a structured file
{ year 1990}
{year 1991 {month jun}}
{ year 1992 {month jan ( 1 0 61.5) } {month feb (1 1 64) (2 2 65.2) } }
{year 2000
{ month feb (1 1 68) (2 3 66.66 ) (1 0 67.2)}
{ month dec ( 15 15 -9.2) (15 14 -8.8) (14 0 -2) }
}
- てな感じのファイル。 year が年指定で {} でネストしてて、 month で月指定、 ()の中が実際の値で 日、時間、温度という順のデータ
- ヘンテコ。けどXML全盛の今でもこういうのはあるし、一般に仕事では入力を選べない
- あまりにヒドけりゃフォーマットコンバータ使えとの事。 んーそうしようか(違
10.11.1 In-memory representation
- 上記の表現のためにYear, Month, Readingをつくるんだけど、、、
-
- んーこのへんほんとヒドい。day のvector添字とint表現がずれてたりとか。しかもそのためにdy vectorの確保数が32とか。うーん、美しくな過ぎる。この章だけヒドい過ぎる
- 一応 year, monthは自分の値と下にvectorを持つイメージ
10.11.2 Reading structured values
- Reading(実際の観測データ)はvector要素なしで素直に 日、時間、温度。
- しかし美しくない事に Reading::operator>>()は一文字だけ チェックしてとか・・ 確かにね、このフォーマットの場合 Readingが何個続くかわからないので先読みが必要なのはわかるのですが、別に failbitたてるだけでぇもぉぉぉお・・・
- ugu- やる気がぁ(汚いコードってやる気をそぎますよね・・・)
-
10.11.3 Changing representations
- 月名のテーブルを最初に初期化しましょうね、という話。
- 本文でも書いてますが map使うべきですよね。