输入字符串计算式,输出计算结果

// Caclulator.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <stack>
#include <deque>
#include <queue>

using namespace std;
字符串转数字
//template <class Type>
//Type stringToNum(string s) {
//	istringstream iss(s);
//	Type num;
//	iss >> num;
//	return num;
//}
enum DataType {
	DT_Num = 0,
	DT_Oper
};
struct OperData {
	DataType type;
	int data;
};
int getOperPriority(char oper) {
	switch (oper)
	{
	case '+':
	case '-':
		return 0;
	case '*':
	case '/':
		return 1;
	default:
		break;
	}
	return -1;
}
bool isNumber(char c) {
	if (c >= '0' && c <= '9') {
		return true;
	}
	return false;
}

bool isOper(char c) {
	switch (c)
	{
	case '+': return true;
	case '-': return true;
	case '*': return true;
	case '/': return true;
	}
	return false;
}

bool parseToMidOrder(string s, vector<OperData> &midOrder, string &err) {
	
	string lastNum;
	bool lastIsOper = false;
	int leftBracketNum = 0;
	int rightBracketNum = 0;
	for (int i = 0; i < s.size(); ++i) {
		if (isNumber(s[i])) {
			lastNum.push_back(s[i]);
			lastIsOper = false;
		}
		else if (isOper(s[i])) {
			if (lastIsOper) {
				err = "two oper can't back to back";
				midOrder.clear();
				return false;
			}
			if (!lastNum.empty())
			{
				midOrder.push_back({ DT_Num, stoi(lastNum) });
				lastNum.clear();
			}
			midOrder.push_back({ DT_Oper, s[i] });
			lastIsOper = true;
		}
		else if ('(' == s[i]) {
			midOrder.push_back({ DT_Oper, s[i] });
			leftBracketNum++;
			
		}
		else if (')' == s[i]) {
			if (lastIsOper) {
				err = "two oper can't back to back";
				midOrder.clear();
				return false;
			}

			rightBracketNum++;
			if (!lastNum.empty())
			{
				midOrder.push_back({ DT_Num, stoi(lastNum) });
				lastNum.clear();
			}
			midOrder.push_back({ DT_Oper, s[i] });
		}
		else if (s[i] != ' ' || s[i] != '\t') {
			err = "find invalid character";
			midOrder.clear();
			return false;			
		}
	}
	if (leftBracketNum != rightBracketNum) {
		err = "bracket num is not match";
		midOrder.clear();
		return false;
	}
	if (lastNum.size() > 0) {
		midOrder.push_back({ DT_Num, stoi(lastNum) });
	}
	
	return true;
}
double calcTwoNum(char oper, double first, double second) {
	switch (oper)
	{		
	case '+': return first + second;
	case '-': return first - second;
	case '*': return first * second;
	case '/': return first / second;
	}
	return 0;
}
//计算
double calculate(const deque<OperData>& backOrder) {
	stack<double> stackToCalc;
	for (auto data : backOrder) {
		if (DT_Oper == data.type) {
			if (stackToCalc.size() < 2) {
				return 0;
			}
			double secondNum = stackToCalc.top();
			stackToCalc.pop();
			double firstNum = stackToCalc.top();
			stackToCalc.pop();
			double result = calcTwoNum(static_cast<char>(data.data), firstNum, secondNum);
			stackToCalc.push(result);
		}
		else if (DT_Num == data.type) {
			stackToCalc.push(data.data);
		}
	}
	return stackToCalc.top();
}
void transToBackOrder(const vector<OperData>& midOrder, deque<OperData> &backOrder){
	stack<char> stackOperator;
	for (int i = 0; i < midOrder.size(); ++i) {
		if (DT_Num == midOrder[i].type) {
			backOrder.push_back(midOrder[i]);
		}
		else if(DT_Oper == midOrder[i].type){
			if (isOper(static_cast<char>(midOrder[i].data)))
			{
				if (stackOperator.empty()) {
					stackOperator.push(static_cast<char>(midOrder[i].data));
				}
				else {
					if (stackOperator.top() == '(') {
						stackOperator.push(static_cast<char>(midOrder[i].data));
					}
					else {
						while (stackOperator.size()) {
							//栈顶符号比读出的符号优先级高,栈顶出栈,保存到队列中
							if (getOperPriority(stackOperator.top()) >= getOperPriority(static_cast<char>(midOrder[i].data))) {
								backOrder.push_back({ DT_Oper, stackOperator.top() });
								stackOperator.pop();
							}
							else {
								//栈顶符号比读出的符号优先给低,将当前符号压入框中
								stackOperator.push(static_cast<char>(midOrder[i].data));
								break;
							}
						}
						if (0 == stackOperator.size()) {
							stackOperator.push(static_cast<char>(midOrder[i].data));
						}
					}
				}
			}
			else if ('(' == static_cast<char>(midOrder[i].data)) {
				stackOperator.push('(');
			}
			else if (')' == static_cast<char>(midOrder[i].data)) {
				while (stackOperator.size()) {
					if ('(' == stackOperator.top()) {
						stackOperator.pop();
						break;
					}
					backOrder.push_back({ DT_Oper, stackOperator.top() });
					stackOperator.pop();
				}
			}
		}
	}
	while (stackOperator.size()) {
		backOrder.push_back({ DT_Oper, stackOperator.top() });
		stackOperator.pop();
	}
}
int main()
{
	//string s = "(5+3*5-88*(5-5/(2*8)))";
	string s = "(1+1*1-1*(1-1/(1*1)))";
	//5 3 5 * + 88 5 5 2 8 * / - * -
	vector<OperData> midOrder;
	string error;
	bool err = parseToMidOrder(s, midOrder, error);
	if (!err) {
		cout << error << endl;
	}
	for (auto data : midOrder) {
		if (data.type == DT_Num) {
			cout << data.data << ' ';
		}
		else if (data.type == DT_Oper) {
			char oper = data.data;
			cout << oper << ' ';
		}
	}
	std::cout << "\n";

	deque<OperData> backOrder;
	transToBackOrder(midOrder, backOrder);
	for (auto data : backOrder) {
		if (data.type == DT_Num) {
			cout << data.data << ' ';
		}
		else if (data.type == DT_Oper) {
			char oper = data.data;
			cout << oper << ' ';
		}
	}
	std::cout << "\n";

	std::cout << "result:" << calculate(backOrder);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
因各个项目中需要使用根据字符串计算数值,这里写出一个算法,专门计算字符串。配有大量常用公。只有一个人方法,直接调用即可。 类名:CustomMath 函数名:Calculations(string value) 说明:求解算式表达字符串的值 表达中包含的符号或函数: truncate, ceiling,floor,round,log10, sign,sinh,sqrt, asin,atan,cosh, tanh, sin,cos,tan ,abs,acos, exp,log,max,min,pow,mod,+,-,*,/,',',(,) 函数说明:(不区分大小写) truncate(num) 计算指定数的整数部分 truncate(1.23)=1 ceiling (num) 返回大于或等于指定的双精度浮点数的最小整数值 ceiling(1.23)=2 floor(num) 返回小于或等于指定双精度浮点数的最大整数 floor(1.23)=1 round(num) 将双精度浮点值舍入为最接近的整数值 round(1.23)=1 round(num,num1) 将小数值按指定的小数位数舍入 round(1.23,1)=1.2 log10(num) 返回指定数字以 10 为底的对数 log10(10)=1 sign(num) 返回表示数字符号的值 sign(1.23)=1 sinh(num) 返回指定角度的双曲正弦值 sinh(1.23)=1.5644 sqrt(num) 返回指定数字的平方根 sqrt(9)=3 sqrt(num,num1) 返回指定数字的num1根 sqrt(27,3)=3 asin(num) 返回正弦值为指定数字的角度 asin(0.5)=PI/6 atan(num) 返回正切值为指定数字的角度 atan(1)=45 cosh(num) 返回指定角度的双曲余弦值 cosh(1.23)=1.8567 tanh(num) 返回指定角度的双曲正切值 tanh(1.23)=0.8425 sin(num) 返回指定角度的正弦值 sin(PI/6)=0.5 cos(num) 返回指定角度的余弦值 sin(PI/3)=0.5 tan(num) 返回指定角度的余切值 sin(PI/4)=1 abs(num) 返回数字的绝对值 abs(-12)=12 acos(num) 返回余弦值为指定数字的角度 acos(0.5)=PI/3 exp(num) 返回 e 的指定次幂 exp(1)=2.718 log(num) 返回指定数字的自然对数(底为 e) log(e)=1 log(num,num1) 返回指定数字在使用指定底时的对数 log(e,e)=1 max(num,um1) 返回最大值 max(1,2)=2 min(num,num1) 返回最小值 min(1,2)=1 pow(num,num1) 返回指定数字的指定次幂 pow(2,2)=4 mod(num,num1) 返回余数 mod(3,2)=1 常量: PI 值:3.14159265358979323846 E 值:2.7182818284590452354 YEAR 值:当前年份 MONTH 值:当前月份 DAY 值: 当前日 HOUR 值:当前时 MINUTE 值:当前分 SECOND 值:当前秒 RANDOM 值:一个随机数(0-1 之间) 实例 系统计算:1+2*3/4-0.5=2 函数计算:1+2*3/4-0.5=2 调用方:CustomMath.Calculations("1+2*3/4-0.5") 系统计算:(1+2)*3/4-0.5=1.75 函数计算:(1+2)*3/4-0.5=1.75 调用方:CustomMath.Calculations("(1+2)*3/4-0.5") 系统计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 公计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 调用方:CustomMath.Calculations("(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6") 系统计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 函数计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 调用方:CustomMath.Calculations("sin(pow(3,2)/4)+3.5-9*sqrt(81)")

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值