C语言后缀表达式计算
一、设计思想
计算算数表达式并求值,采取的共有两种方法:
先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。
对算数表达式进行直接的计算。
第一种算法
这种解决方案又分为两步:
1.将表达式先转化为后缀表达式的字符串数组
2.利用后缀表达式进行计算
在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式
然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。数组中存的就是后缀表达式。得到后缀表达式后,进行计算,要用到数值栈。首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。
第二种算发
首先要建立两个栈,一个用来存放操作符,一个用来存放数值。开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。扫描结束后,计算也结束了,计算的结果就存放在数值栈中,最后把数值栈中的数取出,就是所得的计算结果。
容错的算法简要:
括号匹配:当扫描到左括号是,左括号直接入栈,扫描到右括号时,则左括号出栈,如果栈为空,则右括号多,如果最后栈中还有括号,则左括号多。给出错误提示。
除数不为0:当扫描到'/'时,就判断其后面的数字是否为0,如果为0报错。
取余运算:取余运算时,操作数判断是否为整数,不为整数报错。
二、算法流程图
第一种算法:先将表达式转化为后缀表达式,然后计算
其主函数流程图为:
图1 主函数算法流程图
其中将中缀表达式转化为后缀表达式的主要流程为:
图2 中缀转化为后缀算法流程图
后缀表达式的计算,实现的流程图为:
图3 后缀表达式计算算法流程图
下面介绍直接计算出结果的算法的实现:
图4 直接计算中缀表达式算法流程图
三、源代码
下面给出的是用先转后缀再计算和直接计算的算法实现的程序的源代码:
#include /*导入需要用到的各种包*/
#include
#include
typedef struct /*定义结构体用来存储操作符*/
{
char op; /*存储字符*/
int level; /*存储优先级*/
}OpNode;
typedef struct
{
OpNode op[100];
int top;
int size; /*表示栈内元素的个数*/
} stack; /*定义符号栈*/
void init(stack *st) /*初始化栈*/
{
st->size=0;
st->top=0;
}
OpNode pop(stack *a) / *出栈*/
{
if (a->size==0) /*如果栈为空结束操作*/
{
exit(-1);
}
a->size--;
return a->op[--(a->top)]; /*取出栈顶元素*/
}
void push(stack *a,OpNode op) /*入栈函数*/
{
a->size++;
a->op[(a->top)++]=op;
}
OpNode