表达式在源码中经常出现,如何针对复杂的表达式进行分析计算是程序运行时必须解决的问题,请设计程序对满足如下要求的表达式进行分析,计算表达式的值。
1.操作数是十进制形式的多位整数或者实数。
2.运算符包括+,-,*,/,%。
3.界限符包括(),[ ],{ }。
4.若表达式合法,则输出表达式的值,否则提示表达式不合法。
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>//C++中数学函数的头文件
using namespace std;
const int maxsize = 100;//定义常量
typedef struct
{
double* top;//栈顶指针,指向当前栈顶元素的下一个
double* base;//栈底指针
int stacksize;//栈当前的长度,不包括后面分配的动态内存
} sta;
int init_stack(sta* s)//初始化栈
{
s->base = (double*)malloc(maxsize * sizeof(double));//分配新空间
if (!s->base)//判断栈是否成功初始化
{
return 0;
}
s->top = s->base;
s->stacksize = maxsize;//栈的长度初始化
return 1;
}
int push(sta* s, double m)//入栈函数,m作为新元素
{
if (s->top - s->base == s->stacksize)//判断栈是否是满的
{
return 0;
}
*s->top = m;//把m的值赋值给栈顶指针所指向的位置
s->top++;//栈顶指针+1,符合栈存储结构中栈顶指针的定义
return 1;
}
int pop(sta* s, double* e)//出栈函数
{
if (s->base == s->top)//有栈顶和栈底指针时判断栈空的条件
{
return 0;
}
s->top--;//栈顶指针-1,符合栈顶指针的定义
*e = *s->top;
return 1;
}
double gettop(sta* s)//获取栈顶元素
{
if (s->base != s->top)//判断栈是否是空的
return *(s->top - 1);
else
return 0;
}
double law(double a, double b, char c)//c作为字符,a和b分别是数字,用来计算二元表达式
{
switch (c)
{
case'+':
return a + b;
break;
case'-':
return a - b;
break;
case'*':
return a * b;
break;
case'/':
if (b == '0')//除法要判断分母是否为0
{
cout << "分母不可以是0" << endl;
return 1;
}
return a / b;
break;
case'%':
return fmod(a, b);//引用了fmod函数,基本的a%b只能用于整型计算
break;
default:
break;
}
return 0;
}
char compare(char a, char b)//运算符的优先级,在计算表达式中调用
{
switch(a)
{
case'+':
{
if(b=='+'||b=='-'||b==')'||b=='=')
return '>';
else return '<';
break;
}
case'-':
{
if(b=='+'||b=='-'||b==')'||b=='=')
return '>';
else return '<';
break;
}
case'*':
{
if(b=='*'||b=='/'||b=='-'||b=='+'||b=='%'||b==')'||b==']'||b=='}'||b=='=')
return '>';
else return '<';
break;
}
case'/':
{
if(b=='*'||b=='/'||b=='-'||b=='+'||b=='%'||b==')'||b==']'||b=='}'||b=='=')
return '>';
else return '<';
break;
}
case'%':
if(b=='*'||b=='/'||b=='-'||b=='+'||b=='%'||b==')'||b==']'||b=='}'||b=='=')
return '>';
else return '<';
break;
case'(':
{
if(b==')')
return '=';
else return '<';
break;
}
case')':
{
return '>';
break;
}
case'[':
if(b==']')
return '=';
else return '<';
break;
case']':
return '<';
break;
case'{':
if(b=='}')
return '=';
else return '<';
break;
case'}':
return '<';
break;
case'=':
{
if(b=='=')
return '=';
else return '<';
break;
default:
break;
}
}
}
int yunsuanfu (char c)//运算符确定,如果不是已经规定的运算符则没有办法计算
{
if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}'
|| c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '=')
return 1;
else
return 0;
}
double calculate(char flag[])//计算表达式的值,变量为数组,直接计算中缀表达式的值不用转化成后缀表达式
{
sta n;//数字栈
sta p;//运算符栈
double a = 0, b = 0, c = 0, d = 0, f = 0;
char ch[maxsize] = { 0 };//定义一个长度确定的数组并初始化,用该数组接收输入的一串字符
int i = 0, j = 0;
init_stack(&n);//初始化建立栈,否则栈不存在没有办法处理
init_stack(&p);
push(&p, '=');//将运算符栈的栈底存放=,用于和表达式中输入的=匹配判断运算结束
ch[j] =flag[i++];//数组接收到字符后指针后移
while (ch[j] != '=' || gettop(&p) != '=')//输入字符结束的判断条件
{
if (isdigit(ch[j]) || ch[j] == '.')//isdigit函数是判断是否为0到9的数字,判断是否为数字或者小数点
{
if (isdigit(ch[j]))
{
d = ch[j]-'0';//接收进来的都是字符,因此要转化成十进制数字
push(&n, d);//数字入栈
f = d;
ch[j] =flag[i++];//指针后移
while (isdigit(ch[j]))//判断下一个字符是不是数字
{
pop(&n, &d);//把之前的数字弹出,和现在的数字结合转化成十进制数
d = ch[j]-'0';
f= 10 * f + d;//转化成十进制数
push(&n, f);//数字入栈
ch[j] = flag[i++];
}
if (ch[j] == '.')//判断是不是小数
{
pop(&n, &f);//前面一个数字出栈
ch[j] = flag[i++];
int nn = 0;
for (nn; isdigit(ch[j]); nn++)
{
d = ch[j] - '0';//当前数字转化成十进制数
f= 10 * f +d;//计算前一个数字也就是小数点后的值
ch[j] = flag[i++];
}
f = f / (pow(10, nn));//化成小数
push(&n, f);
}
}
}
else if (yunsuanfu(ch[j]))//运算符处理
{
switch (compare(gettop(&p), ch[j]))
{
case '<'://小于,不能运算暂且先入栈
push(&p, ch[j]);
ch[j] = flag[i++];
break;
case '>'://大于,取出数字栈两个元素和运算符栈一个元素并调用law()函数进行运算
pop(&p, &c);
pop(&n, &b);
pop(&n, &a);
push(&n, law(a, b, c));
break;
case '='://相等的时候出栈字符再比较,指针后移
pop(&p, &c);
ch[j] =flag[i++];
break;
}
}
}
return(gettop(&n));//数字栈最后的元素就是计算结果
}
int main()
{
cout << "输入表达式求值" << endl;
char flag[maxsize];//读取字符串的数组
int ture = 1;
while (ture)
{
cout << "请输入表达式(=结束):";
cin >> flag;
cout << endl << "表达式的值为:" << calculate(flag)<< endl;//调用函数calculate()进行运算
cout << "按任意键继续......" << endl;
cin >> ture;
}
return 0;
}