【C语言】计算四则运算,中缀表达式转换为后缀表达式

news2025/1/20 18:25:25

C语言编程—中缀表达式转换为后缀表达式

思路:

中缀转后缀保存结果栈:stack,保存数据和+-*/
操作符栈:op_stack,保存+-*/()

场景一:遇到数据,直接入栈stack

场景二:遇到"("直接入栈op_stack,遇到")"将栈中左括号之后入栈的运算符全部出栈,输出到保存操作数的栈中stack,同时左括号出栈但丢弃。

场景三:遇到乘号和除号直接入栈op_stack,直到遇到优先级比他更低的运算符,依次出栈op_stack->入栈stack。

场景四:遇到加号和减号,如果此时op_stack栈空,则直接入栈,否则,将栈中优先级高的运算符依次弹栈(注意:加号和减号属于同一个优先级,所以也依次弹栈)直到栈空或则遇到左括号为止,停止弹栈。(因为左括号要匹配右括号时才弹出)。

场景五:扫描完字符串字符后,如果op_stack栈不为空,将op_stack栈中的操作符依次弹出->入栈stack。

例1:34*(23-(1+23)*4-324)中缀转后缀表达式

34*(23-(1+23)*4-324)对应的后缀表达式:suffix=34 23 1 23 + 4 * - 324 - *,计算结果:-13498

例2:34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34)) 中缀转后缀表达式

在例1的基础上加上*(23-32*(23-324)/(34+34))

34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))对应的后缀表达式:
suffix=34 23 1 23 + 4 * - 324 - 23 32 23 324 - 34 34 + / * - * * 

例3:34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))/(43-45*343)中缀转后缀表达式 

34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))/(43-45*343)中缀转后缀:
suffix=34 23 1 23 + 4 * - 324 - 23 32 23 324 - 34 34 + / * - 43 45 343 * - / * * 

C语言实现代码:待实现

/*
 * calculator.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define false    0
#define true     1

typedef int bool;

bool isOperator(char c)
{
    return (c == '+' || c == '-' || c == '*' || c == '/');
}

bool isOperand(char c)
{
    return (c >= '0' && c <= '9');
}

bool isValidExpression(char* exp, int len)
{
    int parenthesesCount = 0;
    for (int i = 0; i < len; i++)
    {
        if (isOperand(exp[i]))
        {
            while (i < len && isOperand(exp[i]))
            {
                i++;
            }
            i--;
        }
        else if(exp[i] == '.')
        {
            if(!isOperand(exp[i - 1]) || !isOperand(exp[i + 1])) return false;
        }
        else if (isOperator(exp[i]))
        {
            if (i == 0 || (i == len - 1)) return false;
            if ((!isOperand(exp[i - 1]) && exp[i - 1] != ')')
                    || (!isOperand(exp[i + 1]) && exp[i + 1] != '(')) return false;
        }
        else if (exp[i] == '(')
        {
            parenthesesCount++;
            if (i == len - 1) return false;
        }
        else if (exp[i] == ')')
        {
            parenthesesCount--;
            if (parenthesesCount < 0) return false;
        }
        else
        {
            return false;
        }
    }

    return parenthesesCount == 0;
}


double calculate(double num1, double num2, char op)
{
    switch(op)
    {
    case '+':
        return num1 + num2;
    case '-':
        return num1 - num2;
    case '*':
        return num1 * num2;
    case '/':
        return (num2 != 0) ? num1 / num2 : 0;
    }
    return 0;
}

int AdjustExpression(char *expIn, int len, char *expOut)
{
    int num = 0;
    for(int i = 0; i < len; i++)
    {
        if(strchr("+-*/()0123456789.", expIn[i])) expOut[num++] = expIn[i];
    }
    return num;
}

double CalcExpression(char *expression)
{
    int len = strlen(expression);
    char *exp = (char *)malloc(len * sizeof(char));
    memset(exp, 0x00, len * sizeof(char));
    len = AdjustExpression(expression, len, exp);
    if(!isValidExpression(exp, len)) return 0;
    char *operatorStack = (char *)malloc(len * sizeof(char));
    int operatorTop = -1;
    double *operand = (double *)malloc(len * sizeof(double));
    int operandTop = -1;
    for(int i = 0; i < len; i++)
    {
        if(isOperand(exp[i]))
        {
            double div = 1.0, num = 0;
            bool dot = false;
            while(i < len && strchr("0123456789.", exp[i]))
            {
                if(exp[i] == '.')
                {
                    dot = true;
                    i++;
                }
                div = dot ? div * 10 : div;
                num = num * 10 + exp[i] - '0';
                i++;
            }
            operand[++operandTop] = num / div;
            i--;
        }
        else if(exp[i] == '(')
        {
            operatorStack[++operatorTop] = exp[i];
        }
        else if(exp[i] == ')')
        {
            while(operatorTop >= 0 && operatorStack[operatorTop] != '(')
            {
                double num2 = operand[operandTop--];
                double num1 = operand[operandTop--];
                char operator = operatorStack[operatorTop--];
                operand[++operandTop] = calculate(num1, num2, operator);
            }
            if(operatorTop >= 0 && operatorStack[operatorTop] == '(') operatorTop--;
        }
        else if(strchr("+-", exp[i]))
        {
            while(operatorTop >= 0 && strchr("+-", operatorStack[operatorTop]))
            {
                double num2 = operand[operandTop--];
                double num1 = operand[operandTop--];
                char operator = operatorStack[operatorTop--];
                operand[++operandTop] = calculate(num1, num2, operator);
            }
            operatorStack[++operatorTop] = exp[i];
        }
        else if(strchr("*/", exp[i]))
        {
            while(operatorTop >= 0 && strchr("*/", operatorStack[operatorTop]))
            {
                double num2 = operand[operandTop--];
                double num1 = operand[operandTop--];
                char operator = operatorStack[operatorTop--];
                operand[++operandTop] = calculate(num1, num2, operator);
            }
            operatorStack[++operatorTop] = exp[i];
        }
    }
    while(operatorTop >= 0)
    {
        double num2 = operand[operandTop--];
        double num1 = operand[operandTop--];
        char operator = operatorStack[operatorTop--];
        operand[++operandTop] = calculate(num1, num2, operator);
    }
    double result = operand[operandTop];
    free(operatorStack);
    free(operand);
    free(exp);
    return result;
}

typedef struct TestCaseSetCalc{
    char    str[100];
    double  expValue;
}TestCaseSetCalc;

TestCaseSetCalc testcaseCalc[] = {
    {"1.0+1.0",2},
    {"1.0*1.0",1},
    {"1.1+1.2",2.3},
    {"((1.0+2.0)*3.0)",9},
    {"((1+2)*3)",9},
    {"((1+2)*(1-2))",-3},
    {"((1+2)*(1+2)/3)",3},
    {"1",1},
    {"(1)",1},
    {"1+1",2},
    {"(1+1)",2},
    {"(3+2)-5",0},
    {"(3+2)-(5+5)",-5},
    {"(3+2)*5",25},
    {"1*1",1},
    {"(1)*(1)",1},
    {"(1)*(1+1)",2},
    {"(1+(4+5+2)-3)+(6+8)",23},
};

void CalcExpression_test()
{
    int caseNum = sizeof(testcaseCalc) / sizeof(testcaseCalc[0]);
    int flag[100] = {0};
    for(int i =0; i < caseNum; i++)
    {
        double ret = CalcExpression(testcaseCalc[i].str);
        printf("CalcExpression ret %lf, exp %lf\n", ret, testcaseCalc[i].expValue);
        if(ret != testcaseCalc[i].expValue)
        {
            flag[i]++;
            printf("CalcExpression erro idx %d\n", i);
        }
    }
    printf("CalcExpression OK\n");
}

int main()
{
    CalcExpression_test();
    return 0;
}











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

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

相关文章

海康笔试题

1. 2. 块设备&#xff1a;磁盘设备驱动、SD设备驱动 字符设备&#xff1a;终端设备驱动 网络设备&#xff1a;网络设备驱动 &#xff08;1&#xff09;linux操作系统驱动程序分为三大类&#xff1a;字符设备驱动、快设备驱动和网络设备驱动 &#xff08;2&#xff09;字符设…

2024 年华数杯全国大学生数学建模竞赛C 题 老外游中国 完整思路 源代码 模型结果(仅供学习)

最近&#xff0c;“city 不 city”这一网络流行语在外国网红的推动下备受关注。随着我国过境免签政策的落实&#xff0c;越来越多外国游客来到中国&#xff0c;通过网络平台展示他们在华旅行的见闻&#xff0c;这不仅推动了中国旅游业的发展&#xff0c;更是在国际舞台上展现了…

基于X86+FPGA助力实现电力系统的智能监测与高效管理

电力监控 信迈提供基于Intel平台、Xilinx平台、Rockchip平台、NXP平台、飞腾平台的Mini-ITX主板、Micro-ATX主板、ATX主板、嵌入式准系统/工业整机等计算机硬件。产品算力强大&#xff0c;支持高速存储&#xff0c;提供丰富串口、USB、LAN、PCIe扩展接口、显示接口等I/O接口&am…

【python】数据类型之列表类型(上)

本篇文章将讲解列表类型。 列表&#xff08;list&#xff09;&#xff0c;是一个有序且可变的容器&#xff0c;在里面可以存放多个不同类型的元素。 列表中的元素之间用逗号&#xff08;英文中的逗号&#xff09;相隔。 1、定义&#xff1a; 例如&#xff1a; user_list[]…

stl容器 vector的基本操作

目录 1.vector构造 1.1默认构造函数 1.2 fill 填充构造函数 ​编辑 1.3 范围构造函数&#xff08;Range Constructor&#xff09; 1.4拷贝构造函数 2.initializer_list初始化vector 3.迭代器 4.常用的几个成员 4.1 size()统计当前有效字符个数 4.2 capacity ve…

青甘环线游记|day(2)|西宁、青海湖

坐动车 早上7:30醒来&#xff0c;在8:00左右起床&#xff0c;下楼吃兰州拉面。面煮的很好吃&#xff0c;就是还是不是很适应。看到8元的牛肉面感觉很震惊&#xff0c;没想到是面8元&#xff0c;牛肉另加&#xff0c;10元。 坐上动车前往西宁&#xff0c;12点左右到了。虽然在…

PXE实现自动安装部署操作系统

PXE&#xff08;Preboot eXecution Environment&#xff09;是一种在计算机启动时使用网络接口从远程服务器获取操作系统安装和启动信息的技术。通过PXE&#xff0c;计算机可以从局域网中的PXE服务器上下载操作系统安装文件&#xff0c;并进行自动化的操作系统部署或故障排除。…

25考研数据结构复习·7.4B树和B+树7.5散列(Hash)表

目录 B树和B树 B树 m阶B树的核心特性 B树的插入 B树的删除 非终端结点关键字 终端结点关键字 低于下限 B树 散列&#xff08;Hash&#xff09;表 基本概念 散列函数的构造 &#x1f469;‍&#x1f4bb; 除留余数法 直接定址法 数字分析法 平方取中法 处理冲突…

动手学深度学习V2每日笔记(池化层)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1EV411j7nX/spm_id_from333.999.0.0&vd_sourcec7bfc6ce0ea0cbe43aa288ba2713e56d 文档教程 https://zh-v2.d2l.ai/ 本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录&#xff0c;内容不会特别…

Linux基础环境开发工具(二)

目录 一、前言二、make和makefile工具1.快速认识一下2.依赖关系和依赖方法3.执行原理 三、Git工具1.快速认识一下2.git的使用 四、gdb工具1.快速认识一下2、类比Windows使用 一、前言 在开发工具第一篇中我们介绍了yum&#xff0c;vim&#xff0c;gcc/g编译器这几种工具&#…

C++ 继承 派生类的拷贝构造

继承 派生类的拷贝构造构造顺序拷贝构造 引例1: 当子类,不自实现拷贝构造时,默认调用父类的拷贝构造引例2: 子类自实现拷贝构造,不做特殊处理时,只会调用父类的构造器.引例3: 显示的调用父类的拷贝构造器。案例: 内嵌函数的拷贝构造 引例1 :当内嵌子对象,子类不自实现拷贝构造时…

Netty二

Netty 问题分析 bootstrap serverBootstrap pipeline和channelPipeline EventLoopGroup和实现类NioEventLoopGroup

U2net论文复现-简单解读-以及奇奇怪怪的改进-测试roc以及pr

论文地址&#xff1a;U2net论文地址 显著性目标检测&#xff1a; Salient ObjectDetetion(SOD)显著性目标检测&#xff0c;就是要把图片中最显著的物体分割出来&#xff0c;所以是二分类任务&#xff0c;只需要背景和前景。 1、Introduce 1.1、目前存在的2个挑战&#xff1…

Day-11 员工管理案例 增删改查、配置文件

SpringBootWeb案例 前面我们已经实现了员工信息的条件分页查询以及删除操作。 关于员工管理的功能&#xff0c;还有两个需要实现&#xff1a; 新增员工修改员工 首先我们先完成"新增员工"的功能开发&#xff0c;再完成"修改员工"的功能开发。而在"新…

Midjourney、Sora和硅谷机密-《分析模式》漫谈15

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的Preface&#xff08;前言&#xff09;有这么一句&#xff1a; Kent Beck, Ward Cunningham, and Jim Coplein encouraged me to get involved with the commu…

《Advanced RAG》-02-揭开 PDF 解析的神秘面纱

摘要 PDF 文件是非结构化文档的代表&#xff0c;但从 PDF 文档中提取信息是一个具有挑战性的过程。 PDF 文件由一系列指令组成&#xff0c;这些指令指示 PDF 阅读器或打印机在屏幕或纸张上显示符号的位置和方式。与 HTML 和 docx 等文件格式不同&#xff0c;后者使用标记来组织…

8月2日,贪心-买卖股票的最佳时期

大家好呀&#xff0c;今天我们看两道用贪心算法解的两道题&#xff0c;150道经典面试题中的买卖股票的最佳时期1和2。 1.买卖股票的最佳时期1 . - 力扣&#xff08;LeetCode&#xff09; 思路 对于这题&#xff0c;我们其实很容易想出暴力解&#xff0c;那就是从后往前找值&…

【文件系统】抽象磁盘的存储结构 CHS寻址法 | sector数组 | LAB数组

目录 1.为什么要抽象 2.逻辑抽象_版本1 2.1sector数组 ​2.2index转化CHS 3.逻辑抽象_版本2 3.1LBA数组 3.2LAB下标转化sector下标 文件其实就是在磁盘中占有几个扇区的问题❗文件是很多个sector的数组下标❗文件是有很多块构成的❗❗文件由很多扇区构成------>文件…

C语言刷题小记3

题目1 序列中删除指定数字 分析&#xff1a;本题要求我们来删除一个序列中指定的数字&#xff0c;这里大家要注意我们要删除的数字可能不止出现一次&#xff0c;所以我们需要用两个变量来进行处理&#xff0c;一个变量来遍历数组&#xff0c;一个变量来存储数组的位置&#xff…

H5 上使用腾讯位置服务选择收货信息

效果图 首先需要在腾讯位置服务上申请你自己的key&#xff0c;可参考地图选点组件 // 点击打开地图 backurl 是点击选中的位置点后&#xff0c;页面跳转至要返回的地址&#xff08;backurl&#xff09;&#xff0c;会将位置信息添加到回跳地址&#xff08;backurl&#xff0…