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;
	}

Recommended Answers

All 3 Replies

I think you are going on a wrong way when you debug a program. What you should do are...

1)Compile it and see what the 3 bugs are (from the URL comment on the top), and fix them first. This mean, they are compile errors which are not difficult to fix.
2)Once you are done with 1, you will have to attempt to insert sample values to see how it behaves. The other 3 bugs could be run-time error and/or wrong result. You need to fix these 3 before you can move on.
3)After you are done with all bugs, you should have a clear idea what the program is all about. Now you can attempt to add "addition" first. Do not try "square root" until you are sure that you understand the program.

Because you jump start at 3 right now, you have no idea what program is all about... It is even more difficult to debug your modified program. :(

In theory (before messing with sqrt()) the program does compile and work.
You are correct though, I do need to run through a set of sample values - I will be doing that. Thanks, Taywin.

As for the use of the sqrt() function, this is what I went in and changed:

Line 117:

if (s == "sqrt") return Token(squarert);

and in primary():

case squarert:
	{	//Adding square root function		
		double d = sqrt(expression());
		return d;
	}

I was instructed that I needed to call expression(), since expression returns a double, and using ts.get() wasn't going to - because the Token isn't a double.

what about the pow function? I'm doing this same program. haha I thought initially to set it up the same as the sqrt( ) function, but i believe the "," in between the value and the degree throws off the calculator and i don't know how to handle it. :/

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.