写一个计算器【后缀表达式】(C++)

前言:

闲来无事,

用后缀表达式写了个计算器。。。

支持加(+)、减(-)、乘(*)、除(/)、乘方(^)

啥是后缀表达式:

波兰逻辑学家卢卡西维奇发明的表示表达式的方法

后缀式即逆波兰式,是波兰逻辑学家卢卡西维奇(Lukasiewicz)发明的一种表示表达式的方法。

这种表示方式把运算符写在运算对象的后面,例如,把a+b写成ab+,所以也称为后缀式。这种表示法的优点是根据运算对象和算符的出现次序进行计算,不需要使用括号,也便于用械实现求值。例如:对于表达式(a+b)*(c+d),其后缀式为ab+cd+*

后缀表达式的优势所在

实现逆波兰式的算法,难度并不大,但为什么要将看似简单的中缀表达式转换为复杂的逆波兰式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。

后缀表达式运算规则

1.设定运算符栈

2.假设表达式的结束符为"#",我们需要预设运算符栈底元素为"#"

3.扫描表达式,若当前字符是操作数,则直接发送给后缀表达式;

4.若当前字符为运算符且优先级大于栈顶运算符,则进栈,否则退出栈顶运算符并将其发送给后缀      式。然后将当前运算符放入栈中。

5.若当前字符是结束符,则将栈中的全部运算符依次发送给后缀式。

6.若当前字符为"(",进栈。

7.若当前字符为")",则从栈顶起,依次将栈中运算符出栈发送给ie后缀式,直到碰到"("。将栈中          "("出栈,不需要发送给后缀式。然后继续扫描表达式。

举个例子:

 代码实现:

#include<bits/stdc++.h>
#include <windows.h>

using namespace std;

string problem;
int len;

string expr;
stack<char> sym;//符号栈 
stack<int > val;//数字栈 

string cmp(char fir ,char sec)//判断优先级 
{ 
	if(fir=='('&&sec==')') return "DELE";
	if(fir=='('||sec=='(') return "PUSH";
	if(sec==')') return "TODO";
	if(fir=='+'||fir=='-') return (sec=='+'||sec=='-')? "TODO":"PUSH";
	if(fir=='*'||fir=='/') return (sec=='*'||sec=='/'||sec=='+'||sec=='-')? "TODO":"PUSH";
	return "TODO";
}
int  ANS(string prob)
{
	expr="";
	while(sym.size()) sym.pop();
	while(val.size()) val.pop();
	//处理字符串 ,把整个字符串用括号套起来(处理负数,如“-1+1”) 
	expr+="(";
	for(int i=0; i<prob.size(); i++)
	{
		if( (prob[i]=='-'||prob[i]=='+') && (!i||prob[i-1]=='(') ) expr+='0'; 
		if(prob[i]=='('&&prob[i-1]==')') expr+='*';
		expr+=prob[i];
	}
	expr+=")";
	sym.push('(');
	for(int i=1; i<expr.size(); i++)
	{
		int num=0;
		if(isdigit(expr[i]))
		{
			while(isdigit(expr[i])) num=num*10+expr[i]-'0',i++;
			val.push(num);
		}
		while(true)
		{
			string OP=cmp(sym.top(),expr[i]);
			if(OP=="PUSH"){sym.push(expr[i]);break;}
			if(OP=="DELE"){sym.pop();break;}
            if(OP=="TODO")
			{
				int a,b;
				//取出两个数字 
				a=val.top(),val.pop();
				b=val.top(),val.pop();
				//取出一个运算符 
				char op=sym.top();
				sym.pop();
				
				
				if(op=='+') val.push(a+b);
				if(op=='-') val.push(b-a);
				if(op=='*') val.push(a*b);
				if(op=='/') val.push(b/a);
				if(op=='^') val.push(pow(b,a));
			}
		}
	}
	return val.top();
}
signed main()
{
	while(1)
	{
		system("cls");
		cout<<"请输入表达式:\n";
		cin>>problem;
		system("cls");
		cout<<"答案:\n";
	    cout<<problem<<"="<<ANS(problem)<<"\n";
	    system("pause");
	}
	
	return 0;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个比较完整的计算器C++代码示例,共计约200行。它支持基本的四则运算、括号、取模、取反、小数和科学计数法等功能。 ``` #include <iostream> #include <stack> #include <cmath> using namespace std; // 定义优先级 int getPriority(char c) { if(c == '(' || c == ')') return 0; if(c == '+' || c == '-') return 1; if(c == '*' || c == '/' || c == '%') return 2; if(c == '^') return 3; return -1; } // 判断是否为数字 bool isNumber(char c) { return (c >= '0' && c <= '9') || c == '.'; } // 中缀表达式转后缀表达式 string infixToPostfix(string infix) { stack<char> s; string postfix; for(int i = 0; i < infix.length(); i++) { if(isNumber(infix[i])) { postfix += infix[i]; if(!isNumber(infix[i+1])) postfix += ' '; } else if(infix[i] == '(') { s.push(infix[i]); } else if(infix[i] == ')') { while(s.top() != '(') { postfix += s.top(); postfix += ' '; s.pop(); } s.pop(); } else { while(!s.empty() && getPriority(s.top()) >= getPriority(infix[i])) { postfix += s.top(); postfix += ' '; s.pop(); } s.push(infix[i]); } } while(!s.empty()) { postfix += s.top(); postfix += ' '; s.pop(); } return postfix; } // 后缀表达式计算 double calculate(string postfix) { stack<double> s; for(int i = 0; i < postfix.length(); i++) { if(isNumber(postfix[i])) { double num = 0, dec = 0, k = 1; while(isNumber(postfix[i])) { if(postfix[i] == '.') { dec = 1; i++; continue; } if(dec == 0) { num = num * 10 + (postfix[i] - '0'); } else { k *= 0.1; num += (postfix[i] - '0') * k; } i++; } s.push(num); i--; } else if(postfix[i] == '+') { double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); s.push(num1 + num2); } else if(postfix[i] == '-') { double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); s.push(num1 - num2); } else if(postfix[i] == '*') { double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); s.push(num1 * num2); } else if(postfix[i] == '/') { double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); if(num2 == 0) { cout << "错误!除数不能为0。"; return 0; } s.push(num1 / num2); } else if(postfix[i] == '%') { int num2 = s.top(); s.pop(); int num1 = s.top(); s.pop(); if(num2 == 0) { cout << "错误!除数不能为0。"; return 0; } s.push(num1 % num2); } else if(postfix[i] == '^') { double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); s.push(pow(num1, num2)); } else if(postfix[i] == 'u') { double num = s.top(); s.pop(); s.push(-num); } } return s.top(); } // 主函数 int main() { string infix; cout << "输入中缀表达式:"; getline(cin, infix); string postfix = infixToPostfix(infix); cout << "后缀表达式:" << postfix << endl; double result = calculate(postfix); cout << "结果:" << result << endl; return 0; } ``` 此代码使用了栈来实现中缀表达式转后缀表达式后缀表达式计算。如果你还不熟悉栈的使用,建议先学习一下栈的相关知识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值