计算器2版

孤者浪人 提交于 2020-01-26 18:30:38

东软学习小组成员:夜枫

先看效果图:
没有写判断表达式正确与否的函数,所以只能识别正确的表达式,可以有小数括号如:6.2+2*(3-2)-3/2
结果为:6.7,已经在程序上测试

在这里插入图片描述
在这里插入图片描述

普通式子为中缀表达式:如 6+2-3/3=?
而如果用电脑计算则无法判断优先级,故此转换为后缀表达式:6 2 + 3 3 / -来解决优先级问题
转换思路为:用栈来处理优先级
栈的特点为:先进后出,只有一个出口。
队列特点为:先进先出,由两个出口。

拿到一个中缀表达式,首先需要将其转换为后缀表达式。

c++代码
需要的头文件:

#include<iostream>
#include<stack>//栈
#include<queue>//队列
#include<map>//map是一种关联容器
#include<math.h>
#include<string>

关于map的基本知识和使用:

c++ queue 容器介绍

C++ 栈(Stack)的基本操作

将中缀表达式的字符串改为后缀的方法:

queue<node> Change_infix_to_suffix(string str);// 将中缀表达式的str修改为后缀表示式子,并返回一个队列,队列元素类型为结构体{}
/*typedef struct Node{
	bool falg;//判断node元素是算术符号还是数字,true为算术运算符 
	double num;//
	char tp;
}node;
*/ 

queue<node> Change_infix_to_suffix(string str){
	
	queue<node> q;
	int len=str.length();//字符窜的长度
	//遍历每一个字符,并做出判断,如果为左括号,压栈,如果为右括号,一直弹栈直到左括号,如果为数字,进队列,如果为算术符号,
	//弹出所有比该字符优先级大的字符,直到比其小为止
	node temp;
	for(int i=0;i<len;){
		if(str[i]=='('){
			temp.falg=true;
			temp.tp=str[i];
			s.push(temp);
			i++;
		}
		else if(str[i]==')'){
			while(!s.empty()&&s.top().tp!='('){
				q.push(s.top()); 
				s.pop();
			}
			s.pop();//弹出左括号,但不进队列 
			i++;
		}
		else if(isdigit(str[i])){
			//数字,不一定为是个位数,也不一定为整数
			double num;
			num=str[i]-'0';
			i++;
			while(i<len&&str[i]>='0'&&str[i]<='9'){//处理整数 
				num=num*10+str[i]-'0';
				i++;
			}
			 //处理小数;
			 int l=0;//小数后几位 
			 if(str[i]=='.'&&i<len){
			 	i++;
			 	while(isdigit(str[i])){
			 		num =num+(str[i]-'0')*(pow(0.1,++l));
			 		i++;
				}
			 }
			 temp.falg=false;
			 temp.num=num;
			//因为是数字,进入队列
			q.push(temp); 
		}
		else{
			while(!s.empty() && ( p[s.top().tp]>=p[str[i]] ) ){
				q.push(s.top());
				s.pop();
			}
			temp.falg=true;
			temp.tp=str[i];
			s.push(temp);
			i++;
		}
		printfqueueAndstack(q,s);
		
	}
	//所有已经遍历完将栈中的所有元素弹出
	 while(!s.empty()){
	 	q.push(s.top());
	 	s.pop();
	 }
	 printfqueueAndstack(q,s);
	 return q;
}

打印队列和栈种的元素的方法:

void printfqueueAndstack(queue<node> q,stack<node> s){
	stack<node> t1=s;
	queue<node> t=q;
	stack<node> t1s;
	node cud;
	cout<<"\n栈中的元素为:";
	while(!t1.empty()){
		cud=t1.top();
		t1s.push(cud);
		t1.pop();
	}
	while(!t1s.empty()){
		cud=t1s.top();
		cout<<cud.tp<<" ";
		t1s.pop();
	}
	cout<<"\n队列中的元素为:";
	while(!t.empty()){
		cud=t.front();
		if(cud.falg==true) cout<<cud.tp<<" ";
		else cout<<cud.num<<" ";
		t.pop();
	}
	cout<<"\n\n";
}

double Evaluate_suffix_expression(queue q)方法;//计算后缀表达式,并将结果返回为字符串类型

double Evaluate_suffix_expression(queue<node> q){
	double reuse;
	queue<node> tq=q;//拿到队列
	//遍历队列
	node cur;
	stack<node> ts; 
	double a,b;
	while(!tq.empty()){
		cur=tq.front();
		if(cur.falg==false){
			//如果是数字,则放进栈中
			ts.push(cur);
			tq.pop(); 
		}
		else{
			//如果是算术符号则从栈中取出两个,进行计算,将结果在放进去
			 b=ts.top().num;
			 ts.pop();
			 a=ts.top().num;
			 ts.pop();
			 char c=cur.tp;
			 double res;
			 switch(c){
			 	case '*':
			 		res=a*b;
			 		break;
			 	case '/':
			 		res=a/b;
			 		break;
			 	case '+':
			 		res=a+b;
			 		break;
			 	case '-':
			 		res=a-b;
			 		break;
			 }
			 
			cur.falg=false;
			cur.num=res;
			ts.push(cur);
			tq.pop();
		}
		
	}
	reuse=ts.top().num;
	ts.pop();
	return reuse;
}

c++源代码:

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<math.h>
#include<string>
using namespace std;
map<char,int> p;
typedef struct Node{
	bool falg;//true为算术运算符 
	double num;
	char tp;
}node; 
//typedef struct Node node;
stack<node> s;
queue<node> q;
stack<node> s1;
void printfqueueAndstack(queue<node> q,stack<node> s);//打印队列和栈中的元素 
queue<node> Change_infix_to_suffix(string str);// 将中缀表达式的str修改为后缀表示式子,并返回一个队列,队列元素类型为结构体{}
/*typedef struct Node{
	bool falg;//true为算术运算符 
	double num;
	char tp;
}node;
*/ 

double Evaluate_suffix_expression(queue<node> q);//计算后缀表达式,并将结果返回为字符串类型
 


int main(void){
p['*']=p['/']=1;
p['-']=p['+']=0;
p['(']=p[')']=-1;
	string str;
	cin>>str;
	q=Change_infix_to_suffix(str);
	queue<node> tem=q;
	node cue;
//	cout<<"\n结果为:";
//	while(!q.empty()){
//		cue=q.front();
//		if(cue.falg==true) cout<<cue.tp<<" ";
//		else cout<<cue.num<<" ";
//		q.pop();
//	}
	double res=Evaluate_suffix_expression(q);
	cout<<"计算结果为: "<<res<<endl;
}
void printfqueueAndstack(queue<node> q,stack<node> s){
	stack<node> t1=s;
	queue<node> t=q;
	stack<node> t1s;
	node cud;
	cout<<"\n栈中的元素为:";
	while(!t1.empty()){
		cud=t1.top();
		t1s.push(cud);
		t1.pop();
	}
	while(!t1s.empty()){
		cud=t1s.top();
		cout<<cud.tp<<" ";
		t1s.pop();
	}
	cout<<"\n队列中的元素为:";
	while(!t.empty()){
		cud=t.front();
		if(cud.falg==true) cout<<cud.tp<<" ";
		else cout<<cud.num<<" ";
		t.pop();
	}
	cout<<"\n\n";
}
queue<node> Change_infix_to_suffix(string str){
	
	queue<node> q;
	int len=str.length();//字符窜的长度
	//遍历每一个字符,并做出判断,如果为左括号,压栈,如果为右括号,一直弹栈直到左括号,如果为数字,进队列,如果为算术符号,
	//弹出所有比该字符优先级大的字符,直到比其小为止
	node temp;
	for(int i=0;i<len;){
		if(str[i]=='('){
			temp.falg=true;
			temp.tp=str[i];
			s.push(temp);
			i++;
		}
		else if(str[i]==')'){
			while(!s.empty()&&s.top().tp!='('){
				q.push(s.top()); 
				s.pop();
			}
			s.pop();//弹出左括号,但不进队列 
			i++;
		}
		else if(isdigit(str[i])){
			//数字,不一定为是个位数,也不一定为整数
			double num;
			num=str[i]-'0';
			i++;
			while(i<len&&str[i]>='0'&&str[i]<='9'){//处理整数 
				num=num*10+str[i]-'0';
				i++;
			}
			 //处理小数;
			 int l=0;//小数后几位 
			 if(str[i]=='.'&&i<len){
			 	i++;
			 	while(isdigit(str[i])){
			 		num =num+(str[i]-'0')*(pow(0.1,++l));
			 		i++;
				}
			 }
			 temp.falg=false;
			 temp.num=num;
			//因为是数字,进入队列
			q.push(temp); 
		}
		else{
			while(!s.empty() && ( p[s.top().tp]>=p[str[i]] ) ){
				q.push(s.top());
				s.pop();
			}
			temp.falg=true;
			temp.tp=str[i];
			s.push(temp);
			i++;
		}
		printfqueueAndstack(q,s);
		
	}
	//所有已经遍历完将栈中的所有元素弹出
	 while(!s.empty()){
	 	q.push(s.top());
	 	s.pop();
	 }
	 printfqueueAndstack(q,s);
	 return q;
}

double Evaluate_suffix_expression(queue<node> q){
	double reuse;
	queue<node> tq=q;//拿到队列
	//遍历队列
	node cur;
	stack<node> ts; 
	double a,b;
	while(!tq.empty()){
		cur=tq.front();
		if(cur.falg==false){
			//如果是数字,则放进栈中
			ts.push(cur);
			tq.pop(); 
		}
		else{
			//如果是算术符号则从栈中取出两个,进行计算,将结果在放进去
			 b=ts.top().num;
			 ts.pop();
			 a=ts.top().num;
			 ts.pop();
			 char c=cur.tp;
			 double res;
			 switch(c){
			 	case '*':
			 		res=a*b;
			 		break;
			 	case '/':
			 		res=a/b;
			 		break;
			 	case '+':
			 		res=a+b;
			 		break;
			 	case '-':
			 		res=a-b;
			 		break;
			 }
			 
			cur.falg=false;
			cur.num=res;
			ts.push(cur);
			tq.pop();
		}
		
	}
	reuse=ts.top().num;
	ts.pop();
	return reuse;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!