0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何利用栈去实现一种简单计算器

工程师邓生 来源:博客园 作者:pdudos 2022-09-19 10:32 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1. 中缀表达式 和 后缀表达式

中缀表达式: 顾名思义,操作符在操作数的中间,例如: 1 + 1

后缀表达式: 指操作符在操作后后面 ,例如 1 1 + , 就代表 中缀表达式 的 1 + 1

2. 关于数据结构: 栈

栈就是一个先进先出的队列

C语言函数之间调用,就是使用栈进行的

3. 中缀表达式 如何利用栈 转换为后缀表达式

利用栈转换规则如下

遍历中缀表达式

判断为数字直接输出

判断为(入栈

判断为)则,出栈 直至遇到(

判断为 * 或/

4.1 判断栈顶元素是否是 * 或/, 如果是 则出栈

4.2 若1不符合规则,再将这个字符入栈

5.1 判断栈顶元素是否是 * 或/,如果是,则全部出栈,然后再入栈

5.2 若1不符合,再将这个字符入栈

判断为+-,则

若表达式计算完毕,将出栈所有数据

实际例子

通过栈,将式子3+2(9+8)/3(3/5)转换为后缀表达式

开始式子:3+2*(9+8)/3*(3/5)

开始处理: 3
执行规则1,是数字直接输出

输出:3

:

开始处理: +
执行规则 5.2 直接入栈

输出:3

:+

开始处理: 2
执行规则1,是数字直接输出

输出:32

:+

开始处理: *
执行规则4.2,直接入栈

输出:32

:+*

开始处理: (
执行规则2,直接入栈

输出:32

:+*(

开始处理: 9
执行规则1,直接入栈

输出:329

:+*(

开始处理: +
执行规则5.2,直接入栈

输出:329

:+*(+

开始处理: 8
执行规则1,直接入栈

输出:3298

:+*(+

开始处理: )
执行规则3,出栈直至遇到 (

输出:3298+

:+*

开始处理: /
执行规则4.1,将栈顶元素为*或/直接出栈,然后在入栈该操作符

输出:3298+*

:+/

开始处理: 3
执行规则1,直接入栈

输出:3298+*3

:+/

开始处理: *
执行规则4.1,将栈顶元素为*或/直接出栈,然后在入栈该操作符

输出:3298+*3/

:+*

开始处理: (
执行规则2,直接入栈

输出:3298+*3/

:+*(

开始处理: 3
执行规则1,直接入栈

输出:3298+*3/3

:+*(

开始处理: /
执行规则4.2,入栈

输出:3298+*3/3

:+*(/

开始处理: 5
执行规则1,直接入栈

输出:3298+*3/35

:+*(/

开始处理: )
执行规则3,出栈 直至遇到(

输出:3298+*3/35/

:+*

开始处理: )
执行规则6,全部出栈

输出:3298+*3/35/*+

:

得到中缀表达式:3298+*3/35/*+

完毕

转换代码 C语言实现:

# include 

int main() {
    // 中缀表达式
    char formula[] = "3+2*(9+8)/3*(3/5)";

    // 栈
    char options[sizeof(formula) * sizeof(char)];
    int stackLen = -1;
    
    printf("%s
",formula);

    int i;
    for (i = 0; formula[i]!='�'; i++) {
        // 规则1
        if (formula[i] >= '0' && formula[i] <= '9') {
            printf("%c",formula[i]);
        }

        switch (formula[i]) {
            // 规则2
            case '(': {
                stackLen += 1;
                options[stackLen] =formula[i];
                break;
            }

            // 规则3
            case ')': {
                while (stackLen >= 0 &&  (options[stackLen] != '(')) {
                    printf("%c",options[stackLen]);
                    stackLen -= 1;
                }
                stackLen-=1;
                break;
            }

            // 规则4
            case '*':
            case '/': {
                while (stackLen >= 0 && (options[stackLen] == '*' || options[stackLen] == '/')) {
                    printf("%c",options[stackLen]);
                    stackLen -= 1;
                }
                stackLen += 1;
                options[stackLen] = formula[i];
                break;
            }

            // 规则5
            case '+': 
            case '-': {
                if (stackLen >= 0 &&  (options[stackLen] == '*' || options[stackLen] == '/')) {
                    while (stackLen >= 0) {
                        printf("%c",options[stackLen]);
                        stackLen -= 1;
                    }
                }
                stackLen += 1;
                options[stackLen] = formula[i];
                break;
            }
        }
    }

    // 规则6 
    while (stackLen >= 0) {
        printf("%c",options[stackLen]);
        stackLen--;
    }

    printf("
");
}

执行结果

# gcc calTest1.c
# ./a.out
3+2*(9+8)/3*(3/5)
3298+*3/35/*+
#

4. 利用栈 后缀表达式计算结果

利用栈计算后缀表达式规则如下

假设后缀表达式是有效的

遍历后缀表达式

判断为数字,则进行压栈

判断为操作符(+ - * /)

2.1 出栈2个元素,m 和 n (对于当前栈而言,m: 栈顶元素 n: 栈顶第二个元素)

2.2 计算 n操作符m ,然后将结果 入栈

实际例子

通过栈,将计算后缀表达式3298+*3/35/*+的值

式子:3298+*3/35/*+

开始处理: 3

执行规则1: 直接入栈

:3

开始处理: 2

执行规则1: 直接入栈

:3 2

开始处理: 9

执行规则1: 直接入栈

:3 2 9

开始处理: 8

执行规则1: 直接入栈

:3 2 9 8

开始处理: +

执行规则2: 取出2个元素,m:8 n:9, 并且执行结果(n + m)入栈

:3 2 17

开始处理: *

执行规则2: 取出2个元素,m:17 n:2, 并且执行结果(n * m)入栈

:3 34

开始处理: 3

执行规则1: 直接入栈

:3 34 3

开始处理: /

执行规则2: 取出2个元素,m:3 n:34, 并且执行结果(n / m)入栈

:3 11.3

开始处理: 3

执行规则1: 直接入栈

:3 11.3 3

开始处理: 5

执行规则1: 直接入栈

:3 11.3 3 5

开始处理: /

执行规则2: 取出2个元素,m:5 n:3, 并且执行结果(n / m)入栈

:3 11.3 0.6

开始处理: *

执行规则2: 取出2个元素,m:0.6 n:11.3, 并且执行结果(n * m)入栈

:3 6.8

开始处理: +

执行规则2: 取出2个元素,m:6.8 n:3, 并且执行结果(n + m)入栈

:9.8

计算结果:9.8

完成

用C实现该代码

转换代码 C语言实现:

# include 

int main() {
    // 后缀表达式
    char formula[] = "3298+*3/35/*+";

    // 栈
    float options[sizeof(formula) * sizeof(char)];
    int stackLen = -1;
    
    printf("%s
",formula);

    int i;
    for(i=0;formula[i]!='�';i++) {
        // 规则1
        if (formula[i] >= '0' && formula[i] <= '9') {
            stackLen++;
            options[stackLen] = (float)(formula[i]-48);
        } else {
            // 规则2
            float m = options[stackLen];
            stackLen--;

            float n = options[stackLen];
            stackLen--;

            switch (formula[i]) {
                case '*': {
                     stackLen++;
                     options[stackLen] = (n * m);
                     break;
                }
                case '/': {
                     stackLen++;
                     options[stackLen] = (n / m);
                     break;
                }
                case '+': {
                     stackLen++;
                     options[stackLen] = (n + m);
                     break;
                }
                case '-': {
                     stackLen++;
                     options[stackLen] = (n - m);
                     break;
                }
            }
        }
    }

    printf("
结果为: %.2f
" , options[0]);
}

执行结果

# ./a.out
3298+*3/35/*+

结果为: 9.80
#



审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144711
  • 计算器
    +关注

    关注

    16

    文章

    440

    浏览量

    38749

原文标题:利用栈实现计算器,实战挺好

文章出处:【微信号:技术让梦想更伟大,微信公众号:技术让梦想更伟大】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    使用TFTP实现IAP的方法

    使用 TFTP 实现 IAP 的方法广泛应用于需要具有固件升级功能的嵌入式应用中(例如,嵌入式 Linux bootloader 中)。TFTP 是一种在 UDP 传输层上执行的简单文件传输协议。此
    发表于 12-10 07:21

    用PLC实现卷径计算的两算法

    卷径计算,是动态计算如钢卷,纸卷等存料量的一种方法,它是实现张力控制和自动充放料、以及甩尾控制的重要前提。卷径计算目前主流的方法有两
    的头像 发表于 11-14 16:54 1453次阅读
    用PLC<b class='flag-5'>实现</b>卷径<b class='flag-5'>计算</b>的两<b class='flag-5'>种</b>算法

    如何利用Trace机制实现LLCP预览功能

    在蓝牙协议开发过程中,有时需要预先知道 LLCP。本文将介绍如何利用 Trace 机制实现 LLCP 预览功能。
    的头像 发表于 10-09 17:55 1578次阅读

    Quartz Frequency 实战:热力图+计算器(6 篇)

    AT-cut 面向对象:嵌入式/硬件/射频/物联网工程师 内容亮点:可视化图示 + 在线计算器 + 设计边界与案例 大家好!整理了套石英定时(Quartz Timing)高原创度文章与工具
    发表于 10-09 15:42

    Qorvo全新设计计算器:晶振选型、能耗预算计算器和链路预算与覆盖范围计算器

    款功能强大的PC端计算工具 。这些工具—— 晶振采购工具 、 能耗预算计算器 和 链路预算与覆盖范围计算器 ——让优化晶振选型、预测电池续航时间以及评估RF链路性能变得前所未有地简单
    的头像 发表于 06-24 17:51 1498次阅读
    Qorvo全新设计<b class='flag-5'>计算器</b>:晶振选型、能耗预算<b class='flag-5'>计算器</b>和链路预算与覆盖范围<b class='flag-5'>计算器</b>

    VirtualLab:衍射角计算器

    可以通过“开始”选项卡下的“计算器”下拉列表访问“衍射角计算器”。 设置输入参数 用户需要输入光栅周期、入射角、波长的值,并定义光栅前后的材料。入射波和反射级次位于第一种材料中,而透射级次于第二
    发表于 06-16 08:48

    一种新型激光雷达惯性视觉里程计系统介绍

    针对具有挑战性的光照条件和恶劣环境,本文提出了LIR-LIVO,这是一种轻量级且稳健的激光雷达-惯性-视觉里程计系统。通过采用诸如利用深度与激光雷达点云关联实现特征的均匀深度分布等先进技术,以及
    的头像 发表于 04-28 11:18 820次阅读
    <b class='flag-5'>一种</b>新型激光雷达惯性视觉里程计系统介绍

    蓝牙架构实现方案(蓝牙协议方案)

    蓝牙架构实现方案有哪几种?我们般把整个蓝牙实现方案叫做蓝牙协议,因此这个问题也可以这么阐述:蓝牙协议有哪些具体的架构方案?在蓝牙协议
    的头像 发表于 04-08 15:35 1249次阅读
    三<b class='flag-5'>种</b>蓝牙架构<b class='flag-5'>实现</b>方案(蓝牙协议<b class='flag-5'>栈</b>方案)

    VirtualLab Fusion应用:相干时间和相干长度计算器

    摘要 在本用例中,我们介绍了一种计算器,它可以根据给定光源的波谱信息快速估计其时间相干特性。然后,可以将该计算器的结果自动复制到通用探测中,以便在考虑时间相干性时应用近似方法,而无
    发表于 04-08 08:48

    VirtualLab:衍射角计算器

    可以通过“开始”选项卡下的“计算器”下拉列表访问“衍射角计算器”。 设置输入参数 用户需要输入光栅周期、入射角、波长的值,并定义光栅前后的材料。入射波和反射级次位于第一种材料中,而透射级次于第二
    发表于 04-08 08:46

    VirtualLab Fusion应用:光波导k域布局可视化(“神奇的圆环”)

    k域可视化:全内反射 k域可视化:FOV“盒子” k域可视化:k域中的RGB和FOV k域可视化:FOV“盒子”的运输 k域可视化:利用光栅耦合 使用k布局可视化计算器 VirtualLab
    发表于 02-21 08:53

    利用结构实现四则运算的巧妙方法

    上个视频写了个简易计算器,算个简单的加减乘除还行,但是如果来个混合运算,或者加个括号,这几行代码就差的太多了。 处理这种混合运算,不得不提到数据结构中的。 我们平时写的这种表达式,叫做中缀表达式
    的头像 发表于 02-07 11:06 993次阅读

    VirtualLab Fusion应用:相干时间和相干长度计算器

    摘要 在本用例中,我们介绍了一种计算器,它可以根据给定光源的波谱信息快速估计其时间相干特性。然后,可以将该计算器的结果自动复制到通用探测中,以便在考虑时间相干性时应用近似方法,而无需
    发表于 12-27 08:48

    Debye-Wolf积分计算器的用法

    即可进行计算。 该案例将说明如何在VirtualLab中使用Debye-Wolf积分计算器。 **建模任务 ** 开启Debye-Wolf积分计算器 •我们直接单击计算器,然后选择D
    发表于 12-26 08:59

    LP光纤模式计算器

    :渐变折射率 (GRIN) 光纤 光纤模式计算器允许定义线性偏振贝塞尔模式和线性偏振拉盖尔模式。 对于 GRIN 光纤,定义了梯度常数。 然后通过下式计算折射率 与前一种情况样,
    发表于 12-18 13:36