Hi guys,
long time no post, any how I'm just doing some revision and re reading Bjarnes practices and principles, in chapter 6 we make a token calculator, we tokenize so we can implement correct mathematic precedence ie multiplication and division before addition and subtraction,
I understand the gist of the code and have no problems implementing it, it uses recursion and while loops to keep testing for operators,
any how what I don't get is... I noticed that when tracing the program with various number of examples addition will actually be done before multiplication in some cases BUT we will always get the right answer!! that makes me scratch my head a little bit, so lets look at an example
2 + 2 + 2 + 2 * 3 + 2 + 2
this answer will obviously equal 16, and I test the calculator and it gives the correct result, 16.
but when following the program we first let left be equal to term(), we call term which returns a 2 so left equals 2, we then check for an operator and in this case it is a + so we then += left to term again, so yet again we call term(), and yet again term returns 2 so now left(2) is += with 2 which equals 4, but have you noticed addition has been done before multiplication!!! technically aren't we breaking the rules?? since we are adding before we hit the multiplication operation???
the program gives the right answer though every time I test it and no matter how long the expression is, can anybody help explain this and why it's ok to do addition in this case before multiplication??
thanks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
#include <iostream>
using namespace std;
class Token{
public:
char type;
int value;
Token(){
type = '0';
value = 0;
}
Token(int value):value(value){
type = '8';
}
Token(char type,int value): type(type),value(value){}
};
class TokenStream{
public:
Token buffer;
bool bufferFull;
TokenStream()
{
buffer = NULL;
bufferFull = false;
}
Token getToken()
{
if(bufferFull)
{
bufferFull = false;
return buffer;
}
char c;
cin >> c;
switch(c){
case ';':
case '+':
case '-':
case '*':
case '/':
case 'q':
return Token(c,0);
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '10':
{
cin.putback(c);
int val = 0;
cin >> val;
return Token(val);
}
default:
cout << "bad token" << endl;
}
}
void putBack(Token t){
if(bufferFull){
return;
}
buffer = t;
bufferFull = true;
}
};
TokenStream ts;
double primary(){
Token t = ts.getToken();
switch(t.type){
case '8':
return t.value;
case '0':
return t.type;
default:
cout << "error" << endl;
}
}
double term(){
double left = primary();
Token t = ts.getToken();
while(true){
switch(t.type)
{
case '*':
{
left *= primary();
t = ts.getToken();
}
break;
case '/':{
left /= primary();
t = ts.getToken();
}
break;
default:
ts.putBack(t);
return left;
}
}
}
double expression(){
double left = term();
Token t = ts.getToken();
while(true){
switch(t.type)
{
case '+':
{
left += term();
t = ts.getToken();
}
break;
case '-':
{
left -= term();
t = ts.getToken();
}
break;
default:
ts.putBack(t);
return left;
}
}
}
int main()
{
int result = 0;
while(true){
cout << "enter expression" << endl;
Token quit = ts.getToken();
if(quit.type == 'q'){
break;
}
ts.putBack(quit);
result = expression();
}
cout << result << endl;
}
|