用两种方式实现表达式自动计算
数据结构(双语)
——项目文档报告
用两种方式实现表达式自动计算
专
班
业: 计算机科学与技术
级:
指导教师:
姓
学
名:
号:
- 1 -
用两种方式实现表达式自动计算
目
录
一、设计思想……………………………………………………….03
二、算法流程图…………………………………………………….04
三、源代码………………………………………………………….06
四、运行结果……………………………………………………….18
五、遇到的问题及解决…………………………………………….18
六、心得体会……………………………………………………….19
- 2 -
用两种方式实现表达式自动计算
一、设计思想
本报告用两种算法分别对表达式进行计算:
一:将用户所输入的中缀表达式先变换成后缀表达式,然后在对后缀表达式进行计算。
二:将用户所输入的中缀表达式直接进行计算。
第一种算法:
这种算法又可分为两步:
第一步:将用户输入的中缀表达式先转换成后缀表达式:在这一步中,首先要
建立一个符号栈,和一个字符串数组,接着读用户输入的字符,如果用户输入的是
数字、+、—、*、/、%、(、)以外的字符,则程序报错。如果读到的是数字或小
数点,则直接放入字符串数组。如果读到的是符号,则与符号栈栈顶的元素的优先
级进行比较,如果当前读入的符号的优先级高,则直接入栈,如果当前符号的优先
级低于栈顶元素的优先级,那么将栈顶元素弹出,并将其放入字符串数组中,如果
读到的是左括号,则直接入栈,并将当前符号与栈中栈顶的下一个元素进行对比。
如果读到的是右括号,则观察栈顶元素,如果栈顶不为左括号或空,则将符号存入
字符串数组中,如果遇到左括号,则弹出左括号,如果栈为空,则结束。如此循环,
直到遇到’\0’结束,最终字符串数组中的表达式为后缀表达式。
第二步:对后缀表达式进行计算:在这一步中,首先要建立一个数值栈,对字
符串数组中的字符进行读取,当读取到数值时,将数值放入数值栈中,如果读到符
号,则将弹出栈中的两个数字进行计算,在将计算结果放入数值栈中,最后栈中留
下的结构就是表达式最后的结果。
第二种算法:
在此算法中要定义两个栈,一个叫数值栈,一个叫符号栈,将用户输入的字符
逐个进行扫描,如果用户输入的是数字、+、—、*、/、%、(、)以外的字符,则
程序报错。如果是数字或小数点,则放入数值栈中,如果是符号,则先将此符号的
优先级与符号栈的栈顶元素的优先级做比较,如果当前读到的符号的优先级比符号
栈栈顶元素的优先级高,则此符号入栈。如果此符号优先级低,则将栈顶元素出栈,
然后从数值栈中弹出两个元素,将这两个元素进行计算,计算结果继续压入到数值
栈中,而将当前读到的符号继续与符号栈中的下一个栈顶元素比较,如此循环,直
到符号栈中栈顶元素的优先级小于或等于当前符号的优先级,则将当前符号压入符
号栈中,如果读到的是左括号,则直接放入符号栈中,如果读到的是右括号,则从
符号栈中弹出一个符号,从数值栈中弹出两个数字,然后将计算结果放入数值栈中,
如此循环操作,如果遇到左括号,则停止,并释放左括号。接着读取下一个字符,
读取结束时,计算结果就放在数值栈中,从而将数值栈中的元素弹出即为所求结果。
- 3 -
存 在 错 误 并 结 束 程
序
二、算法流程图
第一个算法的流程图:
主函数的流程图:
返回计算结
果
用两种方式实现表达式自动计算
用户输入的中缀表达式
判断表达式中是否含有除数字、
+、—、*、/、%、(、)以外的字
符
调用函数将中缀表达式转换
成后缀表达式
调用函数通过后缀表
达式计算出结果
图 1 主函数流程图
中缀转化为后缀的流程图:
如果是数字
或小数点
读取用户输入的字符
并判断
如果是除括
号以外的操
作符
优先级高于
栈顶
与栈顶元素比较
入栈
优先级低于栈顶
栈 顶 元 素 出
栈 存 入 数 组
将 其 放 入 字 符 数 组
中,并在后面加上分
隔符
如果是括号
判断括号类型
如果是左括
如果是右括
号
号
直接入栈
放入数组中
从栈中取出操作符
- 4 -
用两种方式实现表达式自动计算
取出的不是左括号
图 2 中缀转化为后缀流程图
后缀表达式计算的流程图
后缀表达式
如果是数字
判断符号类型
如果是操作符
转化为浮点数入栈
从数值栈中取出两个数计算并将结果放入栈中
第二种算法的流程图
主函数的流程图:
返回计算结
果
返回最终数值栈中的结果
图 3 后缀表达式计算流程图
用户输入的中缀表达式
判断表达式中是否含有除数字、
+、—、*、/、%、(、)以外的字
符
调用直接计算的函数
图 4 主函数流程图
- 5 -
存 在 错 误 并 结 束 程
序
用两种方式实现表达式自动计算
直接计算函数的流程图:
得到中缀表达式
数字
从字符串中读取一个字
符并判断类型
转 化 为 浮 点 数 入
数值栈
左括号
直接入栈
括号
判 断 括 号 类
型
右括号
从栈中取出操作符
操作符
高于栈顶
直 接 入
栈
与符号栈的栈顶元
素做比较
低于栈顶
从相应栈中分别取出一个
操作符和两个操作数进行
计算,并将结果放入栈中,
并再次看栈顶元素
从 数 值 栈
中 取 出 两
个数,并
是
释 放 左
括号
判 断 是 否 为 左 括
号
不是
栈空
符 号 栈 是 否
为空
非空
取出数栈的两个数和符号栈的一个操
作符进行计算,并将结果放入数值栈
将 数
值 栈
顶
图 4 直接计算流程图
三、源代码
下面给出的是用中缀转后缀计算算法实现的程序的源代码:
#include
#include
#include
#include
/*导入需要用到的各种包*/
typedef struct
{
char op;
int level;
}OpNode;
/*定义结构体用来存储操作符*/
/*存储字符*/
/*存储优先级*/
- 6 -
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 top(stack *a)
{
if (a->size==0)
{
printf("stack is empty\n");
exit(-1);
}
return a->op[(a->top)-1];
}
typedef struct
{
double num[100];
int top;
int size;
} numstack;
void init2(numstack *st)
{
用两种方式实现表达式自动计算
/*表示栈内元素的个数*/
/*定义符号栈*/
/*初始化栈*/
/*出栈 */
/*如果栈为空结束操作*/
/*取出栈顶元素*/
/*入栈函数*/
/*观察栈顶函数*/
/*如果栈为空结束操作*/
/*只得到栈顶的值而不出栈*/
/*定义数值栈*/
/*栈顶指针*/
/*初始化数值栈*/
- 7 -
用两种方式实现表达式自动计算
st->size=0;
st->top=0;
}
double pop2(numstack *a)
{
if (a->size==0)
{
exit(-1);
}
a->size--;
return a->num[--(a->top)];
}
void push2(numstack *a,double num)
{
a->size++;
a->num[(a->top)++]=num;
}
void main()
{
/*数值栈出栈*/
/*出栈前的判空*/
/*得到栈顶的值*/
/*入栈*/
/*主函数*/
void change (char str[],char exp[]);
double CalResult(char exp[]);
/*声明要用到的各个函数*/
/*声明后缀表达式的计算函数*/
char str[100],exp[100];
printf("算术表达式为:\n");
/*str 存 储 原 算 术 表 达 式 , exp 存 储 对 应 的
后缀表达式,chestr 存储容错字符'^'*/
printf("算术表达式为:\n");
gets(str);
change(str,exp);
printf("后缀表达式为:%s\n",exp);
printf("运算结果为: %f\n",CalResult(exp));
int a;
scanf(&a);
/*调用函数将中缀转化为后缀*/
/*调用函数计算后缀表达式*/
}
void change (char str[],char ch[])
{
int i=0;
int k=0;
char c;
stack st;
OpNode op;
OpNode ops;
init(&st);
c=str[i++];
/*将前缀表达式转化为后缀表达式*/
/*str 的索引*/
/*字符串中取出的放在 C 中*/
/*定义符号栈*/
/*初始化符号栈*/
- 8 -