954,496 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Help debug please.

Hi people, I am currently teaching myself C++ with Stroustrup's "Programming, Principles and Practice using C++" and I'm stuck on one of the in-book exercises. It is a chunk of code (~180 lines) of buggy code that, when debugged properly, should create a calculator program. I have reached the limits of my ability and need some more help. There are 8 bugs in total, 5 syntax and 3 logic. I have debugged the syntax errors and now need help with the logic. I think I got one of the logic, so there *should* only be 2 left.

Any help would be very useful. Hopefully the code won't be *too* long.

//
// This is example code from Chapter 6.7 "Trying the second version" of
// "Software - Principles and Practice using C++" by Bjarne Stroustrup
//

/*
	This file is known as calculator02buggy.cpp

	I have inserted 5 errors that should cause this not to compile
	I have inserted 3 logic errors that should cause the program to give wrong results

	First try to find an remove the bugs without looking in the book.
	If that gets tedious, compare the code to that in the book (or posted source code)
	Happy hunting!
*/
#include "stdafx.h"
#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 'q':    // 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':
		{
            double val;
            cin >> val;              // read a floating-point number
            return Token('8',val);   // let '8' represent "a number"
			cin.putback(ch);         // put digit back into the input stream
		}
    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();
        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
{
    while (cin) {
		double val;
        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;
}
//------------------------------------------------------------------------------
Member 785072
Newbie Poster
1 post since Jul 2010
Reputation Points: 10
Solved Threads: 0
 

I actually went a head to try compile your code.

You are using two headers which prevents me from compiling this code, as I don't have them.

Excizted
Posting Whiz
309 posts since Oct 2009
Reputation Points: 94
Solved Threads: 27
 
You are using two headers which prevents me from compiling this code, as I don't have them

You can get the second one from BS's page (it's just a mishmash of #includes, template functions,etc) http://www.stroustrup.com/Programming/std_lib_facilities.h

stdafx is needed for precompiled headers. If the OP doesn't have anything listed in there, you can skip it.

jonsca
Quantitative Phrenologist
Team Colleague
5,621 posts since Sep 2009
Reputation Points: 1,165
Solved Threads: 581
 

>>I think I got one of the logic, so there *should* only be 2 left.

Why two? If you know where the bugs are, you might want to tell us. We're not all clairvoyant here.

Nick Evan
Not a Llama
Moderator
10,112 posts since Oct 2006
Reputation Points: 4,142
Solved Threads: 403
 

If there are three logic bugs in total and one's down, two are left.

Aranarth
Posting Whiz in Training
253 posts since May 2010
Reputation Points: 155
Solved Threads: 47
 

>>If there are three logic bugs in total and one's down, two are left.

Holy shit. That's some amazing math!
Although you obviously think otherwise: I'm not stupid. I was asking where the two remaining errors are.

Nick Evan
Not a Llama
Moderator
10,112 posts since Oct 2006
Reputation Points: 4,142
Solved Threads: 403
 

Nothing indicates that the OP knows where they are, so your question inevitably led me to believe you didn't read the post entirely.

Aranarth
Posting Whiz in Training
253 posts since May 2010
Reputation Points: 155
Solved Threads: 47
 

>> I have debugged the syntax errors and now need help with the logic. I think I got
>> one of the logic, so there *should* only be 2 left.

So, if you've gotten the code to compile, it might be worth testing its functionality to see where it goes wrong.

I.e. run very simple tests such as;

1 + 1;
2 * 2;

and so on.

PS. If you already haven't, then try to configure your compiler to produce as many warnings as possible - that might help too.

mitrmkar
Posting Virtuoso
1,809 posts since Nov 2007
Reputation Points: 1,105
Solved Threads: 395
 

>>If there are three logic bugs in total and one's down, two are left.

Holy shit. That's some amazing math! Although you obviously think otherwise: I'm not stupid. I was asking where the two remaining errors are.

I think he got this code from the book. And the book probably said there was x amounts
of errors in the code. And so, he is left hunting for them. Thats why, he maybe saying there are 2 errors left.

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 
I think he got this code from the book. And the book probably said there was x amounts of errors in the code. And so, he is left hunting for them. Thats why, he maybe saying there are 2 errors left.

You're right, it even says so in the code. But I never read the code because the question wasn't clear, so: whoopsie :S

Anyway: I compiled the code and I can't get one single calculation out of it. There are still quite a few things things wrong with this code. Could you indicate which things you've already changed? Maybe you accidently introduced some new bugs in the code, while removing others? I don't own the book, so I can't check.

Nick Evan
Not a Llama
Moderator
10,112 posts since Oct 2006
Reputation Points: 4,142
Solved Threads: 403
 

I am teaching myself C++ with the very same book and did that very exercise yesterday.

One of the 3 'run-time' errors, as opposed to the 5 'compile-time' errors, is that not all of the possible cases are accounted for. The calculator won't recognize a certain digit as a valid token.

A second 'run-time' error is that the calculator won't perform one of the operations it is supposed to because the character that identifies the case is not the same as the operation that the calculator will actually perform.

I am still looking for the third run-time error. The calculator so far gives correct results for me.

Nathaniel10
Junior Poster
125 posts since Aug 2010
Reputation Points: 44
Solved Threads: 6
 

Hi, I'm working through the book as well, and am stumped with this problem. I have been able to find one logic error, which is, in the function:

Token Token_stream::get()

There are the following two lines,

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '9':

This should be changed to:

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':

to include:

case '8':

If you figure out how to do the rest let me know.

EDIT: Just realised someone else has already mentioned that error. I looked at the OP's code and the first page, so missed the last post.

Lone_wolf986
Newbie Poster
8 posts since Aug 2010
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: