*注:本人技术不咋的,就是拿代码出来和大家看看,代码漏洞百出,完全没有优化,主要看气质,是吧

学了数据结构——栈,当然少不了习题。习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和^,当然也可以带小括号)。搞了很久很久啊,终于搞出来的。简单说一下程序原理:

因为中缀表达式基本没法算(就算可以也肯定会超时),所以得把中缀表达式转为后缀表达式。

程序分为两步

第一步:将中缀表达式转为后缀表达式

创建一个字符串,比如叫get,用于存储后缀表达式

先是输入一个字符串,逐一读取单个字符,当是数字则直接存入get,如果是操作符则:

创建栈,比如叫chas

while循环 当栈顶操作符优先级大于或等于当前操作符则弹出并把栈顶元素赋值给get 直到发现优先级小于当前操作符的栈顶的操作符,小于当前操作符的那个栈顶操作符不弹出 然后将当前操作符压入栈内

当当前操作符为'('则直接压入栈内

当当前操作符为')'则while循环 弹出栈顶操作符并赋值给get直到弹出的是'(' ( '('只弹出不赋值 ) 注意,')'不压入栈中

第二部:计算get

创建int型数组栈,比如ints

逐个读入get

当读到数字压入ints

当读到操作符则弹出两个ints的栈顶元素,并进行相应计算,将计算得到的值压入栈ints中

最后读完get时,ints数组只剩下一个元素了,输出。

自个儿写的稀巴烂源码(c):

 #include <stdio.h>
#include <string.h>
#include <math.h> int ints[];
int intt;//ints的top
char chas[];
int chat;//chas的top
int i=, ii=;
char c;
char get[];//输入的中缀表达式
char get2[];//计算得出的后缀表达式 void intpush(x)//整型栈压栈
{
intt++; ints[intt]=x;
}
void chapush(x)//字符型栈压栈
{
chat++; chas[chat]=x;
}
int intpop()//整型栈弹出
{
intt--; return ints[intt+];
}
char chapop()//字符型栈弹出
{
chat--; return chas[chat+];
}
void intadd(int x)//整型栈栈顶元素加入新的个位数字
{
ints[intt]*=; ints[intt]+=x;
} int find()//get2加入操作符
{
c=chapop();
get2[ii]=' ';
get2[ii+]=c;
ii+=;
if(chat==) return ;
return ;
} int main()
{
intt=; chat=;
gets(get);
int lengets=strlen(get);
for(i=;i<=lengets-;i++)//逐个读取输入的中缀表达式
{
if (isdigit(get[i]))//当get[i]为数字时
{
get2[ii]=get[i];
ii++;
}
else
{
if(get[i]=='(')chapush('(');
if(get[i]=='^')chapush('^');
if(get[i]==')')
{
c=chapop();
while(c!='(')
{
get2[ii]=' ';
get2[ii+]=c;
ii+=;
c=chapop();
}
}
if(get[i]=='+')
{
while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
{
if(find()==)break;
}
chapush('+');
}
if(get[i]=='-')
{
while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
{
if(find()==)break;
}
chapush('-');
}
if(get[i]=='*')
{
while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
{
if(find()==)break;
}
chapush('*');
}
if(get[i]=='/')
{
while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
{
if(find()==)break;
}
chapush('/');
}
get2[ii]=' ';
ii++;
} }
while(chat>)//输出栈内剩余的操作符
{
int c=chapop();
get2[ii]=' ';
get2[ii+]=c;
ii+=;
}
get2[ii]='@';//加入结束符
i=;
while(get2[i]!='@')//当看到结束符停止计算
{
if(get2[i]=='+'||get2[i]=='-'||get2[i]=='*'||get2[i]=='/'||get2[i]=='^')
{
int a=intpop();int b=intpop();int c;
if(get2[i]=='+') c=a+b;
if(get2[i]=='-') c=b-a;
if(get2[i]=='*') c=a*b;
if(get2[i]=='/') c=b/a;
if(get2[i]=='^') c=pow(b,a);
intpush(c);
}
else
{
if(get2[i]!=' ')
{
intpush(get2[i]-);
ii=;
while(get2[i+ii]!=' ')
{
intadd(get2[i+ii]-);
ii++;
}
i+=ii-;
}
}
i++;
}
printf("%d",ints[]);
return ;
}

样例输入:

1+(3+2)*(7^2+6*9)/(2)

样例输出:

258

好了,就写到这了。(原题:信息学奥赛一本通C++版 数据结构 栈 上机练习4 calc)//别问我为什么C++的书的练习我写的是C,我不会告诉你是因为那样文件名可以少打两个p

对了,再说一下,其实这玩意完全没必要写这么长,最NB办法:

右键桌面:新建文本文件

双击打开新建文本文件.txt,输入如下脚本:

@echo off
set /p get=
set /a ans=%get%
echo %ans%
pause
exit::可以不要这句exit

右键新建文本文件,重命名为:calc.bat

双击打开

样例输入:

1+(3+2)*(7*7+6*9)/(2)

样例输出:

258

除了乘方没法算,别的都一样

呵呵,我不想多什么了……

最新更新(2016/7/4):新代码,同样的功能,更快的速度,更短的代码

#include <stdio.h>
#include <string.h>
#include <math.h>
char ops[101];
int opsi=0;
int ovs[101];
int ovsi=0;
void opsin(char c)
{
opsi++;
ops[opsi]=c;
}
void ovsin(int num)
{
ovsi++;
ovs[ovsi]=num;
}
char opsout()
{
opsi--;
return ops[opsi+1];
}
int ovsout()
{
ovsi--;
return ovs[ovsi+1];
}
void count2(char c)
{
int b=ovsout();
int a=ovsout();
switch(c)
{
case '+':ovsin(a+b);break;
case '-':ovsin(a-b);break;
case '*':ovsin(a*b);break;
case '/':ovsin(a/b);break;
case '^':ovsin(pow(a,b));break;
}
}
int count(const char *str)
{
ops[0]=0;
int stri=0,lenstr=strlen(str);
while(stri<=lenstr-1)
{
if(str[stri]=='(')opsin('(');
else
if(str[stri]=='^')opsin('^');
else
if(str[stri]==')')
{
char c=opsout();
while(c!='(')
{
count2(c);
c=opsout();
}
}
else
if(str[stri]=='+')
{
while(ops[opsi]=='+'||ops[opsi]=='-'||ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
opsin('+');
}
else
if(str[stri]=='-')
{
while(ops[opsi]=='+'||ops[opsi]=='-'||ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
opsin('-');
}
else
if(str[stri]=='*')
{
while(ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
opsin('*');
}
else
if(str[stri]=='/')
{
while(ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
opsin('/');
}
else//num
{
if(stri>0)
{
if(str[stri-1]-48>=0&&str[stri-1]-48<=9)
ovsin(ovsout()*10+str[stri]-48);
else
ovsin(str[stri]-48);
}
else
ovsin(str[stri]-48);
}
stri++;
}
while(ovsi>1)count2(opsout());
return ovs[1];
}
int main()
{
char s[101];
gets(s);
printf("%d",count(s));
return 0;
}

  

C语言数据结构之栈:中缀表达式的计算的更多相关文章

  1. 适用于实数范围的中缀表达式的 + - * / ( ) 计算(C++实现)

    核心算法: mid=FormatMid(mid); //格式化中缀表达式 JudgeLegalMid(mid); //判断中缀表达式的合法性 MidToPost mtp(mid); mtp.ToPos ...

  2. C++实现顺序栈类求解中缀表达式的计算

    控制台第一行打印的数值为使用形如以下方式得到的结果: cout << +*(+)*/- << endl; 即第一个待求解表达式由C++表达式计算所得结果,以用于与实现得出的结果 ...

  3. C语言数据结构之栈:括号匹配

    括号匹配这是个很简单的题目,如果只有小括号,就模拟进栈和出栈的过程就行了: 注:输入时'@'作为结束标志 #include <stdio.h> int main() { freopen(& ...

  4. C语言数据结构链栈(创建、入栈、出栈、取栈顶元素、遍历链栈中的元素)

    /**创建链栈*创建一个top指针代表head指针*采用链式存储结构*采用头插法创建链表*操作 创建 出栈 入栈 取栈顶元素*创建数据域的结构体*创建数据域的名称指针*使用随机函数对数据域的编号进行赋 ...

  5. Infix expressions 中缀表达式

    中缀表达式的计算 利用两个栈来实现,操作数栈,操作符栈 只支持个位数运算 最后必须输入一个'#' #include<iostream> using namespace std; templ ...

  6. Java堆栈的应用2----------中缀表达式转为后缀表达式的计算Java实现

    1.堆栈-Stack 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

  7. C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611

    09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...

  8. 栈的简单应用之中缀表达式转后缀表达式(C语言实现逆波兰式)

    一.前言   普通人在书写计算式时会选择中缀表达式,这样符合人脑的认知习惯.可计算机处理时后缀表达式才能使处理速度更快,其原因是利用堆栈结构减少计算机内存访问.同时它也是一个很好锻炼栈这个数据结构的应 ...

  9. Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算

    中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...

随机推荐

  1. Android进阶笔记07:Android之MVC 理解

     1. 为什么需要MVC ? 软件中最核心的,最基本的东西是什么?  答:是的,是数据.我们写的所有代码,都是围绕数据的.      围绕着数据的产生.修改等变化,出现了业务逻辑.      围绕着数 ...

  2. python(6)-logging 日志模块

    logging的日志分为5个级别分别为debug(), info(), warning(), error(), critical() 先来看一下简单的代码: logging.basicConfig(f ...

  3. java.lang.IllegalArgumentException: Service Intent must be explicit: Intent

    在Activity中启动Service的时候报错: 服务意图必须是显性声明. 这是为了防止造成冲突(i.e. 有多个Service用同样的intent-filter的情况) 这是Android 5.0 ...

  4. poj 3254 状态压缩DP

    思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k]: 这个方程得 ...

  5. poj 3207 2-SAT问题

    思路:将线段按开始点的升序排序,对线段尾节点进行判断,若存在交叉,那么这两条线段就不能同时在内或同时在外.这样将每条线段在内和在外看成两个状态i和i',i表示线段在内,i'表示线段在外.假使线段i和线 ...

  6. Java Concurrency - Callable & Future

    One of the advantages of the Executor framework is that you can run concurrent tasks that return a r ...

  7. Javascript之计时

    // <!DOCTYPE html> <meta http-equiv="Content-Type" content="text/html; chars ...

  8. html dom的加载

    操作HTML DOM文档的一个难题是,你的JavaScript代码可能在DOM完全载入之前运行,这会导致你的代码产生一些问题.页面加载时浏览器内部操作的顺序大致是这样的: 1. HTML被解析. 2. ...

  9. 如何设置win7任务栏的计算机快速启动

    win7默认会有一个资源管理器的快速启动栏,但是点击的时候会打开“库”,你可能一般不会用这个库,想打开计算机怎么办呢? 其实很简单,再按住shift的同时右键资源管理器的这个快速启动项,然后会出现菜单 ...

  10. 我的手机华为荣耀7,运行android程序不输出Log

    解决方法:1 进入手机拨号界面2 输入*#*#2846579#*#*3 输入完毕后自动跳转到<工程菜单>界面4 依次选择后台设置-->LOG设置-->在此可以看见一些列关于LO ...