问题 L: 后缀表达式求值

问题 L: 后缀表达式求值

题目描述
为了便于处理表达式,常常将普通表达式(称为中缀表示)转换为后缀{运算符在后,如X/Y写为XY/表达式。在这样的表示中可以不用括号即可确定求值的顺序,如:(P+Q)(R-S) → PQ+RS-。后缀表达式的处理过程如下:扫描后缀表达式,凡遇操作数则将之压进堆栈,遇运算符则从堆栈中弹出两个操作数进行该运算,将运算结果压栈,然后继续扫描,直到后缀表达式被扫描完毕为止,此时栈底元素即为该后缀表达式的值。

输入
输入一行表示后缀表达式,数与数之间一定有空格隔开(可能不只一个空格),最后输入@表示输入结束。
数据保证每一步的计算结果均为不超过100000的整数。

输出
输出一个整数,表示该表达式的值.

样例输入
14 3 20 5 / * 8 - + @

样例输出
18

解题过程

下面是对代码的详细解析:

  1. 头文件

    • 包含 <stdio.h> 头文件,提供输入输出函数。
  2. 结构体定义

    • STRACK 结构体用于模拟栈,包含一个数组 m 用于存储栈中的元素,以及一个整型变量 top 用于存储栈顶索引。
  3. 全局变量

    • num 用于存储运算结果的临时变量。
    • ch 用于存储输入的表达式字符串。
  4. 栈初始化

    • LengSTRACK 类型的变量,用作栈,初始化 top 为 -1,表示栈为空。
  5. 输入表达式

    • 使用 gets 函数读取一个以 @ 符号结尾的表达式。注意:gets 函数是不安全的,因为它可能导致缓冲区溢出。
  6. 解析和运算

    • 使用 for 循环遍历表达式字符串 ch
    • 如果当前字符是数字,则将其转换为数值,并使用 while 循环读取多位数值,存储到栈 Leng 中。
    • 如果当前字符是运算符,则从栈中取出顶部两个数值,执行相应的运算,并将结果存回栈中,同时减少栈顶索引。
  7. 输出结果

    • 使用 printf 函数输出栈顶元素,即表达式的计算结果。
  8. 程序结束

    • 返回 0,表示程序正常结束。

代码逻辑分析

  • 这段代码使用了一个栈来存储表达式中的数值部分,遇到运算符时,从栈中取出两个数值进行运算,并将结果压回栈中。
  • 它假设输入的表达式是有效的,并且运算符之后总是有数值。

潜在问题

  • 使用 gets 函数是不安全的,应该使用 fgets 函数代替。
  • 代码没有处理除以零的情况,这可能会导致运行时错误。

改进建议

  • 替换 gets 函数为 fgets,并添加对输入长度的检查。
  • 添加对除以零情况的检查,并给出错误提示。
  • 考虑增加对非法输入(如连续的运算符或不合法的字符)的检查。
  • 可以使用更现代的字符串处理函数,如 sscanf,来提高代码的可读性和健壮性。

二、部分代码

代码如下(定义结构体存储运算式):

typedef struct STRACK                                              //定义结构体
{
    double m[100];
    int top;
} STRACK;

代码如下(利用while循环得到由多位由字符组成的数值):

if(ch[i]<='9'&&ch[i]>='0')
        {
            Leng.top++;
            int temp=ch[i]-'0';
            int j=i+1;
            while(ch[j]!='@')                                          
            {
                if(ch[j]<='9'&&ch[j]>='0')
                {
                    temp=10*temp+(ch[j]-'0');
                    i++;
                    j++;
                }
                else break;
            }
            Leng.m[Leng.top]=temp;
        }

代码如下( 遇到运算符进行计算):

else  if(ch[i]=='+'||ch[i]=='-'||ch[i]=='*'||ch[i]=='/')     
        {
            switch(ch[i])
            {
            case '+':
                num=Leng.m[Leng.top-1]+Leng.m[Leng.top];
                break;
            case '-':
                num=Leng.m[Leng.top-1]-Leng.m[Leng.top];
                break;
            case '*':
                num=Leng.m[Leng.top-1]*Leng.m[Leng.top];
                break;
            case '/':
                num=Leng.m[Leng.top-1]/Leng.m[Leng.top];
                break;
            }
            Leng.m[Leng.top-1]=num;                                          //往前一位存储前一步得到的结果
            Leng.m[Leng.top]=0;
            Leng.top--;
        }

AC代码

#include<stdio.h>
 
typedef struct STRACK                                              //定义结构体
{
    double m[100];
    int top;
} STRACK;
//定义结构体存储运算式
int main()
{
    double num=0;
    char ch[100];
 
    STRACK Leng;
    Leng.top=-1;
    gets(ch);
    for(int i=0; ch[i]!='@'; i++)
    {
        if(ch[i]<='9'&&ch[i]>='0')
        {
            Leng.top++;
            int temp=ch[i]-'0';
            int j=i+1;
            while(ch[j]!='@')                                          //利用while循环得到由多位由字符组成的数值
            {
                if(ch[j]<='9'&&ch[j]>='0')
                {
                    temp=10*temp+(ch[j]-'0');
                    i++;
                    j++;
                }
                else break;
            }
            Leng.m[Leng.top]=temp;
        }
        else  if(ch[i]=='+'||ch[i]=='-'||ch[i]=='*'||ch[i]=='/')        //遇到运算符进行计算
        {
            switch(ch[i])
            {
            case '+':
                num=Leng.m[Leng.top-1]+Leng.m[Leng.top];
                break;
            case '-':
                num=Leng.m[Leng.top-1]-Leng.m[Leng.top];
                break;
            case '*':
                num=Leng.m[Leng.top-1]*Leng.m[Leng.top];
                break;
            case '/':
                num=Leng.m[Leng.top-1]/Leng.m[Leng.top];
                break;
            }
            Leng.m[Leng.top-1]=num;                                          //往前一位存储前一步得到的结果
            Leng.m[Leng.top]=0;
            Leng.top--;
        }
    }
    printf("%.0lf",Leng.m[Leng.top]);                                    //输出最后结果
    return 0;
}
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值