diff --git a/projects/06/calculator08buggy.cpp b/projects/06/calculator.cpp similarity index 82% rename from projects/06/calculator08buggy.cpp rename to projects/06/calculator.cpp index da4f1e2..c0ad85b 100644 --- a/projects/06/calculator08buggy.cpp +++ b/projects/06/calculator.cpp @@ -1,10 +1,7 @@ -/* - calculator08buggy.cpp - - Helpful comments removed. - - We have inserted 3 bugs that the compiler will catch and 3 that it won't. -*/ +// +// This is example code from Chapter 7.8 "Variables" of +// "Software - Principles and Practice using C++" by Bjarne Stroustrup +// #include @@ -17,6 +14,8 @@ struct Token Token(char ch) : kind{ch}, value{0} {} Token(char ch, double val) : kind{ch}, value{val} {} + + Token(char ch, string id) : kind{ch}, name{id} {} }; class Token_stream @@ -51,6 +50,7 @@ constexpr char let = 'L'; const string prompt = "> "; const string result = "= "; const string declkey = "let"; +const string quitkey = "quit"; Token Token_stream::get() { @@ -72,7 +72,7 @@ Token Token_stream::get() case '*': case '/': case '%': - case ';': + case print: case '=': return Token{ch}; @@ -100,15 +100,18 @@ Token Token_stream::get() string s; s += ch; while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) - s = ch; + s += ch; cin.putback(ch); if (s == declkey) return Token{let}; + if (s == quitkey) + return Token{quit}; + return Token{name, s}; } - error("Bad token"); + error("bad token"); } } @@ -121,10 +124,11 @@ void Token_stream::ignore(char c) } full = false; - char ch; - while (cin >> ch) + for (char ch; cin >> ch;) + { if (ch == c) return; + } } struct Variable @@ -137,22 +141,24 @@ struct Variable vector var_table; -double get_value (string s) +double get_value (const string& s) { - for (int i = 0; i < var_table.size(); ++i) - if (var_table[i].name == s) - return var_table[i].value; + for (const auto& var : var_table) + { + if (var.name == s) + return var.value; + } error("get: undefined name ", s); } -void set_value (string s, double d) +void set_value (const string& s, double d) { - for (int i = 0; i <= var_table.size(); ++i) + for (auto& var : var_table) { - if (var_table[i].name == s) + if (var.name == s) { - var_table[i].value = d; + var.value = d; return; } } @@ -160,16 +166,18 @@ void set_value (string s, double d) error("set: undefined name ", s); } -bool is_declared (string s) +bool is_declared (const string& s) { - for (int i = 0; i < var_table.size(); ++i) - if (var_table[i].name == s) + for (const auto& var : var_table) + { + if (var.name == s) return true; + } return false; } -double define_name (string var, double val) +double define_name (const string& var, double val) { if (is_declared(var)) error(var, " declared twice"); @@ -194,6 +202,7 @@ double primary () t = ts.get(); if (t.kind != ')') error("'(' expected"); + return d; } case '-': @@ -235,6 +244,15 @@ double term () break; } + case '%': + { + double d = primary(); + if (d == 0) + error("'%': divide by zero"); + left = fmod(left, d); + break; + } + default: ts.putback(t); return left; diff --git a/projects/06/test_ans.txt b/projects/06/test_ans.txt new file mode 100644 index 0000000..f002515 --- /dev/null +++ b/projects/06/test_ans.txt @@ -0,0 +1,54 @@ +> = 0 +> = 1 +> = 2 +> = 3 +> = 4 +> = 5 +> = 6 +> = 7 +> = 8 +> = 9 +> = 3 +> = 3 +> = 6 +> = -1 +> = -1 +> = -4 +> = 2 +> = 2 +> = 6 +> = 0.5 +> = 0.5 +> = 0.166667 +> = 7 +> = -5 +> = 1.66667 +> = 0.333333 +> = divide by zero +> = primary expected +> = 3 +> = -3 +> = 3 +> = -3 +> = 3 +> = 10 +> = 21 +> = divide by zero +> = bad token +> = bad token +> = 1 +> = 21 +> = -4.5 +> = 0 +> = 0 +> = 2 +> = 0 +> = 4.2 +> = 3.3 +> = 0.2 +> = 2 +> = 3 +> = 0 +> = 5 +> = 1 +> \ No newline at end of file diff --git a/projects/06/test_in.txt b/projects/06/test_in.txt new file mode 100644 index 0000000..037dc66 --- /dev/null +++ b/projects/06/test_in.txt @@ -0,0 +1,50 @@ +0; 1; 2; 3; 4; 5; 6; 7; 8; 9; + +1 + 2; 1+2; 1 + 2 + 3; +1 - 2; 1-2; 1 - 2 - 3; + +1 * 2; 1*2; 1 * 2 * 3; +1 / 2; 1/2; 1 / 2 / 3; + +1 + 2*3; 1 - 2*3; +1 + 2/3; 1 - 2/3; + +3/0; + +(); +(3); +-(3); ++(3); +(-3); +(+3); +(3+7); +(3*7); + +3 / (3 - 3); + +3 * 4&5; + +93"43-189'3dfrer4734***&340#$%%%8340909909()()*(&)))((( ; + +4 / (2 + 2*1); +1 + 4 * (2 + 3/2*2); + +72 / (10*(9-5) - 7*8); + ++2 - 2; -2 + 2; + +2 % 4; +4 % 2; +4.2 % 8; +3.3 % 6.6; +6.8 % 3.3; + +let x = 2; let q=3; + +x*q - (x * q); + +q + x; + +x/(x + 2*q - q*2); + +quit