题前需要了解的:中缀、后缀表达式是什么?(不知道你们知不知道,反正我当时不知道,搜的百度)

基本思路:先把输入的中缀表达式→后缀表达式→进行计算得出结果

栈:”先进先出,先进后出“!

  1. 中缀转后缀(先把转换后的后缀表达式存入字符数组):从左至右依次读取,遇到运算数存入字符数组,遇到运算符压入栈,继续读取–如果遇到的运算符优先级比栈顶的运算符优先级或者相等(比如“+与+或-” ----- “* 与 或/”------“/与/或”),则先将栈中的运算符输送至字符数组(如果栈中有“(”,则只输出到左括号就停止输出,不输出左括号),继续读取–如果遇到运算符优先级比栈顶运算符高的则入栈成为新的栈顶运算符,继续读取----如果遇到“)”,则将栈元素输出至字符数组,直至输出至”(“停止(在后缀表达式中没有括号,所以括号不输出入字符数组),直至读取完毕,然后将栈中剩余的运算符输出至字符数组。完毕!(注意:在遇到右括号”)“后就要将”(“左括号从栈中删除了,因为为防止将括号输出至字符数组)。

  2. 后缀表达式求值:从左至右读取,遇到运算数则将其存入栈中,遇到运算符(比如”/“)则将栈顶元素的前一个运算数(比如temp1)与栈顶元素(比如temp2)出栈(–注意–)并进行运算,temp1/temp2,并将其最终结果重新压入栈中成为新的栈顶元素,直至得出最终结果。


上代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 100
typedef float Num;//为防止以后变换操作数类型需要
typedef struct
{
Num data[MAX];
int top;
}StackNum;//运算数栈
typedef struct
{
char data[MAX];
int top;
}StackChar;//运算符栈
//------函数声明---------
void InitNum(StackNum *p);//运算数栈初始化
void PushNum(StackNum *p, Num e);//运算数压栈
void PopNum(StackNum *p, Num *e);//运算数出栈
Num GetNum(StackNum p);//取栈顶元素
//-----------------------
void InitChar(StackChar *p);//运算符栈初始化
void PushChar(StackChar *p, char e);//运算符压栈
void PopChar(StackChar *p, char *e);//运算符出栈
//-----------------------
void Fun(StackNum *p, char e);//计算并压入运算数栈
//-----------------------
void main()
{
int i;//循环变量
Num temp;//存放一个临时转换数
char str[MAX], ch;//存放中缀表达式原式,临时运算符
//-----------
StackNum n1;
StackChar c1;
InitNum(&n1);
InitChar(&c1);
//------------ for (;;)
{
printf("请输入中缀表达式:");
gets(str);
/*
注意字符串输入函数与scanf("%s",str) 的区别,scanf遇到空白字符,
包括空格,制表符,换行符时均会停止输入,所以不可取,而gets功能为读入一行,
并将换行符转换为字符串结束符。
*/
for (i = 0; str[i] != '\0'; i++)//读完整字符串-----字符串结束标志'\0'
{
if (str[i] >= '0'&&str[i] <= '9')//分岔点一:----------------------------------------------------------------如果为数字
{
temp = str[i] - '0';//-----将字符转换为数值 while (str[i + 1] != '\0')//多位数值获取
{
if (str[i + 1] >= '0'&&str[i + 1] <= '9')
{
temp = temp * 10 + str[i + 1] - '0';//------注意! i++;
}
else
break;//如果不是多位数字,则跳出多位获取循环
}
PushNum(&n1, temp);//将获取来的数值入栈
}
else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '(' || str[i] == ')')//分岔点二:-------如果为运算符
{
switch (str[i])//表达式可为:整型/字符型/枚举型-----C语言中
{
//case 后可为 整型,字符型----C语言中
case '+':
if (c1.data[c1.top - 1] != '+'&&c1.data[c1.top - 1] != '-'&&c1.data[c1.top - 1] != '*'&&c1.data[c1.top - 1] != '/')
{
PushChar(&c1, '+');
}
else//如果不然,则将之前的先都出栈并计算,然后再入栈
{
while (c1.top > 0 && c1.data[c1.top - 1] != '(')//将优先级高的运算符先输出计算,其中括号内的优先级最高
{
PopChar(&c1, &ch);
Fun(&n1, ch);//计算,并压运算数栈 }
PushChar(&c1,'+');
}
; break;
case '-':
if (c1.data[c1.top - 1] != '+'&&c1.data[c1.top - 1] != '-'&&c1.data[c1.top - 1] != '*'&&c1.data[c1.top - 1] != '/')
{
PushChar(&c1, '-');
}
else//如果不然,则将之前的先都出栈并计算,然后再入栈
{
while (c1.top > 0 && c1.data[c1.top - 1] != '(')//将优先级高的运算符先输出计算,其中括号内的优先级最高
{
PopChar(&c1, &ch);
Fun(&n1, ch);//计算,并压运算数栈 }
PushChar(&c1, '-');
}
; break;
case '*':
if (c1.data[c1.top - 1] != '*'&&c1.data[c1.top - 1] != '/')
{
PushChar(&c1, '*');
}
else//如果不然,则将之前的先都出栈并计算,然后再入栈
{
while (c1.top > 0 && c1.data[c1.top - 1] != '(')//将优先级高的运算符先输出计算,其中括号内的优先级最高
{
PopChar(&c1, &ch);
Fun(&n1, ch);//计算,并压运算数栈 }
PushChar(&c1, '*');
}
; break;
case '/':
if (c1.data[c1.top - 1] != '*'&&c1.data[c1.top - 1] != '/')
{
PushChar(&c1, '/');
}
else//如果不然,则将之前的先都出栈并计算,然后再入栈
{
while (c1.top > 0 && c1.data[c1.top - 1] != '(')//将优先级高的运算符先输出计算,其中括号内的优先级最高
{
PopChar(&c1, &ch);
Fun(&n1, ch);//计算,并压运算数栈 }
PushChar(&c1, '/');
}
; break;
case '(': PushChar(&c1, '('); ; break;
case ')'://并没有将'('压入栈中,只是当作一种出栈信号
while (c1.data[c1.top - 1] != '(')
{
PopChar(&c1, &ch);
Fun(&n1, ch);//计算,并压运算数栈
}
PopChar(&c1, &ch);//将'('也出栈,但并不计算
; break;
} }
}
while (c1.top > 0)//将剩余的运算符出栈并计算
{
PopChar(&c1, &ch);
Fun(&n1, ch);
}
printf("\t\t%s=%.2f", str, GetNum(n1));
printf("\n");
system("pause");
} }
void InitNum(StackNum *p)
{
p->top = 0;
}
void InitChar(StackChar *p)
{
p->top = 0;
}
void PushNum(StackNum *p, Num e)
{
if (p->top == MAX)
printf("运算数栈满!\n");
else
{
p->data[p->top] = e;
p->top++;
}
}
void PushChar(StackChar *p, char e)
{
if (p->top == MAX)
printf("运算符栈满!\n");
else
{
p->data[p->top] = e;
p->top++;
}
}
void PopNum(StackNum *p, Num *e)
{
if (p->top == 0)
printf("运算数栈空!\n");
else
{
p->top--;
*e = p->data[p->top];
}
}
void PopChar(StackChar *p, char *e)
{
if (p->top == 0)
printf("运算符栈空!\n");
else
{
p->top--;
*e = p->data[p->top];
}
}
void Fun(StackNum *p, char e)
{
Num temp1, temp2;//存放两个临时操作数
PopNum(p, &temp2);
PopNum(p, &temp1);
switch (e)
{
case '+':PushNum(p, temp1 + temp2); break;
case '-':PushNum(p, temp1 - temp2); break;
case '*':PushNum(p, temp1*temp2); break;
case '/':PushNum(p, temp1 / temp2); break; }
}
Num GetNum(StackNum p)
{
return p.data[p.top - 1];
}

因为我也是个小菜鸟,所以本次也全当作笔记总结的文章,我又找了两篇我参考的大佬的文章,如下:

原文:https://blog.csdn.net/myCsdn_Xm/article/details/80861183

后缀表达式的求值(c语言)

题目描述

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

输入

输入一行表示后缀表达式,数与数之间一定有空格隔开(可能不只一个空格),最后输入@表示输入结束。

数据保证每一步的计算结果均为不超过100000的整数。

输出

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

样例输入

14 3 20 5 / *8 - + @

样例输出

18

#include<stdio.h>

typedef struct STRACK                                              //定义结构体
{
double a[100];
int top;
} STRACK; int main()
{
double totle=0,e=0;
char s[100];
int i; STRACK L;
L.top=-1;
gets(s);
for(i=0; s[i]!='@'; i++)
{
if(s[i]<='9'&&s[i]>='0')
{
L.top++;
int temp=s[i]-'0';
int k=i+1;
while(s[k]!='@') //利用while循环得到由多位由字符组成的数值
{
if(s[k]<='9'&&s[k]>='0')
{
temp=10*temp+(s[k]-'0');
i++;
k++;
}
else break;
}
L.a[L.top]=temp;
}
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/') //遇到运算符进行计算
{
switch(s[i])
{
case '+':
e=L.a[L.top-1]+L.a[L.top];
break;
case '-':
e=L.a[L.top-1]-L.a[L.top];
break;
case '*':
e=L.a[L.top-1]*L.a[L.top];
break;
case '/':
e=L.a[L.top-1]/L.a[L.top];
break;
}
L.a[L.top-1]=e; //往前一位存储
L.a[L.top]=0;
L.top--;
}
}
printf("%.0lf",L.a[L.top]); //输出最后结果
return 0;
}

原文:https://blog.csdn.net/hanmiaobei7428/article/details/82049881

中缀表达式的求值问题

表达式的求值问题(堆栈)

0. 解决目标

将形如2*(9+6/3-5)+4表达式求值的思想

  1. 后缀表达式的求值

形如这里写图片描述的表达式如何求值?

(翻译成中缀表达式为:6/2-3+4*2,我们不进行中缀表达式的翻译操作,只是为了方便理解中间的过程)

从左向右“扫描”,逐个处理运算数和运算符号

遇到运算数怎么办?如何“记住”目前还不未参与运算的数?

遇到运算符号怎么办?对应的运算数是什么?



下图是一种解决办法。



这里使用一种结构,由于长得像先称之为“槽”,这种槽有什么特点?

1.只能存放数字

2.存放的数字只能后面进来的先出

这里有个问题,如果是符号怎么办呢?

我们提供一种解决办法,如果遇到符号,则将槽最顶部的数字与前一个数字从槽中拿出,进行操作,操作为:

1.前一个数字 运算符 槽最顶部的数字

2.并讲运算结果 再放入槽中

3.直至所有东西都按从左到右的顺序 尝试进入槽中,便得到结果。

这种能够解决后缀表达式的求值问题的结构——“槽”,就是堆栈。它是一种线性存储结构,后入先出。

我们用堆栈解决了后缀表达式的求值问题,那么问题来了,如何将中缀表达式转换成后缀表达式呢?

##2. 中缀化后缀

目标:将形如2*(6/3+4)-5的中缀表达式化成 2 6 3 / 4 + * 5 -的后缀表达式

带括号的表达式看起来比较复杂,我们先看没有括号的转换。

小目标:将形如2+9/3-5的中缀表达式化成2 9 3 / + 5 - 的后缀表达式

构造一种堆栈,只能存放符号,同样遵循后入先出的原则。

有两个问题

1.遇到数字怎么办?

2.堆栈中的符号怎么处理?

第一个问题很简单,输出即可,因为我们只需要求表达式,并不需要同时计算。

第二个问题,因为符号有优先级,当将符号放入堆栈时,比较其与前一个符号的优先级,若低于,则先输出前一个运算符。这个也很好理解,高优先级的运算先进行。

解决过程如下图所示。



那如果带括号要怎么解决呢?问题有:

1.括号也算一种符号,但括号不参与运算,

2.括号提供一种优先级,括号里面的运算优先级最高

第一个问题,我们在后缀表达式转换成值的时候是直接进行操作的,利用顺序已经将括号的功能包括进去,但只是不显示括号而已。具体解决是在一对括号齐全时,将其中的运算符输出。

第二个问题,我么将括号放入堆栈之前认为其优先级最高,在放入堆栈之后,将其认为优先级最低,即只进行括号里面的优先级比较(忽略括号)。

解决过程如下图。



总结中缀表达式转化成后缀表达式的方法如下:



按照 步骤2->1->0 完成目标


学习自《数据结构:陈越》之线性结构


呼,终于把最近看的,学的,总结起来了。。。

我如果有什么地方弄得不对的,看到的道友可以在下方评论说出来,或者私信我。

学习使我们快乐~

C语言中缀表达式求值(综合)的更多相关文章

  1. 刁肥宅详解中缀表达式求值问题:C++实现顺序/链栈解决

    1. 表达式的种类 如何将表达式翻译成能够正确求值的指令序列,是语言处理程序要解决的基本问题,作为栈的应用事例,下面介绍表达式的求值过程. 任何一个表达式都是由操作数(亦称运算对象).操作符(亦称运算 ...

  2. C语言实现表达式求值,支持+、-、*、/四则运算,并且支持多级括号,自定义了栈的操作。

    以下是代码的实现使用gcc已经成功运行了,下面是效果图 #include <stdio.h> #include <stdlib.h> #define OPT_ADD 43 /* ...

  3. 第四章 栈与队列(c4)栈应用:中缀表达式求值

  4. FZU2215 Simple Polynomial Problem(中缀表达求值)

    比赛时没做出这题太可惜了. 赛后才反应过来这就是个中缀表达式求值,数字栈存的不是数字而是多项式. 而且,中缀表达式求值很水的,几行就可以搞定. #include<cstdio> #incl ...

  5. C++之字符串表达式求值

    关于字符串表达式求值,应该是程序猿们机试或者面试时候常见问题之一,昨天参加国内某IT的机试,压轴便为此题,今天抽空对其进行了研究. 算术表达式中最常见的表示法形式有 中缀.前缀和 后缀表示法.中缀表示 ...

  6. 数据结构课程设计四则运算表达式求值(C语言版)

    本系统为四则运算表达式求值系统,用于带小括号的一定范围内正负数的四则运算标准(中缀)表达式的求值.注意事项:    1.请保证输入的四则表达式的合法性.输入的中缀表达式中只能含有英文符号"+ ...

  7. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  8. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  9. C/C++ 语言中的表达式求值(原文作者:裘宗燕)

    经常可以在一些讨论组里看到下面的提问:“谁知道下面C语句给n赋什么值?”m = 1; n = m+++m++;最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4, ...

随机推荐

  1. 代码质量管理sonarqube部署使用

    一.sonarqube的部署 1.下载sonaqube:https://www.sonarqube.org/downloads/ 根据需要下载特定版本: 2.如果通过sonar-scanner进行代码 ...

  2. [开发配置]Linux系统配置开发环境

    deeplin系统配置开发环境 开发系统:deeplin 15.11 开发工具:Clion 2019.2 ; PyCharm 2019 ; Idea 2019;  Android Studio 开源库 ...

  3. mysql中文乱码或者中文报错

    当出现中文乱码或者执行包含中文的语句报错时,十有八九就是编码的问题,我们可以执行下面语句查看编码: SHOW VARIABLES LIKE '%char%' 显示 其中character_set_se ...

  4. Sentry 企业级数据安全解决方案 - Relay 运行模式

    内容整理自官方开发文档 Relay 可以在几种主要模式之一下运行,如果您正在配置 Relay server 而不是使用默认设置,那么事先了解这些模式至关重要. 模式存储在配置文件中,该文件包含 rel ...

  5. Swoole 中毫秒定时器(Timer)的使用

    间隔定时器, tick 定时器会持续触发,直到调用 clear() 清除为止. $timer = Swoole\Timer::tick(3000, function (int $timer_id, $ ...

  6. Redis真的又小又快又持久吗

    一本正经 面试官:小伙子,谈谈对Redis的看法. 我:啊,看法呀,坐着看还是躺着看.Redis很小?很快?但很持久? 面试官:一本正经的说,我怀疑你在开车,不仅开开车还搞颜色. 我:... 面试官: ...

  7. 责任链模式(python)

    rom abc import ABCMeta, abstractmethod class Handler(metaclass=ABCMeta): @abstractmethod def handle_ ...

  8. Centos更换阿里云源

    1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...

  9. Linux上天之路(十)之Linux磁盘管理

    主要内容 磁盘介绍 磁盘管理 磁盘限额 逻辑卷管理 磁盘阵列 1. 磁盘介绍 硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等.每个盘片有两面,都可记录信息.盘片 ...

  10. C# 10分钟完成百度翻译(机器翻译)——入门篇

    我们之前基于百度ai开发平台实现了人脸识别 [1].文字识别 [2].语音识别 [3] 与合成的入门和进阶,今天我们来实现百度翻译的实现. 随着"一带一路"政策的开展,各种项目迎接 ...