PPPUC++#8#drill
- 6章には正解の全体コードは載っていないのですが、代わりにこのドリルにてバグだらけコードを修正する、という遊びをすると完成品が手に入るようになってます。
http://www.stroustrup.com/Programming/calculator02buggy.cpp
(みなさんも暇があれば遊んでみてはいかがでしょ?)
方針
- テストコードとして以下の用なのを用意しました。
test_input.txt
1; 2; 3; 1+1*3; 1+1+1+1+1; 8-2; 5/2+9/2; (1+3-2)*4; ( 10 * 83-( 9*(2.3*(11-1)*2/3)*6-3))+4; q
- 結果はこうなるはず。
result_golden.txt
=1 =2 =3 =4 =5 =6 =7 =8 =9 Please enter a character to exit
.PHONY: all clean ALL=calculator02buggy all: $(ALL) $(ALL): $(ALL).cpp test: @echo testing test.dat @./$(ALL) < test_input.txt > result.out @diff result.out result_golden.txt clean: rm -f *.o *~ result.out
と思ったら
- なんぞこの文法エラーの数々、って感じでわざとらしいのが沢山
- コンパイルすら通らん状態でってどうよw
気付いた事
- デバッガ無いとかなり大変。思い知った。
- vimのシンタックスハイライトとか本当に強力。ほとんどの文法エラーはvimに読み込んだ瞬間にハイライトされてしまって演習にならなかったw
- gccのエラーはスゴく親切。たいてい何が間違っているのかがすぐにわかってしまう。
- 現在のobjective-Cほど親切ではないですが・・・
- あっちは本当に「そ、そこまで教えていただけるのであればぜひ直していただきたく・・・」て感じにスゴいものね・・・
ネタばれ系
自分で楽しむ人は見ないでねー。
TYPOはおいといて、まともなエラーは
- case抜け
- break抜け
- +と-の間違い
- ';'を受けた後 そのままドロップスルーなので expression()になってしまう = ';'の直後に 'q'(って普通そうだよねw)がきても読めない
くらいです。あんまりパラノイアックには遊べませんが、まあ腕試しくらいには。
一応のせておきます。
@@ -21,7 +21,7 @@ //------------------------------------------------------------------------------ -lass Token { +class Token { public: char kind; // what kind of token double value; // for numbers: a value @@ -63,7 +63,7 @@ void Token_stream::putback(Token t) //------------------------------------------------------------------------------ -Token get() +Token Token_stream::get() { if (full) { // do we already have a Token ready? // remove token from buffer @@ -81,7 +81,7 @@ Token get() return Token(ch); // let each character represent itself case '.': case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '9': + case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); // put digit back into the input stream double val; @@ -112,7 +112,7 @@ double primary() { double d = expression(); t = ts.get(); - if (t.kind != ')') error("')' expected); + if (t.kind != ')') error("')' expected"); return d; } case '8': // we use '8' to represent a number @@ -135,6 +135,7 @@ double term() case '*': left *= primary(); t = ts.get(); + break; case '/': { double d = primary(); @@ -155,7 +156,7 @@ double term() // deal with + and - double expression() { - double left = term(; // read and evaluate a Term + double left = term(); // read and evaluate a Term Token t = ts.get(); // get the next token from token stream while(true) { @@ -165,7 +166,7 @@ double expression() t = ts.get(); break; case '-': - left += term(); // evaluate Term and subtract + left -= term(); // evaluate Term and subtract t = ts.get(); break; default: @@ -178,29 +179,33 @@ double expression() //------------------------------------------------------------------------------ int main() -try { - while (cin) { - Token t = ts.get(); - - if (t.kind == 'q') break; // 'q' for quit - if (t.kind == ';') // ';' for "print now" - cout << "=" << val << '\n'; - else - ts.putback(t); - val = expression(); + try + { + double val; + while (cin) { + Token t = ts.get(); + + if (t.kind == 'q') break; // 'q' for quit + if (t.kind == ';') // ';' for "print now" + cout << "=" << val << '\n'; + else { + ts.putback(t); + val = expression(); + } + } + keep_window_open(); + } + catch (exception& e) { + cerr << "error: " << e.what() << '\n'; + keep_window_open(); + return 1; + } + catch (...) { + cerr << "Oops: unknown exception!\n"; + keep_window_open(); + return 2; } - keep_window_open(); -} -catch (exception& e) { - cerr << "error: " << e.what() << '\n'; - keep_window_open(); - return 1; -} -catch (...) { - cerr << "Oops: unknown exception!\n"; - keep_window_open(); - return 2; }