Answered! /* This file is known as calculator02buggy.cpp I have inserted 5 errors that should cause this not to compile…

217 CHAPTER 6 REVIEW Drill This drill involves a series of modifications of a buggy program to turn it from something useless into something reasonably 1. Take the calculator from the file calculator02buggy.cpp. Get it to compile. You need to find and fix a few bugs. Those bugs are not in the text in the book. Find the three logic errors deviously inserted in calculator02buggy .cpp and remove them so that the calculator produces correct results. 2. Change the character used as the exit command from q to x. 3. Change the character used as the print command from to 4. Add a greeting line in main0: Welcome to our simple calculator. Please enter expressions using floating-point numbers. 5. Improve that greeting by mentioning which operators are available and how to print and exit.c++

/*
        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 "../std_lib_facilities.h"

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

lass 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 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':
        {    
            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();
        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) {
        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;
}

Headerfile

/*
        simple "Programming: Principles and Practice using C++" course header to
        be used for the first few weeks.
        It provides the most common standard headers (in the global namespace)
        and minimal exception/error support.

        Students: please don't try to understand the details of headers just yet.
        All will be explained. This header is primarily used so that you don't have
        to understand every concept all at once.

        Revised April 25, 2010: simple_error() added
*/

#ifndef H112
#define H112 201004L

#include<iostream>
#include<fstream>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<list>
#include<vector>
#include<algorithm>
#include<stdexcept>

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

#ifdef _MSC_VER
#include <hash_map>
using stdext::hash_map;
#else
#include <ext/hash_map>
using __gnu_cxx::hash_map;

namespace __gnu_cxx {

    template<> struct hash<std::string>
    {
        size_t operator()(const std::string& s) const
        {
            return hash<char*>()(s.c_str());
        }
    };

} // of namespace __gnu_cxx
#endif

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

#define unordered_map hash_map

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

typedef long Unicode;

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

using namespace std;

template<class T> string to_string(const T& t)
{
        ostringstream os;
        os << t;
        return os.str();
}

struct Range_error : out_of_range {     // enhanced vector range error reporting
        int index;
        Range_error(int i) :out_of_range("Range error: "+to_string(i)), index(i) { }
};


// trivially range-checked vector (no iterator checking):
template< class T> struct Vector : public std::vector<T> {
        typedef typename std::vector<T>::size_type size_type;

        Vector() { }
        explicit Vector(size_type n) :std::vector<T>(n) {}
        Vector(size_type n, const T& v) :std::vector<T>(n,v) {}
        template <class I>
        Vector(I first, I last) :std::vector<T>(first,last) {}

        T& operator[](unsigned int i) // rather than return at(i);
        {
                if (i<0||this->size()<=i) throw Range_error(i);
                return std::vector<T>::operator[](i);
        }
        const T& operator[](unsigned int i) const
        {
                if (i<0||this->size()<=i) throw Range_error(i);
                return std::vector<T>::operator[](i);
        }
};

// disgusting macro hack to get a range checked vector:
#define vector Vector

// trivially range-checked string (no iterator checking):
struct String : std::string {
        
        String() { }
        String(const char* p) :std::string(p) {}
        String(const string& s) :std::string(s) {}
        template<class S> String(S s) :std::string(s) {}
        String(int sz, char val) :std::string(sz,val) {}
        template<class Iter> String(Iter p1, Iter p2) : std::string(p1,p2) { }

        char& operator[](unsigned int i) // rather than return at(i);
        {
                if (i<0||size()<=i) throw Range_error(i);
                return std::string::operator[](i);
        }

        const char& operator[](unsigned int i) const
        {
                if (i<0||size()<=i) throw Range_error(i);
                return std::string::operator[](i);
        }
};

#ifndef _MSC_VER
namespace __gnu_cxx {

    template<> struct hash<String>
    {
        size_t operator()(const String& s) const
        {
            return hash<std::string>()(s);
        }
    };

} // of namespace __gnu_cxx
#endif


struct Exit : runtime_error {
        Exit(): runtime_error("Exit") {}
};

// error() simply disguises throws:
inline void error(const string& s)
{
        throw runtime_error(s);
}

inline void error(const string& s, const string& s2)
{
        error(s+s2);
}

inline void error(const string& s, int i)
{
        ostringstream os;
        os << s <<": " << i;
        error(os.str());
}

#if _MSC_VER<1500
        // disgusting macro hack to get a range checked string:
        #define string String
        // MS C++ 9.0 have a built-in assert for string range check
        // and uses "std::string" in several places so that macro substitution fails
#endif

template<class T> char* as_bytes(T& i)        // needed for binary I/O
{
        void* addr = &i;    // get the address of the first byte
                                                // of memory used to store the object
        return static_cast<char*>(addr); // treat that memory as bytes
}


inline void keep_window_open()
{
        cin.clear();
        cout << "Please enter a character to exitn";
        char ch;
        cin >> ch;
        return;
}

inline void keep_window_open(string s)
{
        if (s=="") return;
        cin.clear();
        cin.ignore(120,'n');
        for (;;) {
                cout << "Please enter " << s << " to exitn";
                string ss;
                while (cin >> ss && ss!=s)
                        cout << "Please enter " << s << " to exitn";
                return;
        }
}



// error function to be used (only) until error() is introduced in Chapter 5:
inline void simple_error(string s)      // write ``error: s�� and exit program
{
        cerr << "error: " << s << 'n';
        keep_window_open();             // for some Windows environments
        exit(1);
}

// make std::min() and std::max() accessible:
#undef min
#undef max

#include<iomanip>
inline ios_base& general(ios_base& b)   // to augment fixed and scientific
{
        b.setf(ios_base::fmtflags(0),ios_base::floatfield);
        return b;
}

// run-time checked narrowing cast (type conversion):
template<class R, class A> R narrow_cast(const A& a)
{
        R r = R(a);
        if (A(r)!=a) error(string("info loss"));
        return r;
}


inline int randint(int max) { return rand()%max; }

inline int randint(int min, int max) { return randint(max-min)+min; }

inline double sqrt(int x) { return sqrt(double(x)); }   // to match C++0x

#endif

Expert Answer

 main.cpp

// ERROR.at_least_for_me #include “../std_lib_facilities.h”
#include “std_lib_facilities.h”

//——————————————————————————

// ERROR.1.syntax lass Token {
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
}

//——————————————————————————

// ERROR.2.syntax Token get()
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’:
// ERROR.3.logic case ‘5’: case ‘6’: case ‘7’: case ‘9’:
case ‘5’: case ‘6’: case ‘7’: case’8′: 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();
// ERROR.4.syntax if (t.kind != ‘)’) error(“‘)’ expected);
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();
// ERROR.5.logic no break;
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()
{
// ERROR.6.syntax double left = term(;      // read and evaluate a Term
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 ‘-‘:
// ERROR.7.logic left += term();    // evaluate Term and subtract
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.n”
<< “Please enter expressions using floating-point numbers.n”
<< “(Currently +, -, *, /, and () are supported.)n”
<< “Evaluate the expression with = at the end. Enter x to quit.n”;

// ERROR.8.syntax No val variable declared
double val = 0;
while (cin) {
Token t = ts.get();

if (t.kind == ‘x’) 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;
}

//——————————————————————————

std_lib_facilities.h

#ifndef H112
#define H112 251113L

#include<iostream>
#include<iomanip>
#include<fstream>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<list>
#include <forward_list>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include <array>
#include <regex>
#include<random>
#include<stdexcept>

typedef long Unicode;

//——————————————————————————

using namespace std;

template<class T> string to_string(const T& t)
{
ostringstream os;
os << t;
return os.str();
}

struct Range_error : out_of_range {   // enhanced vector range error reporting
int index;
Range_error(int i) :out_of_range(“Range error: “+to_string(i)), index(i) { }
};

// trivially range-checked vector (no iterator checking):
template< class T> struct Vector : public std::vector<T> {
using size_type = typename std::vector<T>::size_type;

#ifdef _MSC_VER
// microsoft doesn’t yet support C++11 inheriting constructors
Vector() { }
explicit Vector(size_type n) :std::vector<T>(n) {}
Vector(size_type n, const T& v) :std::vector<T>(n,v) {}
template <class I>
Vector(I first, I last) : std::vector<T>(first, last) {}
Vector(initializer_list<T> list) : std::vector<T>(list) {}
#else
using std::vector<T>::vector;   // inheriting constructor
#endif

T& operator[](unsigned int i) // rather than return at(i);
{
if (i<0||this->size()<=i) throw Range_error(i);
return std::vector<T>::operator[](i);
}
const T& operator[](unsigned int i) const
{
if (i<0||this->size()<=i) throw Range_error(i);
return std::vector<T>::operator[](i);
}
};

// disgusting macro hack to get a range checked vector:
#define vector Vector

// trivially range-checked string (no iterator checking):
struct String : std::string {
using size_type = std::string::size_type;
//   using string::string;

char& operator[](unsigned int i) // rather than return at(i);
{
if (i<0||size()<=i) throw Range_error(i);
return std::string::operator[](i);
}

const char& operator[](unsigned int i) const
{
if (i<0||size()<=i) throw Range_error(i);
return std::string::operator[](i);
}
};

namespace std {

template<> struct hash<String>
{
size_t operator()(const String& s) const
{
return hash<std::string>()(s);
}
};

} // of namespace std

struct Exit : runtime_error {
Exit(): runtime_error(“Exit”) {}
};

// error() simply disguises throws:
inline void error(const string& s)
{
throw runtime_error(s);
}

inline void error(const string& s, const string& s2)
{
error(s+s2);
}

inline void error(const string& s, int i)
{
ostringstream os;
os << s <<“: ” << i;
error(os.str());
}

template<class T> char* as_bytes(T& i)   // needed for binary I/O
{
void* addr = &i;   // get the address of the first byte
// of memory used to store the object
return static_cast<char*>(addr); // treat that memory as bytes
}

inline void keep_window_open()
{
cin.clear();
cout << “Please enter a character to exitn”;
char ch;
cin >> ch;
return;
}

inline void keep_window_open(string s)
{
if (s==””) return;
cin.clear();
cin.ignore(120,’n’);
for (;;) {
cout << “Please enter ” << s << ” to exitn”;
string ss;
while (cin >> ss && ss!=s)
cout << “Please enter ” << s << ” to exitn”;
return;
}
}

// error function to be used (only) until error() is introduced in Chapter 5:
inline void simple_error(string s)   // write “error: s and exit program
{
cerr << “error: ” << s << ‘n’;
keep_window_open();       // for some Windows environments
exit(1);
}

// make std::min() and std::max() accessible on systems with antisocial macros:
#undef min
#undef max

// run-time checked narrowing cast (type conversion). See ???.
template<class R, class A> R narrow_cast(const A& a)
{
R r = R(a);
if (A(r)!=a) error(string(“info loss”));
return r;
}

// random number generators. See 24.7.

inline int randint(int min, int max) { static default_random_engine ran; return uniform_int_distribution<>{min, max}(ran); }

inline int randint(int max) { return randint(0, max); }

//inline double sqrt(int x) { return sqrt(double(x)); }   // to match C++0x

// container algorithms. See 21.9.

template<typename C>
using Value_type = typename C::value_type;

template<typename C>
using Iterator = typename C::iterator;

template<typename C>
// requires Container<C>()
void sort(C& c)
{
std::sort(c.begin(), c.end());
}

template<typename C, typename Pred>
// requires Container<C>() && Binary_Predicate<Value_type<C>>()
void sort(C& c, Pred p)
{
std::sort(c.begin(), c.end(), p);
}

template<typename C, typename Val>
// requires Container<C>() && Equality_comparable<C,Val>()
Iterator<C> find(C& c, Val v)
{
return std::find(c.begin(), c.end(), v);
}

template<typename C, typename Pred>
// requires Container<C>() && Predicate<Pred,Value_type<C>>()
Iterator<C> find_if(C& c, Pred p)
{
return std::find_if(c.begin(), c.end(), p);
}

#endif //H112

Still stressed from student homework?
Get quality assistance from academic writers!