表达式求值进阶(浮点型)
本例主体思路还是:中缀表达式转后缀表达式
与我之前那篇表达式求值(整数基础版)相比,只是对数字做了些处理,将原来仅供整数的运算变为现在所有正实数的计算。
为了实现上述改变,需要做出以下改变(含规则介绍):
将数字栈中数字类型改为(双精度)浮点型
小数就需要增加对小数点的处理,分为两个部分
1)中缀表达式转后缀:
根据规则,这一步需要两个字符串和一个符号栈,第一个字符串是存从键盘输入的中缀表达式,如:” 1 + 2 * (2 - 1) = “ 的形式,处理时,遇到数字,则将该数字输出至第二个字符串(也就是即将形成的后缀表达式)中,如果遇到符号,则进栈按照优先级规则,确定出栈,出栈的符号进入上述第二个字符串中,承袭上面的例子:
求得中缀表达式" 1 + 2 * (2 - 1) = "的后缀表达式为:“1 2 2 1 - * +”
但是,这样做其实后缀字符串是这样存的:“1221-*+”,在接下来的后缀表达式运算中,我们无法知道第一个数字是1还是12还是122还是1221,因为它们连在一起了,为了防止这种情况的出现,我们在存放数字那一步,即第一个串中数字存放第二个串的时候,以特殊符号作为标记,以‘#’为例,可得上述后缀表达式"1#2#2#1#- * +"
ps: 另外,从字符串一读数的时候,判断数字的方法不是直接的,以中缀表达式“ 10 + 2 * (21 - 1) = ”为例,其实是一个字符一个字符处理的,对于10,先将1输入字符串二中,再把0输入,遇到‘+’后,再在字符串二补充一个‘#’,最后字符串二即为后缀表达式。
总结:这一步由中缀表达式得到了后缀表达式,主要用到了中缀表达式字符串和运算符栈
2)后缀表达式求值:
遍历后缀表达式,遇到数字就进数字栈,遇到符号,就从数字栈中连续出栈的两个数字,用后一个对前一个数字进行符号运算,运算值进入数字栈,直到后缀表达式遍历到末尾,那么数字栈栈顶元素即为所求。
ps: 这时后缀表达式中的数字是需要转换的,如“10#2#2#1#- * +”
第一个数字会读入"10"这个字符串,然后用atof()函数将其转化为双精度浮点型,’#‘作为数字隔板。
总结:这一步由后缀表达式求得值,用到了后缀表达式和数字栈。
代码如下:
/*
1. 中缀表达式 -> 后缀表达式
1>根据一个字符串,遍历字符串,数字存入另一个字符串,将运算符存入符号栈中
2>根据规则来依次输出结果于另一个字符串中
2. 后缀表达式 -> 求值
1>读取字符串,如果是数字则进入数字栈中,而符号直接用来参与运算
2>结束
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#define MaxSize 1010
using namespace std;
typedef struct
{
char *ch;
int top;
}CharStack;
typedef struct
{
double *num;
int top;
}NumStack;
CharStack S;
NumStack St;
void InitCharStack(CharStack &S);
void InitNumStack(NumStack &St);
void PushCharStack(CharStack &S, char c);
void PushNumStack(NumStack &St, double num);
char PopCharStack(CharStack &S);
double PopNumStack(NumStack &St);
char GetStackTop(CharStack &S);
bool PriorJudge(char c1, char c2);//priority优先级 judge判断
char *InfixToSuffex(char *a, char *b);//infix前缀 suffex后缀
double CaculatValue(char *b, NumStack &St);
int main()
{
InitCharStack(S);
char a[MaxSize] = {0};
char b[MaxSize] = {0};
printf("%s\n", InfixToSuffex(a, b));
double ans = CaculatValue(b, St);
printf("%f\n", ans);
return 0;
}
void InitCharStack(CharStack &S)
{
S.ch = (char *)malloc(MaxSize * sizeof(char));
if (S.ch == NULL)
{
cout << "内存分配失败!" << endl;
return;
}
S.top = -1;
return;
}
void PushCharStack(CharStack &S, char c)
{
if (S.top == MaxSize)
{
cout << "栈已满!" << endl;
return;
}
S.top ++;
* ++S.ch = c;
return;
}
char PopCharStack(CharStack &S)
{
if (S.top == -1)
{
cout << "栈为空!" << endl;
exit(1);
}
S.top --;
char c = *S.ch --;
return c;
}
char GetStackTop(CharStack &S)
{
char c = *S.ch;
return c;
}
bool PriorJudge(char c1, char c2)//priority优先级 judge判断
{
if (c1 == '*' || c1 == '/')
if (c2 == '+' || c2 == '-' || c2 == '(')
return true;
if (c1 == '+' || c1 == '-')
if (c2 == '(') return true;
return false;
}
char *InfixToSuffex(char *a, char *b)//infix中缀 suffex后缀
{
fgets(a, MaxSize-1, stdin);//从输入流中读取字符串
int t = strlen(a);
int k = 0;
// 12.25 + 25.02 / 2.36 + 8 * 2.01 =
for (int i = 0; i < t; ++ i)
{
if (a[i] >= '0' && a[i] <= '9')
{
b[k ++] = a[i];
if (a[i+1] == '.') b[k ++] = '.', ++ i;
else if (a[i+1] < '0' || a[i+1] > '9')
b[k ++] = '#';
}
else if (a[i] == ' ' || a[i] == '=') continue;
else
{
if(S.top == -1 || a[i] == '(')
PushCharStack(S, a[i]);
else if (a[i] == ')')
{
while (S.top != -1 && GetStackTop(S) != '(')
b[k ++] = PopCharStack(S);
if (S.top != -1) PopCharStack(S);
}
else
{
while (S.top != -1 && !PriorJudge(a[i], GetStackTop(S)))
b[k ++] = PopCharStack(S);
PushCharStack(S, a[i]);
}
}
}
b[k] = '\0';//这句话加不加应该无所谓,因为该字符数组已初始化为0
return b;
}
void InitNumStack(NumStack &St)
{
St.num = (double *)malloc(MaxSize * sizeof(double));
St.top = -1;
return;
}
void PushNumStack(NumStack &St, double n)
{
if (St.top == MaxSize)
{
cout << "栈已满!" << endl;
return;
}
St.top ++;
* ++St.num = n;
return;
}
double PopNumStack(NumStack &St)
{
if (St.top == -1)
{
cout << "栈为空2!" << endl;
exit(1);
}
St.top --;
double num = *St.num --;
return num;
}
double CaculatValue(char *b, NumStack &St)
{
InitNumStack(St);
int t = strlen(b);
char str[MaxSize] = {0};
for (int i = 0, k = 0; i < t; ++ i)
{
if (b[i] == '.' || (b[i] >= '0' && b[i] <= '9'))
{
str[k ++] = b[i];
if (b[i+1] == '#')
{
str[k] = '\0';
double num = atof(str);
PushNumStack(St, num);
k = 0;
}
}
else
{
if (b[i] == '#') continue;
double n = PopNumStack(St);
double m = PopNumStack(St);
if (b[i] == '+') PushNumStack(St, m + n);
else if (b[i] == '-') PushNumStack(St, m - n);
else if (b[i] == '*') PushNumStack(St, m * n);
else PushNumStack(St, m / n);
}
}
return PopNumStack(St);
}
运行结果:
感谢观看!如有错误还请指出。