最近在带大二助教,以前上课听得模模糊糊的知识点现在自己动手全部弄明白了!
思路:主要是用到栈先进后出的数据结构。在该程序中建有两个栈:一个用于存储运算符OPTR(+-*/#),另一个OPND用于存储操作数或运算结果(5 2 2.5)。基本过程是:
(1)首先设置操作数栈为空栈,设置运算符栈以‘#’为栈底元素(其优先级最低)。
(2)通过为栈内栈外运算符设置值而比较其优先级
(3)依次找到表达式中的所有运算符和操作数,对于操作数直接入栈,运算符则和运算符栈的栈顶运算符进行比较优先级,若栈内优先级大,则进行相应操作并且操作数和栈内运算符都出栈,若优先级相等只需栈内运算符出栈继续查找下一个运算符即可,若栈内优先级低则栈外运算符入栈。依次循环知道分析完表达式中
的所有运算符和操作数即可。
(4)最后在操作数栈中将只会剩下唯一的一个元素,而该元素也将就会是所求表达式的值。
#include<iostream>
#include<stack>
#include<string>
using namespace std;
/*判断符号间的优先关系函数
*1表示>,0表示=,-1表示<
*c1栈内的算符,c2栈外的算符
*/
int Judge(char c1, char c2)
{
int a1, a2;
if ('+' == c1 || '-' == c1) a1 = 3;
if ('*' == c1 || '/' == c1)a1 = 5;
if ('(' == c1) a1 = 1;
if (')' == c1) a1 = 7;
if ('#' == c1) a1 = 0;
if ('+' == c2 || '-' == c2)a2 = 2;
if ('*' == c2 || '/' == c2)a2 = 4;
if ('(' == c2) a2 = 6;
if (')' == c2) a2 = 1;
if ('#' == c2) a2 = 0;
if (a1>a2) return 1;
if (a1 == a2) return 0;
if (a1<a2) return -1;
}
//符号运算函数
double run(char c, double d1, double d2)
{
switch (c)
{
case '+':
return d1 + d2;
break;
case '-':
return d1 - d2;
break;
case'*':
return d1*d2;
break;
case '/':
return d1 / d2;
break;
default:
return 0.0;
break;
}
}
int main()
{
char * op = "+-*/()#";
string str;
cin >> str;
//给表达式字符串str添加'#'结束标识符
str.append(1, '#');//添加1个#
stack<char> OPTR;//运算符栈
stack<double> OPND;//操作数栈
//a记录操作符位置
int a = -1;
//先将#符号入栈
OPTR.push('#');
while (true)
{
int b = a + 1;
a = str.find_first_of(op, a + 1);//int find_first_of(char c, int start)查找字符串中第1个出现的c,由位置start开始。
if (a == string::npos) break;//npos 是一个常数,用来表示不存在的位置
if (a != b)
{
string ss(str, b, a - b);//将字符串str内“始于b且长度顶多a - b”的部分作为字符串的初值
double d = atof(ss.c_str());//atof 是ascII to float的缩写,将ascII字符串转换为相应的单精度浮点数
//数据先入栈
OPND.push(d);
}
//运算符优先级比较
int ju = Judge(OPTR.top(), str[a]);
if (-1 == ju)//栈外优先级大直接入栈
{
OPTR.push(str[a]);
}
if (0 == ju)//栈内外优先级相等则出栈
{
OPTR.pop();
}
if (1 == ju)//栈内优先级大,出栈进行运算
{
double d1 = OPND.top();
OPND.pop();
double d2 = OPND.top();
OPND.pop();
d1 = run(OPTR.top(), d2, d1);
//运算结果入栈
OPND.push(d1);
OPTR.pop();
a--;
}
}
//删除表达式最后的'#'结束标识符
str.erase(str.length() - 1, 1);//erase(pos,n);删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
cout << str << " = " << OPND.top() << endl;
}