#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
#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;
}
}
}
#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");
}
}
欢迎来hack