c语言用栈实现字符串字面量转换为后缀表达式并计算结果

观前提示!该代码只能实现个位数的后缀表达式转换以及加减乘除,而且对除法无法精确至小数点后,若表达式包含除法可能有极大误差,该代码只是个人一次简单尝试!

1、设计目的以及思路

本设计旨在通过个人熟悉的字符串字面量表达式转换为计算机熟悉的后缀表达式(逆波兰表达式)并进行求值,后缀表达式可以省略括号带来的优先级判断麻烦,数据结构使用栈

栈是一种先进后出的数据结构(FILO),这意味着最后放入的元素将被最先操作,栈只能从一端(栈顶)操作,类似于一个只有一个开口的盒子,定义如下:       

typedef struct stack
{
    char* data;
    int top;
}Stack;

其中包含一个数据项data与栈顶top,常用操作有压栈push出栈pop两种,我另外添加了遍历bianli函数用于检测栈的运行情况

运算符的优先级用自定义函数precedence判断

后缀表达式利用栈的压栈出栈进行数据运算得出,转换具体步骤如下(从左至右):

        1.遇到数字直接输出        

        2.遇到右括号'('直接压栈        

        3.遇到符号,先判断优先级,若优先级小于栈顶符号则不断出栈直至大于等于栈顶符号,然后压栈

        4.到达最右端后出栈所有符号

逆波兰表达式示例

  • 中缀表达式:3 + 4

  • 逆波兰表达式:3 4 +

  • 中缀表达式:(3 + 4) × 5

  • 逆波兰表达式:3 4 + 5 ×

  • 中缀表达式:3 + (4 × 5)

  • 逆波兰表达式:3 4 5 × +

后缀表达式由于只做了个位数的运算没有额外设计整数类型的栈来运算,而是根据核心思路设计了一个简易计算步骤:

        1.将逆波兰表达式第一个数字赋值给result

        2.每遇到一个符号将它前面的数字与result累计运算

        3.循环结束输出结果

2、代码与结果

以下是完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义栈大小为100
#define SIZE 100

//定义一个栈的结构体
typedef struct stack
{
    char* data;
    int top;
}Stack;

//初始化
void init(Stack* s)
{
    s->data=malloc(sizeof(char)*SIZE);
    s->top=-1;
}
//压栈
void push(Stack* s,char n)
{
    if(s->top==SIZE-1)
    {
        printf("栈已满\n");
    }
    else
    {
        s->top++;
        s->data[s->top]=n;
    }
}
//出栈,返回值类型为int以便于后缀表达式的运算
int pop(Stack* s)
{
    int i;
    if(s->top==-1)
    {
        printf("栈为空\n");
    }
    else
    {
        i=s->data[s->top]-48;
        s->top--;
    }
    return i;
}
//遍历
void bianli(Stack* s)
{
    if(s->top==-1)
    {
        printf("栈为空\n");
    }
    else
    {
        int i=0;
        while(i<=s->top)
        {
            printf("%c->",s->data[i]);
            i++;
        } 
        printf("\n");
    }
}
//栈的析构函数
void my_free(Stack* s)
{
    free(s->data);
    free(s);
}
//优先级判断函数
int precedence(char op) 
{
    switch (op)
    {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0;
    }
}

char* InfixToPostfix(char* str,Stack* s)
{
    //初始化栈避免脏内存
    init(s);
    //测量字符串长度
    int len=strlen(str);
    //设置缓冲区buf来存后缀表达式,长度设为前缀表达式长度,动态分配内存
    char* buf=(char*)malloc(sizeof(char)*(len+1));
    //index来控制buf的读入
    int index=0;
    for(int i=0;i<len;i++)
    {
        //如果为数字就直接输出
        if(str[i]>='0'&&str[i]<='9')
        {
            buf[index++]=str[i];
        }
        //遇到)直接出栈出到(为止,(直接出栈而不输出
        else if(str[i]==')')
        {
            while(s->data[s->top]!='(')
            {
                buf[index++]=s->data[s->top];
                pop(s);
            }
            pop(s);
        }
        else if(str[i]=='(')
        {
            push(s,str[i]);
        }
        //如果是符号则比较优先级,栈顶的优先级如果大于当前符号则出栈,比较到栈顶优先级低于或等于当前符号为止
        else if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/')
        {
            if(s->top!=-1&&precedence(s->data[s->top])>=precedence(str[i]))
            {
                buf[index++]=s->data[s->top];
                pop(s);
            }
            push(s,str[i]);
        }
    }
    //剩余操作符全部出栈
    while(s->top!=-1)
    {
        buf[index++]=s->data[s->top];
        pop(s);
    }
    buf[index]='\0';
    return buf;
}
//后缀表达式运算
void OperationPostfix(char* str,Stack* s)
{
    //初始化s
    init(s);
    int len=strlen(str);
    int result=str[0]-48;
    for(int i=1;i<len;i++)
    {
        if(str[i]>='0'&&str[i]<='9')
        {
            push(s,str[i]);
        }
        else
        {
            switch(str[i])
            {
                case '+':
                    result+=pop(s);
                    break;
                case '-':
                    result-=pop(s);
                    break;
                case '*':
                    result*=pop(s);
                    break;
                case '/':
                    result/=pop(s);
                    break;
            }
        }
    }
    printf("%d\n",result);
}

int main(int argc,char* argv[])
{
    //定义并初始化一个操作栈
    Stack* stack=malloc(sizeof(Stack));
    init(stack);

    char* string=argv[1];
    char* post_string=InfixToPostfix(string,stack);
    printf("%s\n",post_string);
    OperationPostfix(post_string,stack);

    //释放在InfixToPostfix中动态分配的内存
    free(post_string);
    //释放栈中动态分配的内存
    my_free(stack);
    return 0;
}

编译并运行:(程序名为RPN.c,可运行文件为a.out)

主函数第二个参数输入一个字符串字面量即可得到它的逆波兰表达式与运算结果

3、感谢观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值