5 Replies - 1172 Views - Last Post: 19 November 2012 - 05:53 AM Rate Topic: -----

#1 Swiftyl  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 21-November 11

Help with adding 'multiple brackets' for a calculator program

Posted 17 November 2012 - 03:54 PM

I am working through the Principles and Practise using C++ book, and I working on one of the exercises that asks me to alter this program so that I could use '{' and '}' as well as '()'... For example {2+(4*4)}/3

I have so far tried adding them as a primary along with the parentheses but as expected this didn't work.

Any help as to where I would add these into my program would be greatly appreciated



#include "../../std_lib_facilities.h"

//------------------------------------------------------------------------------

class Token {
public:
    char kind;        // what kind of token
    double value;     // for numbers: a value 
    Token(char ch)    // make a Token from a char
        :kind(ch), value(0) { }    
    Token(char ch, double val)     // make a Token from a char and a double
        :kind(ch), value(val) { }
};

//------------------------------------------------------------------------------

class Token_stream {
public: 
    Token_stream();   // make a Token_stream that reads from cin
    Token get();      // get a Token (get() is defined elsewhere)
    void putback(Token t);    // put a Token back
private:
    bool full;        // is there a Token in the buffer?
    Token buffer;     // here is where we keep a Token put back using putback()
};

//------------------------------------------------------------------------------

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}

//------------------------------------------------------------------------------

// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
    if (full) error("putback() into a full buffer");
    buffer = t;       // copy t to buffer
    full = true;      // buffer is now full
}

//------------------------------------------------------------------------------

Token Token_stream::get()
{
    if (full) {       // do we already have a Token ready?
        // remove token from buffer
        full=false;
        return buffer;
    } 

    char ch;
    cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)

    switch (ch) {
    case '=':    // for "print"
    case 'x':    // for "quit"
	case '(': case ')': case '+': case '-': case '*': case '/':
        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':
        {    
            cin.putback(ch);         // put digit back into the input stream
            double val;
            cin >> val;              // read a floating-point number
            return Token('8',val);   // let '8' represent "a number"
        }
    default:
        error("Bad token");
    }
}

//------------------------------------------------------------------------------

Token_stream ts;        // provides get() and putback() 

//------------------------------------------------------------------------------

double expression();    // declaration so that primary() can call expression()

//------------------------------------------------------------------------------

// deal with numbers and parentheses
double primary()
{
    Token t = ts.get();
    switch (t.kind) {
	case '(':    // handle '(' expression ')'
        {    
            double d = expression();
            t = ts.get();
			if (t.kind != ')') error("')' expected)");
            return d;
        }
    case '8':            // we use '8' to represent a number
        return t.value;  // return the number's value
    default:
        error("primary expected");
    }
}

//------------------------------------------------------------------------------

// deal with *, /, and %
double term()
{
    double left = primary();
    Token t = ts.get();        // get the next token from token stream

    while(true) {
        switch (t.kind) {
        case '*':
            left *= primary();
            t = ts.get();
			break;
        case '/':
            {    
                double d = primary();
                if (d == 0) error("divide by zero");
                left /= d; 
                t = ts.get();
                break;
            }
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;
        }
    }
}

//------------------------------------------------------------------------------

// deal with + and -
double expression()
{
    double left = term();      // read and evaluate a Term
    Token t = ts.get();        // get the next token from token stream

    while(true) {    
        switch(t.kind) {
        case '+':
            left += term();    // evaluate Term and add
            t = ts.get();
            break;
        case '-':
            left -= term();    // evaluate Term and subtract
            t = ts.get();
            break;
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;       // finally: no more + or -: return the answer
        }
    }
}

//------------------------------------------------------------------------------

int main()
try
	{
	cout << "Welcome to our simple calculator.\nPlease enter expressions using floating-point numbers.\n('x' to exit, and '=' to print)\n: ";
	double val = 0;
    while (cin) {
        Token t = ts.get();

        if (t.kind == 'x') break; // 'x' 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;
}

//------------------------------------------------------------------------------


Is This A Good Question/Topic? 0
  • +

Replies To: Help with adding 'multiple brackets' for a calculator program

#2 Xupicor  Icon User is offline

  • Nasal Demon
  • member icon

Reputation: 249
  • View blog
  • Posts: 582
  • Joined: 31-May 11

Re: Help with adding 'multiple brackets' for a calculator program

Posted 17 November 2012 - 04:22 PM

Well I don't want to be rude, but I didn't really care to look into the code that much once I saw a global variable.
Not bad idea with a class representing a stream of tokens, however why don't you inherit your specific Token types as derived from it? Then you could implement operators elsewhere leaving much cleaner code.

And to get parentheses right you may either build a tree of tokens (AST?) or... Well, you could use infix-to-postfix notation algorithm, and then when the tokens are in RPN, just evaluate them using RPN evaluation algorithm. While the second is fun too, I'd probably try AST approach first. (Build a tree, then evaluate it).

Also, your function names are mighty confusing. "primary"? "expression"? Function names should rather be verbs/name an action (run, execute, make_pair, get_primes, sort, connect, etc) or a question, if they return bool (i.e. is_prime, is_valid, has_tail). There are sometimes shortcuts when bool is returned, loke "good", "bad" instead of "is_good", "is_bad" - so "primary" looks like it's a function that returns a state of its parameter, it's either primary (something) or not. That's how common convention would make people think on the first glance. ;)
Was This Post Helpful? 0
  • +
  • -

#3 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1346
  • View blog
  • Posts: 4,638
  • Joined: 19-February 09

Re: Help with adding 'multiple brackets' for a calculator program

Posted 17 November 2012 - 05:15 PM

Most of the code is from someone called Stroustrup.

Did you change the switch in get?

Token_stream::get()

Was This Post Helpful? 0
  • +
  • -

#4 Xupicor  Icon User is offline

  • Nasal Demon
  • member icon

Reputation: 249
  • View blog
  • Posts: 582
  • Joined: 31-May 11

Re: Help with adding 'multiple brackets' for a calculator program

Posted 17 November 2012 - 05:52 PM

Ah, "Programming: Principles and Practice using C++", if I'm not wrong.
Right. Well I don't quite feel like I should change anything in my previous post even if it is Stroustrups. I don't like the Token struct all that much. I'd favour Token as ABC anytime. ;)
Was This Post Helpful? 0
  • +
  • -

#5 Swiftyl  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 21-November 11

Re: Help with adding 'multiple brackets' for a calculator program

Posted 19 November 2012 - 05:21 AM

Yeah the code I used from from "Programming: Principles and Practice using C++", but I'm happy to take your advice and change things if needed. Thanks for the advice on changing the function names, and #define, yeah I did try adding it into there, however when I ran the program as soon as I used '{' the program just exited and IDE gave me several memory errors..

Thanks for repsonses
Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is offline

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,573
  • Joined: 25-December 09

Re: Help with adding 'multiple brackets' for a calculator program

Posted 19 November 2012 - 05:53 AM

Post your current code and post the complete error messages.

Jim
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1