C++計算機

69155 ワード

Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

class Calculator {
public:
	bool legality();
	Calculator(string);
	string infixToSuffix(string);
	void printAnswer();
private:
	string fomular;
	bool isSybol(char);
	bool isOper(char);
	void pre(string&);
	double to_double(string);
	int priority(char);
	double calc(char, double, double);
	bool finish(string);
	void formalize(string&);
	double calcString(string);
};

#endif

Calculator.cpp
#include "Calculator.h"
#include 
using namespace std;

Calculator::Calculator(string str)
{
	fomular = str;
}

void Calculator::pre(string& str)
{
	if (str[0] == '+')
	{
		str.insert(0, "0");
	}
	for (string::size_type i = 1; i < str.length(); i++)
	{
		if (str[i - 1] == '(' && str[i] == '+')
		{
			str.insert(i, "0");
		}
	}

	for (string::size_type i = 0; i < str.length(); i++)
	{
		if (str[i] == '-')
		{
			if (i == 0 || str[i - 1] == '(')
			{
				str.insert(i, "0");
			}
		}
	}

	bool noOper = true;
	for (string::size_type i = 0; i < str.length(); i--)
	{
		if (isOper(str[i]))
		{
			noOper = false;
			break;
		}
	}
	if (noOper == false)
	{
		for (string::size_type i = 0; i < str.length(); i++)
		{
			if (isdigit(str[i]) || str[i] == '.')
			{
				str.insert(i, "0+");
				break;
			}
		}
	}
	//cout << str << endl;
	//system("pause");
}

bool Calculator::isSybol(char ch)
{
	if (ch == '+' || ch == '-' || ch == '/' || ch == '*' || ch == '(' || ch == ')')
	{
		return true;
	}
	return false;
}

bool Calculator::isOper(char ch)
{
	if (ch == '+' || ch == '-' || ch == '/' || ch == '*')
	{
		return true;
	}
	return false;
}

double Calculator::to_double(string str)
{
	stringstream ss;
	ss << str;
	double ans;
	ss >> ans;
	return ans;
}


int Calculator::priority(char ch)
{
	switch (ch)
	{
	case '+':
		return 3;
	case '-':
		return 3;
	case '*':
		return 4;
	case '/':
		return 4;
	case '(':
		return 1;
	case ')':
		return 2;
	}
	return -1;
}

double Calculator::calc(char oper, double a, double b)
{
	switch (oper)
	{
	case '+':
		return a + b;
	case '-':
		return a - b;
	case '*':
		return a * b;
	case '/':
		if (abs(b - 0) < 1e-6)
		{
			throw "divided by zero!";
		}
		return a / b;
	}
	return -1;
}


string Calculator::infixToSuffix(string str)
{
	stack< pair<char, int> > st;
	stringstream ans;

	for (string::size_type i = 0; i < str.length(); i++)
	{
		if (isdigit(str[i]))
		{
			//int t = str[i] - '0';
			ans << str[i];
		}
		else if (str[i] == '.')
		{
			ans << '.';
		}
		else
		{
			ans << ' ';
			if (str[i] == '(')
			{
				st.push(make_pair('(', priority('(')));
			}
			else if (str[i] == ')')
			{
				while (!st.empty() && st.top().first != '(')
				{
					ans << st.top().first << " ";
					st.pop();
				}
				st.pop();
			}
			else
			{
				int priorityNow = priority(str[i]);
				while (!st.empty() && st.top().second >= priorityNow)
				{
					ans << st.top().first << "  ";
					st.pop();
				}
				st.push(make_pair(str[i], priorityNow));
			}
		}
	}

	while (!st.empty())
	{
		ans << " " << st.top().first << "  ";
		st.pop();
	}
	string answer;
	getline(ans, answer);

	//cout << answer << endl;
	//system("pause");
	for (string::size_type i = answer.length() - 1; i >= 0; i--)
	{
		if (answer[i] == ' ')
		{
			answer.erase(i, 1);
		}
		else
		{
			break;
		}
	}
	answer.insert(--answer.end(), ' ');

	return answer;
}



bool Calculator::legality()
{
	for (string::size_type i = 0; i < fomular.length(); i++)
	{
		if (!isdigit(fomular[i]) && !isSybol(fomular[i]) && fomular[i] != '.')
		{
			return false;
		}
	}

	pre(fomular);

	stack<char> charStack;
	for (string::size_type i = 0; i < fomular.length(); i++)
	{
		if (fomular[i] == '(')
		{
			charStack.push(fomular[i]);
		}
		if (fomular[i] == ')')
		{
			if (charStack.empty())
			{
				return false;
			}
			else
			{
				charStack.pop();
			}
		}
	}
	if (!charStack.empty())
	{
		return false;
	}

	for (string::size_type i = 0; i < fomular.length(); i++)
	{
		if (fomular[i] == '.')
		{
			for (string::size_type j = i + 1; j < fomular.length(); j++)
			{
				if (isSybol(fomular[j]))
				{
					break;
				}
				else if (fomular[j] == '.')
				{
					return false;
				}
			}
		}
	}

	for (string::size_type i = 0; i < fomular.length(); i++)
	{
		if (fomular[i] == '*' || fomular[i] == '/' || fomular[i] == '+')
		{
			if (i == 0 || (!isdigit(fomular[i - 1]) && fomular[i - 1] != '.'&&fomular[i - 1] != ')') || i + 1 == fomular.length() || (!isdigit(fomular[i + 1]) && fomular[i + 1] != '.'&&fomular[i + 1] != '('))
			{
				return false;
			}
		}

		if (fomular[i] == '(')
		{
			if (!(i == 0 || isOper(fomular[i - 1]) || fomular[i - 1] == '('))
			{
				return false;
			}
		}

		if (fomular[i] == ')')
		{
			if (!(i == fomular.length() - 1 || isOper(fomular[i + 1]) || fomular[i + 1] == ')'))
			{
				return false;
			}
		}

		if (fomular[i] == '-')
		{
			if (i + 1 == fomular.length() || fomular[i + 1] == ')')
			{
				return false;
			}
		}

	}

	return true;
}

bool Calculator::finish(string str)
{
	if (!isOper(*(--str.end())))
	{
		return true;
	}
	return false;
}


void Calculator::formalize(string& str)
{
	for (string::size_type i = 0; i < str.length(); i++)
	{
		if (str[i] == ' ')
		{
			for (string::size_type j = i + 1; j < str.length(); j++)
			{
				if (str[j] != ' ')
				{
					break;
				}
				else
				{
					str.erase(j, 1);
					j--;
				}
			}
		}
	}

	if (str[0] == ' ')
	{
		str.erase(0, 1);
	}
}


double Calculator::calcString(string str)
{
	while (!finish(str))
	{
		char op;
		double a, b;
		int l, r;
		for (string::size_type i = 0; i < str.length(); i++)
		{
			if (isOper(str[i]) && i != 0 && str[i - 1] == ' ' && (i + 1 == str.length() || str[i + 1] == ' '))
			{
				op = str[i];
				r = i;
				break;
			}
		}

		int blankCnt = 0;


		for (string::size_type i = r; i >= 0; i--)
		{
			if (str[i] == ' ')
			{
				blankCnt++;
			}

			if (blankCnt == 3)
			{
				l = i;
				break;
			}
			if (i == 0)
			{
				l = -1;
				break;
			}
		}

		string::size_type blankPos1, blankPos2;
		for (int i = l + 1; i <= r; i++)
		{
			if (i < 0)
			{
				continue;
			}
			else if (str[i] == ' ')
			{
				blankPos1 = i;
				break;
			}
		}
		//blankPos1=str.find_first_of(" ",l+1,r-l);
		blankPos2 = r - 1;

		//	cout<
		//	system("pause");

		//	cout<
		//	cout<
		//	system("pause");

		a = to_double(str.substr(l + 1, blankPos1 - l - 1));
		b = to_double(str.substr(blankPos1 + 1, blankPos2 - blankPos1 - 1));
		//cout<//system("pause");
double tmpAns = calc(op, a, b);
//cout<
//system("pause");
str.replace(l + 1, r - l, to_string(tmpAns));
if (str[0] == ' ')
{
str.erase(0, 1);
}
//cout << str << endl;
//system("pause");
}
//cout<
return to_double(str);
}
void Calculator::printAnswer()
{
if (!legality())
{
throw "The fomular has syntax error, refuse to calculate";
}
else
{
//pre(fomular);
fomular = infixToSuffix(fomular);
formalize(fomular);
try
{
double res = calcString(fomular);
cout << "Answer is: " << res << endl;
}
catch (const char* msg)
{
cerr << msg << endl;
}
}
}

test.cpp
#include "Calculator.h"
#include 
#include 
using namespace std;

int main()
{
	while (true)
	{
		string str;
		cin >> str;
		Calculator a(str);
		
		try
		{
			a.printAnswer();
		}
		catch (const char* msg)
		{
			cerr << msg << endl;
		}

		system("pause");
	}
}

ようこそハック