栈的应用—— 表达式求值进阶(浮点型)

表达式求值进阶(浮点型)

本例主体思路还是:中缀表达式转后缀表达式

与我之前那篇表达式求值(整数基础版)相比,只是对数字做了些处理,将原来仅供整数的运算变为现在所有正实数的计算。

为了实现上述改变,需要做出以下改变(含规则介绍):

  1. 将数字栈中数字类型改为(双精度)浮点型

  2. 小数就需要增加对小数点的处理,分为两个部分

    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);
}

运行结果:
p1

感谢观看!如有错误还请指出。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值