dmpコンバータ2

id:selvaggio:20070306の続き

dmpの質問の返答ー。

exitの代替は、返り値か例外か

一ついえることは、

 返り値はチェックされることを期待してはいけない。

という経験的な事実かね。
printfの返り値をチェックした人は今まで何人いるか、とか考えればね。


逆に例外はスローされればキャッチされるまで正常な処理には戻らないので、
誰かが処理してくれるってことは多分期待できる。


でも例外マンドクサイ('ー`)
取りあえず返り値で対処でOKな気がする。←自堕落系


あと、手続きは返り値がないからエラー値を返せるが、関数は返せない。
これに対して、Cライブラリはerrornoとかいう気持ち悪いグローバル変数をおいて対処したが、これはどう見ても危ない仕様だな。
と言うわけでこれがもし関数だったら素直に例外投げておけばいい気がする。

int全域を返す関数だったとしたら、どうやってもエラーコードを設定できないしな。

初期化構文と代入文の違い

初期化はコンストラクタを使っての文字通り初期化が行われるので、

std::string::string(char*)

が呼ばれる。
代入は代入演算子を使って、データの設定が行われるので、

std::string::operator=(char*)

が呼ばれる。


ゆえに、

  • 初期化→ char[] 引数のコンストラクタが1つ呼ばれるだけ
  • 代入→コンストラクタが("")で呼ばれたあと、char[] による代入が呼ばれる。

という微妙な違いがある。


クラスの実装によってはパフォーマンスがかなり違ったりする。

ライブラリのエラーでorz

C++ライブラリは大半がSTLなので、一つの凡ミスでエラーが数百個出ることも少なくないんだよな。
このライブラリエラーに対処するコツは最初の行だけ見て後は無視することらしい。
でもまぁtemplate系のメッセージは正直わけが分からんことが多いので、しょうがないな。

エラーチェックのタイミング

基本的にはエラーがあったらすぐに処理を中断して復旧処理を行うべきだと思われ。
なのでまぁ直後かな、と。

テーブルを引く

switchの実装も実はテーブル引くのと大して変わらないので、保守性などを考えるとそっちのほうがよさげだす。
しかし、今回はテーブルにするには少々隙間が開いてるような気がするので、std::mapの使用を考えても良いかもしれない。
std::mapかね。

stringではなくてchar[]

一切加工しない、読み出し専用ならば確かにそっちのほうが良いかもしれんね。
今回は当てはまる。

インチキhash

ハッシュマップはSTLには無かった気もするが、前述のstd::mapで代用できなくもない、気がする。
ので、まぁ出来ればライブラリ使おうぜ、と。

ifname/ofname

俺だったら、ファイル名ではなく std::istream/std::ostream を渡すようにする。
(ストリームはmainで開いておく)

ファイル名が指定されていなかったら標準入力から取得、とかが簡単に出来る。

void toUpper(std::istream& ist, std::ostream& ost)
{
  char ch;
  while(!ist.eof()){
    ist >> ch;
    if(islower(ch)) ch += ('A' - 'a');
    ost << ch;
  }
}

これはこんな風に使える

std::ifstream ifs("hoge");
std::ofstream ofs("hage");

toUpper(ifs, ofs);            // ファイルから入力、ファイルへ出力
toUpper(ifs,std::cout);       // ファイルから入力、標準出力へ出力
toUpper(std::cin, ofs);       // 標準入力から入力、ファイルへ出力
toUpper(std::cin, std::cout); // 標準入力から入力、標準出力へ出力

std::stream系とstd::fstream系の継承関係を利用する感じ。