C++ Builderで文字列から数値を得るための簡便な関数としてUnicodeString::ToInt()、StrToInt( int )等がある。
便利なのだが使い勝手の問題があって、結局そのままこれらの関数を呼び出しするようなコードを書くと、意図せぬ結果になる場合があるので備忘。
例えば、UnicodeString::ToInt()あるいはStrToInt( int )が受け付けするのは0-9までの数字と接頭語として+および-だけだ。
それ以外の文字列があると例外が発生する。同様にToIntDef系は例外を投げる代わりに標準値を返す。
ただ、人間としては数値の前後に空白があったとしても許容したい。
今回の問題が発覚したのはエクセルから自分のプログラムにコピーアンドペーストで数値を渡すときに空白があって、それをUnicodeString::ToIntDefで変換すると駄目だったことに気づいたため。
コピーアンドペーストを含めて全てのケースに対応することを考えると、もうそのまま使うのは止めようという結論に至った。
もちろん、事前に以下のようにTrimを追加するだけで済むが、呼び出し文字列が複雑になっている場合などを考えると、多分忘れる。
UnicodeString u = L" 123"; // 先頭にスペースがある int n = Trim( u ).ToInt(); // 大丈夫 int m = u.ToInt(); // エラー! 例外が発生する。
だったら、始めから自前の関数を用意してそちらを使うように習慣づけした方が良い。
inline int to_int( const UnicodeString u ) { return Trim( u ).ToInt(); }
何でもTrimを呼び出ししてから変換をかけるので、多少のオーバヘッドはある。
もったいないのなら自前で関数を起こせば良いけど、よほど大量の文字列を制限時間ありで処理するようなタスクでなければ、これでいいと思う。
昔なら絶対に最適化かけてたと思うけど。