1.任务:
[问题描述]
一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#6+15*(21-8/4)#。引入表达式起始、结束符是为了方便。编程利用“运算符优先法”求算术表达式的值。
[基本要求]
(1)从键盘或文件读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
(3)考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。
(4)实现非整数的处理(*)。
2.采用的数据结构
采用栈的结构
3.算法设计思想
依次读入表达式中的每一个字符,若为输入为数字,则加入数字栈;若读取为操作符,当其优先级高于栈顶操作符优先级,则将它加入符号栈,当其优先级低于栈顶操作符时,则符号栈弹出符号,数字栈弹出两个数字进行计算,将计算所得结果压入数字栈,操作符继续与栈顶操作符进行优先级比较,直至最后读入’#’。时间复杂度T(n)=O(n).
同时,程序可以对于表达式出现的错误进行提示,例如输入表达式格式不正确,除数为零等,实现了算法的健壮性。
4.源程序:
#include <iostream>
#include <math.h>
using namespace std;
char input[128];
int position;
double Calculation(double a,double b,char op) //定义运算
{
switch (op)
{
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
default:
printf("表达式中含有错误运算符!");
exit -1;
}
}
int Provity(char op)
{
if(op=='*' || op=='/')
{
return 2;
}
else if(op=='+' || op=='-')
{
return 1;
}
else if(op=='(')
{
return 0;
}
else if(op=='#')
{
return -1;
}
else
{
printf("表达式中含有错误运算符!");
exit -1;
}
}
double GetNum(int &position) //提取输入的表达式中的数字
{
int integer=0;
double decimal=0;
while (input[position]>= '0' && input[position]<= '9')
{
integer=integer*10;
int t;
t=input[position]-'0';
integer=integer+t;
position++;
}
if (input[position]=='.')
{
position++;
int t;
double w=0.1;
while (input[position]>='0' && input[position]<= '9')
{
t=input[position]-'0';
decimal=decimal+t*w;
w=w*0.1;
position++;
}
}
return integer+decimal;
}
double Compute() //计算表达式
{
char opstack[64]; //符号栈
double numstack[128]; //数字栈
opstack[0]='#';
int optail=1;
int numtail=0;
if (input[0] != '#')
{
printf("输入公式有误!");
exit -1;
}
int position=1;
while (input[position]!='#')
{
if(input[position]== '(') //当输入'('时
{
opstack[optail++]='(';
printf("运算符'('入栈\n");
position++;
}
else if (input[position] == ')') //当输入')'时
{
position++;
while (opstack[--optail]!='(')
{
double a;
a=numstack[--numtail];
printf("数字%f出栈\n",a);
double b;
b=numstack[--numtail];
printf("数字%f出栈\n",b);
char op;
op=opstack[optail];
printf("运算符'%c'出栈\n", op);
if (op=='/' && a==0)
{
printf("ERROR: 0不能做除数!\n");
exit -1;
}
double result;
result=Calculation(b,a,op);
numstack[numtail++]=result;
printf("数字%f入栈\n", result);
}
printf("运算符'(''出栈\n");
}
else if (input[position]>='0'&&input[position]<='9') //如果是数字
{
double num;
num=GetNum(position);
numstack[numtail++]=num;
printf("数字%f入栈\n", num);
}
else //其它运算符
{
while (Provity(input[position]) <= Provity(opstack[--optail]) )
{
double a;
a=numstack[--numtail];
printf("数字%f出栈\n",a);
double b;
b=numstack[--numtail];
printf("数字%f出栈\n",b);
char op;
op=opstack[optail];
printf("运算符'%c'出栈\n", op);
if (op == '/' && a==0)
{
printf("ERROR: 0不能做除数!\n");
exit -1;
}
double result;
result=Calculation(b,a,op);
numstack[numtail++]=result;
printf("数字%f入栈\n", result);
}
optail++;
opstack[optail++]=input[position];
printf("运算符'%c''入栈\n", input[position]);
position++;
}
}
while (opstack[--optail]!= '#')
{
double a;
a=numstack[--numtail];
printf("数字%f出栈\n",a);
double b;
b=numstack[--numtail];
printf("数字%f出栈\n",b);
char op;
op=opstack[optail];
printf("运算符'%c'出栈\n", op);
if (op == '/' && a==0)
{
printf("ERROR: 0不能做除数!\n");
exit -1;
}
double result;
result=Calculation(b,a,op);
numstack[numtail++]=result;
printf("数字%f入栈\n", result);
}
return numstack[--numtail];
}
int main()
{
printf("请输入算术表达式,示例:#6+15*(21-8/4)#\n");
cin>>input;
printf("运算结果为:%f",Compute());
return 0;
}
5.源程序测试数据及结果
算术表达式测试数据及测试结果