Calculator
Feb 5, 2014 at 2:06pm Feb 5, 2014 at 2:06pm UTC
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 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
#include <iostream>
#include <limits>
#include <stdexcept>
using namespace std;
//declaring classes
class token
{
public :
char kind;
double value;
token (char ch)
:kind(ch), value(0) {}
token (char ch, double val)
:kind(ch), value(val) {}
};
class token_stream
{
public :
token_stream();
token token_get();
void putback(token t);
private :
bool full;
token buffer;
};
// class member functions of token_stream
token_stream::token_stream()
:full(false ), buffer(0) {}
void token_stream::putback(token t)
{
if (full==true ) throw runtime_error ("putback into a full buffer" );
buffer = t;
full=true ;
}
token token_stream::token_get()
{
if (full) {
full=false ;
return buffer;
}
char ch;
cin >> ch;
switch (ch) {
case ';' :
case 'q' :
case '(' : case ')' : case '+' : case '-' : case '*' : case '/' : case '{' : case '}' : case '!' :
return token(ch);
case '.' :
case '0' : case '1' : case '2' : case '3' : case '4' :
case '5' : case '6' : case '7' : case '8' : case '9' :
{
cin.putback(ch);
double val;
cin >> val;
return token ('8' ,val);
}
default :
throw runtime_error("bad token" );
}
}
//declaring functions
token_stream ts;
double expression();
double term();
double primary();
int factorial(int number);
//functions
double primary()
{
token t = ts.token_get();
switch (t.kind) {
case '{' :
{
double d = expression();
t = ts.token_get();
if (t.kind != '}' ) throw runtime_error ("']' expected" );
return d;
}
case '(' :
{
double d = expression();
t = ts.token_get();
if (t.kind != ')' ) throw runtime_error("')' expected" );
return d;
}
case '!' :
{
t = ts.token_get();
double d = factorial(t.value);
return d;
}
case '8' :
return t.value;
case 'q' :
cout << "exit" ;
return 0;
default :
throw runtime_error("primary expected" );
}
}
double term()
{
double left = primary();
token t = ts.token_get();
while (true ) {
switch (t.kind) {
case '*' :
left *= primary();
t = ts.token_get();
break ;
case '/' :
{
double d = primary();
if (d==0) throw runtime_error("divide by zero" );
left /=d;
t = ts.token_get();
break ;
}
default :
ts.putback(t);
return left;
}
}
}
double expression()
{
double left = term();
token t = ts.token_get();
while (true ) {
switch (t.kind) {
case '+' :
left+=term();
t = ts.token_get();
break ;
case '-' :
left-=term();
t = ts.token_get();
break ;
default :
ts.putback(t);
return left;
}
}
}
int factorial(int number)
{
int solution = 1;
for (int i=number; i>1; i--) {
solution= solution*i;
}
return solution;
}
int main()
try
{
cout << "A simple calculator able to deal with +,-,*,/. Enter ';' to calculate and 'q' to quit" << '\n' ;
cout << ">" ;
//main loop
while (cin) {
token t = ts.token_get();
if (t.kind == 'q' ) {
cout << "Thanks for using the calculator" << '\n' ;
break ; //'q' for quit
}
if (t.kind == ';' ) // ';' for "print now"
cout << "=" << expression() << '\n' << ">" ;
else {
ts.putback(t);
cout << "=" << expression() << '\n' << ">" ;
}
}
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n' ;
return 1;
}
catch (...) {
cerr << "Unknown exception!\n" ;
return 2;
}
Hello guys,
I'm working on Sir Stroustrups Beginner book. This is, as you can see, a simple calculator.
It is supposed to exit on pressing 'q', which it does, but only if I input 'q' before I do anything else. Afterwards I can't exit the program that way anymore.
From my understanding the following happens (Please correct me if I'm wrong)
- due to line 212, my last token is put back into the stream, thus the program calls "expression()" which calls "term()" which calls "primary()". Now I tried fixing the problem by inserting case "q" into primary, but from my understanding I can not end the program from a function, I can only "return" to main();
How please do I fix this? Feel free to criticize the rest of the code as well (keep in mind, I'm a beginner)
Feb 5, 2014 at 2:22pm Feb 5, 2014 at 2:22pm UTC
The app is stuck in the parser at that point. You need to change line 118, (case 'q' in primary()) to call exit(0)
rather than return 0
.
Feb 5, 2014 at 2:35pm Feb 5, 2014 at 2:35pm UTC
Feb 5, 2014 at 3:45pm Feb 5, 2014 at 3:45pm UTC
Thanks for the answers.
Topic archived. No new replies allowed.