周回遅れ。すでに第9回の参考問題が出題されているという状況で第8回の参考問題を解くという。
以下、コード。コードの全体はGitHubに格納しています。
#include <iostream> #include <sstream> #include <string> static const std::string NIBBLES[] = { "0000", "1000", "0100", "1100", "0010", "1010", "0110", "1110", "0001", "1001", "0101", "1101", "0011", "1011", "0111", "1111" }; static const std::string HEXES = "0123456789abcdef"; std::string solve(const std::string& input) { std::string bits; for(std::string::const_iterator i = input.begin(); i != input.end(); ++i) { bits += NIBBLES[HEXES.find(*i)]; } std::string::size_type pos = 0; std::string result; for(;;) { if (bits.size() <= pos) { pos = std::string::npos; break; } else if(bits.substr(pos, 3) == "000" ) { result += 't'; pos += 3; } else if(bits.substr(pos, 4) == "0010" ) { result += 's'; pos += 4; } else if(bits.substr(pos, 4) == "0011" ) { result += 'n'; pos += 4; } else if(bits.substr(pos, 4) == "0100" ) { result += 'i'; pos += 4; } else if(bits.substr(pos, 5) == "01010" ) { result += 'd'; pos += 5; } else if(bits.substr(pos, 7) == "0101101") { result += 'c'; pos += 7; } else if(bits.substr(pos, 6) == "010111" ) { result += 'l'; pos += 6; } else if(bits.substr(pos, 4) == "0110" ) { result += 'o'; pos += 4; } else if(bits.substr(pos, 4) == "0111" ) { result += 'a'; pos += 4; } else if(bits.substr(pos, 2) == "10" ) { result += 'e'; pos += 2; } else if(bits.substr(pos, 4) == "1100" ) { result += 'r'; pos += 4; } else if(bits.substr(pos, 4) == "1101" ) { result += 'h'; pos += 4; } else if(bits.substr(pos, 3) == "111" ) { pos += 3; break; } else { pos = std::string::npos; break; } } if(pos != std::string::npos) { std::ostringstream output; output << result << ":" << pos; return output.str(); } else { return "*invalid*"; } } // テストコード略
攻めと 守りーを くりかえーし
「どう書く」はとても楽しいのですが(出題されている鍋谷さんに感謝)、ハコニワ的なところがあって、枠をはみ出す心配がないのでアイディアをガシガシとプログラミングを進めてしまう、という側面があります。それ自体は悪いわけではないのですが、プログラミングではほとんどのばあいは耐性のあるコードを書かなければなりません。
たとえば。今回こういうコードを書きました。
bits += NIBBLES[HEXES.find(*i)];
今回の「どう書く」のルール上はこれで問題ありませんが、find
関数はstd::string::npos
を返す可能性があります。引数にstd::string::npos
があたえられたばあいのstd::string::operator []
の動作は未定義なので、この参考問題以外の場所でこのコードが使われたら原因不明のバグになりかねません。
個人的には、いまのところ仕事でコードを書く機会は少なくもっぱら読むばかり。ですが、コードを読んでいると耐性=守りを考えなかったコードが原因のバグによく遭遇します。
「どう書く」は攻めるプログラミングの訓練に最適だと思います。でも「どう書く」で攻めをおぼえたら、今度は守りをおぼえないとならない。もちろん「どう書く」がよくないというわけではありません。「どう書く」でお膳立てされた環境でプログラミングするだけで満足しちゃだめだってことです。自戒を込めて。
いつか読むはずっと読まない:ジョブチェンジ
なんで急にそんなことを言い出したかというと。現在「体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践」で勉強中なためでした。なんで急に勉強しているかというと。それについては、またいずれ。
体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
- 作者: 徳丸浩
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2011/03/01
- メディア: 単行本
- 購入: 119人 クリック: 4,283回
- この商品を含むブログ (146件) を見る