Hello all,
As part of a homework assignment, we're to take a given buggy calculator and correct the errors. Once that's done, the assignment is to add the sqrt() and pow() functions to said calculator. This is from Stroustrup's Programming, Principles and Practices using C++.
I've been working on the addition of the sqrt() function, but I can't seem to get it working. The current error is error C2665: 'sqrt' : none of the 3 overloads could convert all the argument types, and I haven't been able to figure out how to fix it.
Any tips on how to proceed?
Thanks in advance.
Here's my source code, sorry it's lengthy:
std_lib_facilities.h is here for reference.
/*
hw3pr1.cpp
Upgrade the calculator following p. 250
A calculator program
*/
#include "../../../std_lib_facilities.h"
/* Grammar:
Calculation:
statment
print
quit
calculation statement
Statement:
declaration
expression
Declaration:
"let" name "=" expression
Expression: - Deal with addition and subtraction
Term
Expression "+" Term
Expressiom "-" Term
Term: - Deal with Multiplication, Division, and %
Primary
Term "*" Primary
Term "/" Primary
Term "%" Primary
Primary: - Deal with Numbers and Parentheses
Number
"("Expression")"
"sqrt(" expression ")"
"pow(" expression "," expression ")"
Number:
floating-point-literal
*/
/* Features to Add (Steps 6-11)
6: Predefined name k meaning 1000 - DONE
7: Give the user the ability to use sqrt(x), available through std_lib_facilities
8: Catch attempts of sqrt(-number), print appropriate error message
9: Allow use of pow(double, int) to mean raise the double to the int power. Req. i to be int
10: change declaration keyword from let to #
11: change quit keyword from q to exit, see S.7.8.2 (string for "let")
*/
struct Token { //creating the Token type
char kind;
double value; //Token of what kind and value
string name;
Token(char ch) :kind(ch), value(0) { }
Token(char ch, double val) :kind(ch), value(val) { }
Token(char ch, string n) :kind(ch), name(n) { } //error - needed to add possibility of Token(char,string)
};
class Token_stream {
bool full;
Token buffer;
public:
Token_stream() :full(0), buffer(0) { }
Token get();
void unget(Token t) { buffer=t; full=true; }
void ignore(char);
};
const char let = 'L';
const char quit = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char squarert = 's';
Token Token_stream::get()
{
if (full) { full=false; return buffer; }
char ch;
cin >> ch;
switch (ch) {
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.unget();
double val;
cin >> val;
return Token(number,val);
}
default:
if (isalpha(ch)) {
string s;
s += ch;
while(cin.get(ch) && (isalpha(ch) || isdigit(ch))) s+=ch;
cin.unget();
if (s == "let") return Token(let);
if (s == "quit") return Token(quit); //was Token(name), now typing "quit" will exit the program
if (s == "sqrt(") return Token(squarert);
return Token(name,s);
}
error("Bad token");
}
}
void Token_stream::ignore(char c)
{
if (full && c==buffer.kind) {
full = false;
return;
}
full = false;
char ch;
while (cin>>ch)
if (ch==c) return;
}
struct Variable {
string name;
double value;
bool var;
Variable(string n, double v, bool va=true) :name(n), value(v), var(va) { }
};
vector<Variable> names;
double get_value(string s)
{
for (int i = 0; i<names.size(); ++i)
if (names[i].name == s) return names[i].value;
error("get: undefined name ",s);
}
void set_value(string s, double d)
{
for (int i = 0; i<names.size(); ++i)
if (names[i].name == s) {
names[i].value = d;
return;
}
error("set: undefined name ",s);
}
bool is_declared(string s)
{
for (int i = 0; i<names.size(); ++i)
if (names[i].name == s) return true;
return false;
}
double define_name(string s, double val, bool var=true)
// add (s,val,var) to names
{
if (is_declared(s)) error(s," declared twice");
names.push_back(Variable(s,val,var));
return val;
}
Token_stream ts;
double expression();
double primary()
{
Token t = ts.get();
switch (t.kind) {
case '(':
{ double d = expression();
t = ts.get();
if (t.kind != ')') error("')' expected");
return d; //Error - case ( didn't return anything, so using parentheses led to default
}
case '-':
return - primary();
case squarert:
{ //Attempting to add sqrt function...
t = ts.get();
if (t.kind != number) error("Number expected");
double d = sqrt(t);
return d;
}
case number: //returns value if the case is a number, better than using "magic constants"
return t.value;
case name:
return get_value(t.name);
default:
error("primary expected");
}
}
double term()
{
double left = primary();
while(true) {
Token t = ts.get();
switch(t.kind) {
case '*':
left *= primary();
break;
case '/':
{ double d = primary();
if (d == 0) error("divide by zero");
left /= d;
break;
}
default:
ts.unget(t);
return left;
}
}
}
double expression()
{
double left = term();
while(true) {
Token t = ts.get();
switch(t.kind) {
case '+':
left += term();
break;
case '-':
left -= term();
break;
default:
ts.unget(t);
return left;
}
}
}
double declaration()
{
Token t = ts.get();
if (t.kind != 'a') error ("name expected in declaration");
string name = t.name;
if (is_declared(name)) error(name, " declared twice");
Token t2 = ts.get();
if (t2.kind != '=') error("= missing in declaration of " ,name);
double d = expression();
names.push_back(Variable(name,d));
return d;
}
double statement()
{
Token t = ts.get();
switch(t.kind) {
case let:
return declaration();
default:
ts.unget(t);
return expression();
}
}
void clean_up_mess()
{
ts.ignore(print);
}
const string prompt = "> ";
const string result = "= ";
void calculate()
{
while(true) try {
cout << prompt; //Display symbol for input
Token t = ts.get();
while (t.kind == print) t=ts.get(); //Discard prints from stream
if (t.kind == quit) return; //End the program
ts.unget(t);
cout << result << statement() << endl; //enables the calculator to loop
}
catch(runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
}
int main()
try {
//Predefined names: Pi, E, and k
define_name("pi",3.1415926535);
define_name("e",2.7182818284);
define_name("k",1000);
cout << "Welcome to the Calculator, please enter your expression at the >\nFinish your expression with a semicolon, ;\n"; //Make slightly more user-friendly
calculate(); //Tell calculate() to run
return 0;
}
catch (exception& e) {
cerr << "exception: " << e.what() << endl;
char c;
while (cin >>c&& c!=';') ;
return 1;
}
catch (...) {
cerr << "exception\n";
char c;
while (cin>>c && c!=';');
return 2;
}