Hello!

I am making a postfix calculator and I want to add in some equation integrity checking. Everything seems to work ( it needs to be done some little improvements, but overall it is working), except when I am checking for the blank spaces the program do not work the way as it should.

I enclosed the snippet of that part of code. Compile it and enter something like 9 * 5 + 2. The result should be 9*5+2, but it is not even near as that.
What could be wrong?

#include <iostream>
#include <string>
#include <sstream>
#include <cctype>

using namespace std;

bool IsOperator(char ch);
bool IsOperand(char ch);
void Check(string & infix, double & result, int & i);
double strToDbl(string const& str);


int main()
{  

	string infix, postfix;
           double result = 0.0;

	for( int i = 1; i <= 2 ; i++ )
	{
		switch(i)
		{
			case 1:
				postfix.erase();
				infix.erase();
				cout << "Enter equation (\"q\" for quit): ";
				cin >> infix;
				cout << endl;
				if (!(infix.compare("q"))) return 0;
				break;
			case 2:
				Check(infix, result, i);
				cout << infix << endl;
				i = 0;
				break;
		}
	}	

	return 0;
}

bool IsOperand(char ch)
{
	if ((ch >= '0') && (ch <= '9') || (ch == '.'))
		return true;
	else
		return false;
}

bool IsOperator(char ch)
{
	if (((ch == '*') || (ch == '/')) ||
		((ch == '+') || (ch == '-')) || (ch == '^'))
		return true;
	else
		return false;
}

void Check(string &infix, double & result, int &st)
{
	short counter = 0;

	for ( int x = 1; x <= 5; x++ )
	{
		switch (x)
		{
		case 1:
                       {
			cout << "Checking if there is any letters in the equation...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( isalpha(infix[i]) )
				{
					infix.erase(i, 1);
					i--;
					counter++;
				}
			}
			if (counter != 0)
			{
				cout << "Error!\nThere were letters in the equation! They were deleted." << endl;
				counter = 0;
			}
			else cout << "Passed!" << endl;
			break;
                        }
		case 2:
                       {
			cout << "Checking if there is any blank space...";
			string temp;
			temp.clear();
			
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( isspace(infix[i]) )
					counter++;
				else
					temp.append(1, infix[i]);	
			}
			
			if (counter != 0)
			{
                                                infix.clear();        
				infix.assign(temp);
				cout << "Error!\nThere were blank space in equation! They were deleted." << endl;
				counter = 0;
			}
			else cout << "Passed!" << endl;
			break;
                         }
		case 3:
                        {
			cout << "Checking if there is any parenthesis misspelling...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( infix[i] == '(' || infix[i] == ')' )
					counter++;
			}
			
			if (counter % 2 != 0)
			{
				cout << "Error!\nThere were error placing parenthesis!" << endl;
				counter = 0;
				st = 0;
			}
			else cout << "Passed!" << endl;
			break;
                        }
		case 4:
                       {
                                    cout << "Checking if there is any operator misspelling...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( IsOperator(infix[i]) && IsOperator(infix[i+1])  )
					counter++;
				else if (IsOperand(infix[i]) && infix[i+1] == '(' || infix[i+1] == ')' )
					counter++;
				else if (IsOperator(infix[infix.size()-1]) || IsOperator(infix[0]) )
					counter++;
			}
			
			if (counter != 0)
			{
				cout << "Error!\nThere were error using operators!" << endl;
				counter = 0;
				st = 0;
			}
			else cout << "Passed!" << endl;
			break;
                        } 
		case 5:
                       {
                         // if there is only a number entered
                         for ( string::size_type i = 0; i < infix.size(); i++ ) 
	                    if ( !IsOperand(infix[i]) )counter++;
			
		        if (counter == 0)
		         {
			   result = strToDbl(infix);
			   st = 0;
		          }
		     }
            }
	}
	cout << endl;
}

double strToDbl(string const& str) 
{
	std::istringstream ss(str);
	double d;
	ss >> d;

	return d;
}

> Just want to remove all the spaces from a string?
>> Use a function like this one:

string trim(const string &s) {
	string t;
	for(unsigned int i=0; i<s.length(); i++)
		if(s[i] != ' ') t+= s[i];
	return t;
}

>> Just put your read expression into a string and pass it to this trim-function and all the spaces will be removed :)

Hehe, I have finally discovered what was causing the problem...I was reading expression with cin command so it ignored everything after space. How that I did not see that before .... heh lol :)

So here is what i have come up with.
I would be glad if someone would comment it, give me some tips of what is bad and needs to be improved/changed etc.

#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <cmath>
#include <cctype>
#include <windows.h>

using namespace std;

void Check(string &, long double &, int &);
bool IsOperand(char);
bool IsOperator(char);
bool TakesPrecedence(char, char);
void Convert(const string &, string &);
double sToDbl(string const&);
void Calculate(const string &, const string &, long double &);
double DoMath(double,double,char);

int main()
{  
	SetConsoleTitle(L"Postfix Calculator.");

	string infix, postfix;
	long double result = 0.0;

	for( int i = 1; i <= 5 ; i++ )
	{
		switch(i)
		{
		case 1:
			postfix.erase();
			infix.erase();
			cout << "Enter equation (\"q\" for quit): ";
			getline(cin, infix);
			cout << endl;
			if (!(infix.compare("q"))) return 0;
			break;
		case 2:
			Check(infix, result, i);
			break;
		case 3:
			Convert(infix, postfix);
			//cout << "Postfix form:" << postfix << endl;
			break;
		case 4:
			Calculate(postfix, infix, result);
			break;
		case 5:
			cout << "\nResult: " << result << endl << endl;
			i = 0;
			break;
		}
	}	

	return 0;
}

void Check(string &infix, long double & result, int &st)
{
	short counter = 0;

	for ( int i = 1; i <= 4; i++ )
	{
		switch (i)
		{
		case 1:
			cout << "Letter/s, Blank/s...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( isalpha(infix[i]) || isspace(infix[i]) )
				{
					infix.erase(i, 1);
					i--;
					counter++;
				}
			}
			if (counter != 0)
			{
				cout << "Error!\nThere were letter/s, blank/s in the equation! They were deleted." << endl;
				counter = 0;
			}
			else cout << "OK!" << endl;
			break;

		case 2:
			cout << "Operator/s...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( IsOperator(infix[i]) && IsOperator(infix[i+1]) )
					counter++;
				else if (IsOperator(infix[infix.size()-1]) || IsOperator(infix[0]))
					counter++;
			}
			if (counter != 0)
			{
				cout << "Error!\nThere were error using operators!" << endl;
				counter = 0;
				st = 0;
			}
			else cout << "OK!" << endl;
			break;

		case 3:
			cout << "Parenthesis...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
				if ( infix[i] == '(' || infix[i] == ')' )
					counter++;

			if (counter % 2 != 0)
			{
				cout << "Error!\nThere were error placing parenthesis!" << endl;
				counter = 0;
				st = 0;
			}
			else cout << "OK!" << endl;
			break;

		case 4:// if there is only number entered, convert it to integer and print it as result
			for ( string::size_type i = 0; i < infix.size(); i++ )
				if ( !IsOperand(infix[i]) )counter++;

			if (counter == 0)
			{
				result = sToDbl(infix);
				st = 4;
			}
		}
	}
	cout << endl;
}

bool IsOperand(char ch)
{
	if ((ch >= '0') && (ch <= '9') || (ch == '.'))
		return true;
	else
		return false;
}

bool IsOperator(char ch)
{
	if (((ch == '*') || (ch == '/')) ||
		((ch == '+') || (ch == '-')) || (ch == '^'))
		return true;
	else
		return false;
}


bool TakesPrecedence(char OperatorA, char OperatorB)
{
	if (OperatorA == '(')
		return false;
	else if (OperatorB == '(')
		return false;
	else if (OperatorB == ')')
		return true;
	else if ((OperatorA == '^') && (OperatorB == '^'))
		return false;
	else if (OperatorA == '^')
		return true;
	else if (OperatorB == '^')
		return false;
	else if ((OperatorA == '*') || (OperatorA == '/'))
		return true;
	else if ((OperatorB == '*') || (OperatorB == '/'))
		return false;
	else
		return true;
}

void Convert(const string & infix, string & postfix)
{
	stack <char> OperatorStack;
	const string BLANK = " ";
	char TopSimbol, Simbol;

	for (string::size_type i = 0; i < infix.length(); i++)
	{
		Simbol = infix[i];
		if (IsOperand(Simbol))
		{
			postfix += BLANK + Simbol;
			while ( IsOperand(infix[i+1]))
			{
				postfix.append(1, infix[i+1]);
				i++;
			}
		}
		else
		{
			while ((!OperatorStack.empty()) &&
				(TakesPrecedence(OperatorStack.top(), Simbol)))
			{
				TopSimbol = OperatorStack.top();
				OperatorStack.pop();
				postfix += BLANK + TopSimbol;
			}

			if ((! OperatorStack.empty()) && (Simbol == ')'))
				OperatorStack.pop();
			else
				OperatorStack.push(Simbol);
		}
	}
	while (!OperatorStack.empty())
	{
		TopSimbol = OperatorStack.top();
		OperatorStack.pop();
		postfix += BLANK + TopSimbol;
	}
}

double sToDbl(string const& str) {

	istringstream ss(str);
	long double d;
	ss >> d;

	return d;
}

void Calculate(const string &postfix, const string &infix, long double &result)
{

	stack <long double> NumberStack;

	for (string::size_type i = 0; i < postfix.length(); i++)
	{
		char ch = postfix[i];
		string number;
		number.clear();

		if (IsOperand(postfix[i]))
		{
			number.append(1, ch);

			while (!isspace(postfix[i+1]))
			{
				number.append(1, postfix[i+1]);
				i++;
			}

			NumberStack.push(sToDbl(number));
		}
		else if (isspace(postfix[i])) continue;
		else
		{
			long double c2 = NumberStack.top();
			NumberStack.pop();
			long double c1 = NumberStack.top();
			NumberStack.pop();

			//cout << c1 << " " << ch << endl;
			NumberStack.push(DoMath(c1,c2,ch));
		}
	}

	result = NumberStack.top();
}

double DoMath(double a, double b, char op)
{
	if (op == '+'){return (a + b);}
	else if (op == '-'){return (a - b);}
	else if (op == '*'){return (a * b);}
	else if (op == '/'){return (a / b);}
	else if (op == '^'){return (pow(a,b));}
	else return 0;
}

Because I can not edit my previous post( why can not I? ) I am posting new one...I added checking for disallowed/unknown symbol...so here is the updated code.

#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <windows.h>

using namespace std;

void Check(string &, long double &, int &);
bool IsOperand(char);
bool IsOperator(char);
bool TakesPrecedence(char, char);
void Convert(const string &, string &);
double sToDbl(string const&);
void Calculate(const string &, const string &, long double &);
double DoMath(double,double,char);

int main()
{  
	SetConsoleTitle(L"Postfix Calculator.");

	string infix, postfix;
	long double result = 0.0;

	for( int i = 1; i <= 5 ; i++ )
	{
		switch(i)
		{
		case 1:
			postfix.erase();
			infix.erase();
			cout << "Enter equation (\"q\" for quit): ";
			getline(cin, infix);
			cout << endl;
			if (!(infix.compare("q"))) return 0;
			break;
		case 2:
			Check(infix, result, i);
			break;
		case 3:
			Convert(infix, postfix);
			//cout << "Postfix form:" << postfix << endl;
			break;
		case 4:
			Calculate(postfix, infix, result);
			break;
		case 5:
			cout << "\nResult: " << result << endl << endl;
			i = 0;
			break;
		}
	}	

	return 0;
}

void Check(string &infix, long double & result, int &st)
{
	short counter = 0;
	string symbols = "+-*/()^.0123456789";

	for ( int i = 1; i <= 5; i++ )
	{
		switch (i)
		{
		case 1:
			cout << "Letter/s, Blank/s...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( isalpha(infix[i]) || isspace(infix[i]) )
				{
					infix.erase(i, 1);
					i--;
					counter++;
				}
			}
			if (counter != 0)
			{
				cout << "ERROR!\nThere were letter/s, blank/s in the equation! They were deleted." << endl;
				counter = 0;
			}
			else cout << "OK!" << endl;
			break;

		case 2:
			cout << "Operator/s...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
			{
				if ( IsOperator(infix[i]) && IsOperator(infix[i+1]) )
					counter++;
				else if (IsOperator(infix[infix.size()-1]) || IsOperator(infix[0]))
					counter++;
			}
			if (counter != 0)
			{
				cout << "ERROR!\nThere were error using operators!" << endl;
				counter = 0;
				st = 0;
			}
			else cout << "OK!" << endl;
			break;

		case 3:
			cout << "Parenthesis...";
			for ( string::size_type i = 0; i < infix.size(); i++ )
				if ( infix[i] == '(' || infix[i] == ')' )
					counter++;

			if (counter % 2 != 0)
			{
				cout << "ERROR!\nThere were error placing parenthesis!" << endl;
				counter = 0;
				st = 0;
			}
			else
			{
				cout << "OK!" << endl;
				counter = 0;
			}
			break;

		case 4:
			cout << "Unknown symbol/s...";
			for (size_t i = 0; i < infix.size(); i++)
			{
				for(size_t j = 0; j < symbols.size(); j++)
				{
					if(infix[i] == symbols[j])
					{
						counter++;
					}
				}
			}
			if (counter != infix.size())
			{
				cout << "ERROR!\nThere were unknown symbol/s detected in equation!" << endl;
				st = 0;
				counter = 0;
			}
			else
			{
				cout << "OK!" << endl;
				counter = 0;
			}
			break;

		case 5:// if there is only number entered, convert it to integer and print it as result
			for ( string::size_type i = 0; i < infix.size(); i++ )
				if ( !IsOperand(infix[i]) )counter++;

			if (counter == 0)
			{
				result = sToDbl(infix);
				st = 4;
			}
		}
	}
	cout << endl;
}

bool IsOperand(char ch)
{
	if ((ch >= '0') && (ch <= '9') || (ch == '.'))
		return true;
	else
		return false;
}

bool IsOperator(char ch)
{
	if (((ch == '*') || (ch == '/')) ||
		((ch == '+') || (ch == '-')) || (ch == '^'))
		return true;
	else
		return false;
}


bool TakesPrecedence(char OperatorA, char OperatorB)
{
	if (OperatorA == '(')
		return false;
	else if (OperatorB == '(')
		return false;
	else if (OperatorB == ')')
		return true;
	else if ((OperatorA == '^') && (OperatorB == '^'))
		return false;
	else if (OperatorA == '^')
		return true;
	else if (OperatorB == '^')
		return false;
	else if ((OperatorA == '*') || (OperatorA == '/'))
		return true;
	else if ((OperatorB == '*') || (OperatorB == '/'))
		return false;
	else
		return true;
}

void Convert(const string & infix, string & postfix)
{
	stack <char> OperatorStack;
	const string BLANK = " ";
	char TopSimbol, Simbol;

	for (string::size_type i = 0; i < infix.length(); i++)
	{
		Simbol = infix[i];
		if (IsOperand(Simbol))
		{
			postfix += BLANK + Simbol;
			while ( IsOperand(infix[i+1]))
			{
				postfix.append(1, infix[i+1]);
				i++;
			}
		}
		else
		{
			while ((!OperatorStack.empty()) &&
				(TakesPrecedence(OperatorStack.top(), Simbol)))
			{
				TopSimbol = OperatorStack.top();
				OperatorStack.pop();
				postfix += BLANK + TopSimbol;
			}

			if ((! OperatorStack.empty()) && (Simbol == ')'))
				OperatorStack.pop();
			else
				OperatorStack.push(Simbol);
		}
	}
	while (!OperatorStack.empty())
	{
		TopSimbol = OperatorStack.top();
		OperatorStack.pop();
		postfix += BLANK + TopSimbol;
	}
}

double sToDbl(string const& str) {

	istringstream ss(str);
	long double d;
	ss >> d;

	return d;
}

void Calculate(const string &postfix, const string &infix, long double &result)
{

	stack <long double> NumberStack;

	for (string::size_type i = 0; i < postfix.length(); i++)
	{
		char ch = postfix[i];
		string number;
		number.clear();

		if (IsOperand(postfix[i]))
		{
			number.append(1, ch);

			while (!isspace(postfix[i+1]))
			{
				number.append(1, postfix[i+1]);
				i++;
			}

			NumberStack.push(sToDbl(number));
		}
		else if (isspace(postfix[i])) continue;
		else
		{
			long double c2 = NumberStack.top();
			NumberStack.pop();
			long double c1 = NumberStack.top();
			NumberStack.pop();

			//cout << c1 << " " << ch << endl;
			NumberStack.push(DoMath(c1,c2,ch));
		}
	}

	result = NumberStack.top();
}

double DoMath(double a, double b, char op)
{
	if (op == '+'){return (a + b);}
	else if (op == '-'){return (a - b);}
	else if (op == '*'){return (a * b);}
	else if (op == '/'){return (a / b);}
	else if (op == '^'){return (pow(a,b));}
	else return 0;
}
This article has been dead for over six months. Start a new discussion instead.