C语言 栈的应用 计算简单的中缀表达式

news2024/9/20 10:30:09

代码简介:

下面的代码实现了计算简单的中缀表达式:只可以处理一位正整数的四则运算及括号。是栈的简单应用,要实现中缀表达式运算需要用两个栈,一个存储数字的栈和一个存储运算符的栈,因为懒得写两遍不同的栈上的操作,所以就用一个结构体实现了两个栈,用标志1表示操作其内部的栈1(int栈),标志2表示操作栈2(char栈),具体思路见代码。

完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100

typedef struct node *ptrNode;
typedef struct node
{
    int top1;
    int data1[MAXSIZE];

    int top2;
    char data2[MAXSIZE];
}stackNode;
typedef ptrNode stack_;

int empty_(stack_ st,int d)
{
    if(d==1 && st->top1 == -1)return 1;
    else if(d==2 && st->top2 == -1)return 1;
    return 0;
}
int full_(stack_ st,int d)
{
    if(d==1 && st->top1 == MAXSIZE-1)return 1;
    else if(d==2 && st->top2 == MAXSIZE-1)return 1;
    return 0;

}
void pop_(stack_ st,int d)
{
    if(d==1)
        st->top1--;
    else if(d==2)
        st->top2--;
}

void push_(stack_ st,int d,int data1,char data2)
{
    if(d==1)
        st->data1[++st->top1]=data1;
    else if(d==2)
        st->data2[++st->top2]=data2;
}
//显示栈顶
int top_num(stack_ st)
{
    return st->data1[st->top1];
}
char top_chr(stack_ st)
{
    return st->data2[st->top2];
}

stack_ init_stack()
{
    stack_ st = (stack_)malloc(sizeof(stack_) );
    st->top1  = -1;
    st->top2  = -1;
    return st;
}

int prior_chr(char c)
{
    if(c=='(')return 3;
    else if(strchr("*/",c))return 2;
    else if(strchr("+-",c))return 1;
}

int operate(char op,int a,int b)
{
    switch(op){
        case '+':return a+b;
        case '-':return a-b;
        case '*':return a*b;
        case '/':return a/b;
    }
}

int main()
{
    int out = 0;

    stack_ st = init_stack();
    char str[100];
    scanf("%s",&str);// \0结尾
    int don=0;

    while(str[don]!='\0')
    {
        if(str[don]-'0'>=0 && str[don]-'0'<10)//是数字,直接压栈
            push_(st,1,str[don]-'0','0');
        else if(str[don]==')')
        {   //一直出栈直到遇到左括号
            while( top_chr(st) != '(' )
            {
                char op = top_chr(st);
                pop_(st,2);
                int b   = top_num(st);
                pop_(st,1);
                int a   = top_num(st);
                pop_(st,1);
                out = operate(op,a,b);
                push_(st,1,out,'0');
            }
            pop_(st,2);//左括号出栈
        }
        else//是字符
        {
            int top_pro;
            if(!empty_(st,2))
                top_pro = prior_chr(top_chr(st));
            int now_pro = prior_chr(str[don]);

            if(empty_(st,2) || top_pro==3 ||top_pro<=now_pro)
                push_(st,2,0,str[don]);
            else //需要弹栈计算,暂时不压入
            {
                char op = top_chr(st);
                int b   = top_num(st);
                pop_(st,1);
                int a   = top_num(st);
                pop_(st,1);
                pop_(st,2);
                out = operate(op,a,b);
                push_(st,1,out,'0');
                don--;
            }
        }
        don++;
    }
    while(!empty_(st,2))
    {
        char op = top_chr(st);
        int b   = top_num(st);
        pop_(st,1);
        int a   = top_num(st);
        pop_(st,1);
        pop_(st,2);
        out = operate(op,a,b);
        push_(st,1,out,'0');
    }
    printf("out:%d\n",top_num(st));
    return 0;
}

代码解释:

如上,我图省事一个结构体放了两栈。

typedef struct node
{
int top1;
int data1[MAXSIZE];

int top2;
char data2[MAXSIZE];
}stackNode;

栈上有如下操作:

int empty_(stack_ st,int d) //判栈空,返回值为0表示栈非空,1表示栈空,参数 st表示该函数所操作的栈,参数d为1表示操作stack结构体中的int栈,2表示操作stack结构体中的char栈

int full_(stack_ st,int d) //判栈满,返回值为0表示栈非满,1表示栈满,参数含义与上相同

void push_(stack_ st,int d,int data1,char data2) //压数据入栈,参数st和d与上相同,data1表示待压入的int数据,data2表示待压入的char数据,由于d选择了操作哪一个栈,所以两个数据只有有效的那个会被压入,使用时不用的数据位随意填值就好(因为C语言没函数重载,写两个push又太麻烦所以就用这种方法了)

int top_num(stack_ st) //显示栈顶元素,该函数会返回int栈的栈顶元素
char top_chr(stack_ st)//显示栈顶元素,该函数会返回int栈的栈顶元素

另外说一下写这段代码我遇到的问题,需要注意的地方:一是在运算时(如下),需要获取两个数,在获取第一个数后需要弹栈,然后再获取第二个数(如代码第121行);

char op = top_chr(st);
int b = top_num(st);
pop_(st,1);
int a = top_num(st);
pop_(st,1);
pop_(st,2);
out = operate(op,a,b);
push_(st,1,out,'0');

二是在字符串处理完成后,还需要加个while循环处理栈,因为字符串处理完了但是栈中可能还存有数据没运算;三是代码第115行, top_pro==3 的意思是如果char栈的栈顶元素是(,那么不管是啥直接加进来就好了,这么处理的原因是当遇到(时,应该直接将其入栈,所以我给他设置了最高的优先级3(是唯一的,只有他有的优先级),而在其后要压操作入栈时,(后不管是啥都需要压入进来,所以这里特殊设置了一下,想不太明白的话自己写一个带括号的中缀表达式转换一下就好了。

if(empty_(st,2) || top_pro==3 ||top_pro<=now_pro)
push_(st,2,0,str[don]);

运行结果:

附几个运行结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

增益自适应PI控制器+死区过滤器(Smart PLC向导PID编程应用)

增益自适应和死区过滤器如果不和S7-200 SMART PLC PID向导组合实现,大家可以自行编写优化的PID指令。算法起始非常简单,具体实现过程大家可以参看下面的文章链接, 三菱增量式PID+死区过滤器 三菱PLC增量式PID算法FB(带死区设置和外部复位控制)_RXXW_Dor的博客-CSDN博客关于…

【论文简述】High-Resolution Optical Flow from 1D Attention and Correlation(ICCV 2021)

一、论文简述 1. 第一作者&#xff1a;Haofei Xu 2. 发表年份&#xff1a;2021 3. 发表期刊&#xff1a;ICCV 4. 关键词&#xff1a;光流、代价体、自注意力、高分辨率、GRU 5. 探索动机&#xff1a;小分辨率对于网络性能有影响&#xff0c;并且现实场景中大多为高分辨率的…

Minecraft 1.19.2 Fabric模组开发 04.动画效果方块

我们本次尝试在1.19 Fabric中制作一个具有动画效果的方块 效果演示效果演示效果演示 首先&#xff0c;请确保你的开发包中引入了geckolib依赖&#xff0c;相关教程请参考:Minecraft 1.19.2 Fabric模组开发 03.动画生物实体 1.首先我们要使用geckolib制作一个物品和对应的动画…

eCharts工具类

ECharts是一款基于JavaScript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。ECharts最初由百度团队开源&#xff0c;并于2018年初捐赠给Apache基金会&#xff0c;成为ASF孵化级项目。 ECharts官方地址…

【数据结构与算法】顺序表的原理及实现

1.什么是顺序表 顺序表是用一段物理地址连续的存储单元进行存储元素的线性结构&#xff0c;通常是以数组进行存储。通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。 2.顺序表的实现 判断顺序表是否为空表public boolean isEmpty()判断顺序表是否满publi…

excel功能小技巧:自动求和的注意事项

在EXCEL里有个非常方便的按钮&#xff0c;叫做自动求和。不需要输入公式&#xff0c;直接一点&#xff0c;即可得出求和结果。由于它操作上的便利&#xff0c;所以深受小白喜爱。不过看着简单的自动求和按钮&#xff0c;实际上却藏着不少暗坑&#xff0c;稍不留神&#xff0c;可…

juc系列(2)--线程的使用及原理

目录线程创建线程ThreadRunnableCallable线程方法APIrun startsleep yieldjoininterrupt打断线程打断 park终止模式daemon不推荐线程原理运行机制线程调度未来优化线程状态查看线程线程 创建线程 Thread Thread 创建线程方式&#xff1a;创建线程类&#xff0c;匿名内部类方…

R-P-Faster R-CNN day65 读论文:高分辨率遥感影像综合地理空间目标检测框架

An Efficient and Robust Integrated Geospatial Object Detection Framework for High Spatial Resolution Remote Sensing Imagery 1. Introduction3. Overview of the Proposed R-P-Faster R-CNN Framework3.1. 有效集成区域建议网络与目标检测Faster R-CNN框架3.1.2. RPN与…

java反射在spring ioc和aop中的应用

java反射在spring ioc和aop中的应用 反射&#xff1a; 1.反射是什么&#xff1f; 程序运行时&#xff0c;通过类名能够获得类的属性和方法。使用方式如下 Class clazz Class.ForName(“Student”)Class clazz Student.class;Class clazz student.getClass(); 获取到claz…

java JUC 中 Object里wait()、notify() 实现原理及实战讲解

1.Object中的wait()实现原理 在进行wait()之前&#xff0c;就代表着需要争夺Synchorized&#xff0c;而Synchronized代码块通过javap生成的字节码中包含monitorenter和monitorexit两个指令。 当在进加锁的时候会执行monitorenter指令&#xff0c;执行该指令可以获取对象的mon…

前端与HTML

本节课程围绕“前端要解决的基本问题”及“什么是 HTML ”两个基本问题展开&#xff0c;了解 HTML 高效的编写原则。 什么是前端 使用web技术栈解决多端的人机交互问题 技术栈 html&#xff08;内容&#xff09; css &#xff08;样式&#xff09;javascript &#xff08;行…

linux部署KubeSphere和k8s集群

上一篇文章讲述了在单个节点上安装 KubeSphere和k8s&#xff0c;这节主要讲解k8s多节点集群部署 准备环境&#xff1a;Alibaba Cloud Linux系统3台机器第一步&#xff1a;设置主机名称hostname--(3台机器都设置) hostnamectl set-hostname master hostnamectl set-hostname nod…

智云通CRM:为什么你总是在请客,但业绩却上不来?

王总是一位企业老板&#xff0c;社会资源比较好&#xff0c;在过去的一年里&#xff0c;他新代理的一个保健品的项目&#xff0c;需要销售产品和招募合伙人。他想利用自己的人脉资源做销售&#xff0c;但他的销售过程并不顺利&#xff0c;在连续主动邀约之后效果不佳。 于是他…

2023/1/15 JS-变量提升与函数提升 执行上下文

1 变量提升与函数提升 变量声明提升 通过 var 声明的变量&#xff0c;在声明语句之前就可以访问到 - 值: undefined <script>console.log(a); // undefinedvar a 10 </script>函数声明提升 通过 function 声明的函数, 在声明语句之前就可以直接调用 - 值: 函数…

走近软件生态系统

生态系统&#xff08;Ecosystem&#xff09;原本是一个生物学术语&#xff0c;意思是由一些生命体相互依存、相互制约而形成的大系统&#xff0c;就像我们学生时代在生物学课堂上学到的那样。隐喻无处不在&#xff0c;人们把这个术语移植到了 IT 领域中来&#xff0c;比如我们常…

计算机基础(六):静态链接与动态链接

上一篇文章简单概括了 C语言程序经过编译&#xff0c;生成汇编语言、机器语言的基本过程。今天主要介绍其中链接阶段的实现思路。 静态链接 静态链接是将被依赖的代码片段复制到执行程序中&#xff0c;进行代码整合。因为我们在汇编代码中看到的是具体的符号&#xff0c;而且…

电路方案分析(十七)TI远程声控参考设计

远程声控参考设计 描述 CC2650远程控制设计为基于ZigBeeRF4CE™兼容的软件架构RemeTI™或蓝牙低能耗软件堆栈的快速测试、评估和开发远程控制应用程序提供了最佳基础。 该方案设计包含了CC2560远程控制的原理图和布局文件&#xff0c;以及一个演示了使用RF4CE和低能耗蓝牙的…

层次分析法和熵值法经典实操案例+数据

1、数据来源&#xff1a;无 2、时间跨度&#xff1a;无 3、区域范围&#xff1a;无 4、指标说明&#xff1a; 层次分析法&#xff08;Analytic Hierarchy Process&#xff0c;简称AHP&#xff09;是美国运筹学家、匹兹堡大学T. L. Saaty教授在20世纪70年代初期提出的&#…

《Buildozer打包实战指南》第二节 安装Kivy和Buildozer

目录 2.1 安装Kivy 2.2 安装Buildozer 2.3 验证安装 2.4 一点建议 Python是Ubuntu系统中自带的&#xff0c;我们在桌面上右键打开终端&#xff0c;然后输入python3 --version就可以看到Ubuntu系统中的Python版本了。 可以看到&#xff0c;Python的版本是3.10.6。虽然Python…

【Go基础】结构体

1. 结构体引入 Golang也支持面向对象编程&#xff0c;但是和传统的面向对象有区别&#xff0c;并不是像Java、C那样纯粹的面向对象语言&#xff0c;而是通过特别的手段实现面向对象特点。 Golang没有类(Class)的概念&#xff0c;但是提供了结构体(struct)&#xff0c;和其他编…