数据结构课程设计-用栈求表达式
c语言栈计算表达式

c语言栈计算表达式在计算机科学中,栈是一种非常重要的数据结构,被广泛应用于编译器、操作系统、网络通信等领域。
在本文中,我们将探讨如何使用C语言实现栈来计算表达式。
表达式是由操作数、操作符和括号组成的数学式子,例如:3 + 4 * 2 / (1 - 5)。
在计算表达式时,我们需要遵循一定的计算规则,如乘除法优先于加减法,括号内的计算优先于括号外的计算等。
我们可以使用栈来实现对表达式的计算。
具体步骤如下:1. 定义两个栈:一个操作数栈和一个操作符栈。
2. 从左到右遍历表达式的每一个字符,如果是数字则将其压入操作数栈;如果是操作符则将其压入操作符栈,并根据运算规则进行计算。
3. 在遍历完成后,操作符栈中可能还有未计算的操作符,需要继续计算,直到操作符栈为空。
4. 最终操作数栈中只剩下一个数,即为表达式的计算结果。
下面是一段示例代码,用于计算简单的表达式:```#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;} Stack;void initStack(Stack *s) {s->top = -1;}void push(Stack *s, int item) { if (s->top == MAX_SIZE - 1) { printf('Stack Overflow');exit(1);}s->data[++s->top] = item;}int pop(Stack *s) {if (s->top == -1) {printf('Stack Underflow');exit(1);}return s->data[s->top--];}int isEmpty(Stack *s) {return s->top == -1;}int isFull(Stack *s) {return s->top == MAX_SIZE - 1;}int peek(Stack *s) {return s->data[s->top];}int evaluate(char *expr) {Stack operandStack, operatorStack; initStack(&operandStack);initStack(&operatorStack);int i = 0;while (expr[i] != '0') {if (isdigit(expr[i])) {int num = 0;while (isdigit(expr[i])) {num = num * 10 + (expr[i] - '0'); i++;}push(&operandStack, num);}else if (expr[i] == '(') {push(&operatorStack, expr[i]);i++;}else if (expr[i] == ')') {while (!isEmpty(&operatorStack) && peek(&operatorStack) != '(') {int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result);}pop(&operatorStack);i++;}else if (expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/') {while (!isEmpty(&operatorStack) &&peek(&operatorStack) != '(' &&((expr[i] == '*' || expr[i] == '/') || (expr[i] == '+' || expr[i] == '-') &&(peek(&operatorStack) == '*' || peek(&operatorStack) == '/'))) {int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result); }push(&operatorStack, expr[i]); i++;}else {i++;}}while (!isEmpty(&operatorStack)) { int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result);}return pop(&operandStack);}int main() {char expr[MAX_SIZE];printf('Enter an expression: ');fgets(expr, MAX_SIZE, stdin);int result = evaluate(expr);printf('Result = %d', result);return 0;}```在这段代码中,我们定义了一个栈结构体,包含了栈的数据和栈顶指针。
数据结构课程设计报告-表达式求值

《数据结构》课程设计利用栈求表达式的值班级: 2学号: 100171021330姓名:吴迪指导老师:王方利用栈求表达式的值1、设计思路这个程序的关键是对数字与运算符的判断和运算符优先级的判断,以及出栈的运算。
建立两个栈,分别存储数字与运算符,栈1存运算符,栈2存数字。
依次读取表达式的字符串,先判断是数字还是运算符,如果是数字不能马上压入栈2,因为可能是大于10的数字,应该继续循环,如果还是数字,则利用计算保存数值,直到指到运算符时停止,将计算后的数字压入栈2。
压入运算符之前先将要压入的与栈顶的运算符优先级相比较,如果栈顶是‘(’而当前不是‘)’,则不需比较优先级,直接压入;如果栈顶是‘(’,当前是‘)’,则抵消(弹出‘(’,指向表达式下一个字符);若当前的运算符优先级大于栈顶的,则压入;若当前的运算符优先级小于栈內时,弹出栈顶的运算符,同时弹出两组数字,经过运算符的运算后再重新压到栈内。
为了方便判断运算结束,在存储运算符之前先将‘#’压入栈1中,在输入表达式时以‚#‛结束,所以可以以运算符==‘#’并且栈1顶==‘#’来结束运算,弹出栈2的数值,即为表达式求值的最终结果。
上述操作的算法步骤:(1)初始化算符S1,数字栈S2;,将‘#’压入算符栈S1中。
(2)读表达式字符=>w。
(3)当栈顶为‘#’并且w也是‘#’时结束;否则循环做下列步骤:(3-1)如果w是数字,存储到m,再经过计算存储到num中。
m=w-‘0’;num=num*pow(10,n)+m;n++;读下一个字符=>w,如果是运算符,则跳出循环;转3-2。
(3-2)w若是运算符,则:(3-2-1)如果栈顶为‘(’并且w为‘)’则‘(’出栈,读下一个字符=>w;转(3)。
(3-2-2)如果栈顶为‘(’或者栈顶优先级小于w优先级,则w入栈,读下一个字符=>w;转(3)。
否则:从算符栈中出栈,并从数字栈中弹出两组数字进行运算,将结果重新压入数字栈,转(3)。
利用栈求表达式的值,可供小学生作业,并能给出分数 数据结构课程设计说明书格式

中北年夜学之迟辟智美创作数据结构 课程设计说明书1. 设计任务概述(包括系统总体框图及功能描述)此课题是研究表达式求值的问题,以帮手小学生完成测试.为了到达这个功能,实际我们要做的就是出题,和计算分数给出评价的工作.整体设计都是以这个要求为轴心进行的.为了直观和方便,现画出软件整体设计模块图.2.计法式完胜利能;3. 功能模块详细设计在此说明每个部份的算法设计说明(可以是描述算法的流程图),每个法式中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的界说).3.1 详细设计思想学生要进行测试,首先要有试题.那么我们就要先建立试题库.这个试题库的试题是我们在法式运行过程中手动输入,寄存在一个shujuku.txt的文件中.首先在主函数中调用创立试题库函数,将试题存入到试题库文件shitiku.txt中,然后将该调用从主函数中删除.创立试题库函数:创立指向xuanti类型的指针,利用循环将输入的测试题该指针的xuanti单位中,最后将该指针中的测试题写入试题库文件shitiku.txt中.3.2 核心代码(正文宋体小四号字,1.5倍行距)#include <stdio.h>#include <stdlib.h>#include <time.h>#include<string.h>#include <conio.h>#define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define ERROR 0#define OK 1//界说表达式typedef struct shiti{char a[20];long result;}xuanti;typedef struct SqStack1{ //建立数字栈int *base;int *top;int stacksize;}SqStack1;typedef struct SqStack2{//建立运算符栈char *base;char *top;int stacksize;}SqStack2;void WriteToFile(xuanti *pstu,int num);void ReadFromFile(xuanti *pstu,int num);void page_title(char *menu_item){//建立菜单printf(">>> 数学习题库 <<<\n\n- %s -\n\n",menu_item); }void return_confirm(){printf("\n按任意键返回……\n");getch();}void IntInitStack(SqStack1 *S1){S1->base=(int *)malloc(STACK_INIT_SIZE*sizeof(int)); if(!S1->base)exit(ERROR);S1->top=S1->base;S1->stacksize=STACK_INIT_SIZE;}//IntInitStackvoid CharInitStack(SqStack2 *S2){S2->base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!S2->base)exit(ERROR);S2->top=S2->base;S2->stacksize=STACK_INIT_SIZE;}//CharInitStacklong IntGetTop(SqStack1 *S1){ //取栈顶元素long e1;if((*S1).top==(*S1).base)return 0;e1=*((*S1).top-1);return e1;}//IntGetTopchar CharGetTop(SqStack2 *S2){ //取栈顶元素char e2;if((*S2).top==(*S2).base) return 0;e2=*((*S2).top-1);return e2;}//IntGetTopint IntPush(SqStack1 *S1,int e1)*(*S1).top++=e1;return OK;}//IntPushint CharPush(SqStack2 *S2,char e2) {//入栈*(*S2).top++=e2;return OK;}//CharPushint IntPop(SqStack1 *S1){//出栈int e1;if((*S1).top==(*S1).base)return 0;e1=*--(*S1).top;return e1;}//IntPopint CharPop(SqStack2 *S2){//出栈char e2;if((*S2).top==(*S2).base) return 0; e2=*--(*S2).top;}//CharPopchar Precede(char a,char b){int i,j;char Table[8][8]={ ' ','+','-','*','/','(',')','#', '+','>','>','<','<','<','>','>','-','>','>','<','<','<','>','>','*','>','>','>','>','<','>','>','/','>','>','>','>','<','>','>','(','<','<','<','<','<','=',' ',')','>','>','>','>',' ','>','>','#','<','<','<','<','<',' ','=', }; //优先级表格for(i=0;i<8;i++)if(Table[0][i]==a) //纵坐标寻找 break;for(j=0;j<8;j++) //横坐标寻找 if(Table[j][0]==b)break;return Table[j][i];}//Precedeint Operate(int a,char theta,int b){ //计算表达式值:主要是将年夜的表达式转化成小的表达式进行逐步求值int c;if(theta=='+') c=a+b;else if(theta=='-') c=a-b;else if(theta=='*') c=a*b;else c=a/b;return c;}//Operateint IsOptr(char ch){char ptr[10]={'+','-','*','/','(',')','#'};for(int i=0;i<7;i++){if(ch==ptr[i])return true;}return false;}long result(char *a,SqStack1 *OPND,SqStack2 *OPTR){//求值char theta;int b,d,k=0,i=0,j=0,num2=0;IntInitStack(OPND);CharInitStack(OPTR);CharPush(OPTR,'#');while(a[i]!='='){if(!IsOptr(a[i])){k++;if(k<=j){num2=(int(a[i])-48);i++;}if(k>j){num2=num2*10+(int(a[i])-48); k=j=0;i++;}if(!IsOptr(a[i]))k++;if(k==j)IntPush(OPND,num2);}else if(IsOptr(a[i])){switch(Precede(a[i],CharGetTop(OPTR))) {case '<':CharPush(OPTR,a[i++]);if(a[i]!='('&&a[i]!=')')j++;break;case '=':CharPop(OPTR);i++;break;case '>':theta=CharPop(OPTR);d=IntPop(OPND);b=IntPop(OPND);IntPush(OPND,Operate(b,theta,d)); break;}//switch} //else if}//whileprintf("表达式的正确结果为:");printf("%d\n",IntGetTop(OPND));return (IntGetTop(OPND));}//reslutvoid Built_shitiKu(){int i,num;xuanti *pstu;printf("输入试题数目:\n");scanf("%d",&num);fflush(stdin);pstu=(xuanti *)malloc(num*sizeof(xuanti));//静态分配内存 if(pstu==NULL){printf("没有足够的内存空间!\n");return;}for(i=0;i<num;i++){//输入试题printf("第%d道试题:",i+1);gets(pstu[i].a);fflush(stdin);printf("\n");}WriteToFile(pstu,num);//将pstu所指向的学生信息写入文件中memset(pstu,0,num*sizeof(xuanti));//将pstu所指向的内存块清0ReadFromFile(pstu,num);//从文件中读取学生信息到pstu 所指向的内存块中printf("试题列表:\n");for(i=0;i<num;i++){//输入试题printf("第%d道试题:",i+1);printf("%s",pstu[i].a);printf("\n");}free(pstu);//释放静态分配的内存}void WriteToFile(xuanti *pstu,int num)FILE *fp;fp=fopen("shitiku.txt","at");if(fp==NULL){printf("不能创立shitiku.txt\n");free(pstu);exit(0);}fwrite(pstu,sizeof(xuanti),num,fp);fclose(fp);}void ReadFromFile(xuanti *pstu,int num){//从试题库中提取试题FILE *fp;fp=fopen("shitiku.txt","rt");if(fp==NULL){printf("不能翻开shitiku.txt\n");free(pstu);exit(0);}fread(pstu,sizeof(xuanti),num,fp);fclose(fp);}//****************************************** void RecMark(int *m,int num)FILE *mp;mp=fopen("markrec.txt","at");if(mp==NULL){printf("不能创立markrec.txt\n"); free(m);exit(0);}fwrite(m,sizeof(int),num,mp);fclose(mp);}//Recmarkvoid LookMark(int *m,int num){//检查得分记录FILE *mp;mp=fopen("markrec.txt","rt");if(mp==NULL){printf("不能翻开markrec.txt\n"); free(m);exit(0);}fread(m,sizeof(int),num,mp);fclose(mp);}//************************************* void RecN(int *m,int num)FILE *mp;mp=fopen("n_rec.txt","wt");if(mp==NULL){printf("不能创立n_rec.txt\n");free(m);exit(0);}fwrite(m,sizeof(int),num,mp);fclose(mp);}//Recmarkvoid LookN(int *m,int num){//检查m的值FILE *mp;mp=fopen("n_rec.txt","rt");if(mp==NULL){printf("不能翻开n_rec.txt\n");free(m);}fread(m,sizeof(int),num,mp);fclose(mp);}//************************************* int excersice_begin(){int i, j, temp, KEY[20];int mark,count=0;int *Mark;char g;SqStack1 s1,*OPND;SqStack2 s2,*OPTR;xuanti *XT;OPND=&s1;OPTR=&s2;Mark=(int *)malloc(20*sizeof(int));XT=(xuanti *)malloc(20*sizeof(xuanti));ReadFromFile(XT,20);do{srand((unsigned)time(NULL));KEY[0] = rand()%20;for(i=1;i<20;i++){while(1){temp = rand()%20;for(j=0;j<i;j++){if(KEY[j]==temp)break;}if(j==i){KEY[i]=temp;break;}}}system("cls");printf("随机的10个练习题 :\n");for(i=0;i<10;i++){printf("第%d个练习题:",i+1);printf("%s\n",XT[KEY[i]].a);printf("请输入计算结果:");scanf("%ld",&XT[KEY[i]].result);fflush(stdin);if(XT[KEY[i]].result==result(XT[KEY[i]].a,OPND,OPTR)) {mark+=10;printf("谜底正确!");printf("\n\n");}else{printf("谜底毛病!");printf("\n\n");}}printf("****得分情况****\n");printf("最后的得分为:%d\n",mark);if(mark>=90)printf("Very Good!\n");else if(mark>=60)printf("成果不错.\n");else printf("很遗憾成果不及格!\n");printf("\n");RecMark(Mark,count);Mark[count]=mark;count++;//记录次数递增printf("是否继续做练习?('y'—是,'n'—否):"); g=getchar();fflush(stdin);printf("\n");if(count>=20)//超越最年夜记录次数清0count=0;}while(g=='y');RecMark(Mark,count);return count;return_confirm();}void Look_Mark(int count){//printf("是否检查历史得分?('y'—是,'n'—否):");int *Mark;int i;Mark=(int *)malloc(20*sizeof(int));system("cls");printf("****查询历史得分情况****\n");LookMark(Mark,count);for(i=0;i<count;i++)printf("****第%d次得%d分****\n", i+1, Mark[i]);if(i>1){if(Mark[i-1]>60||Mark[i-2]>60){if(Mark[i-1]>Mark[i-2])printf("有进步,还要加油哦.\n");else if(Mark[i-1]==Mark[i-2]) printf("成果还可以,但没有进步,还要多多努力呀!\n");else printf("成果有点下降,要多多练习,不要气馁!!\n");}else printf("成果很欠好!要更加努力学习!\n");}else{if(Mark[0]>=90)printf("Very Good!\n");else if(Mark[0]>=60)printf("成果不错.\n");else printf("很遗憾成果不及格!\n"); }return_confirm();}void main(){int m=0;int *RN;char ch;RN=(int *)malloc(1*sizeof(int));RN[0]=0;printf("***如果是第一次运行***\n"); printf("**请先建立 n_rec.txt**\n");printf("*****否则会犯错 !*****\n"); printf("('y'--创立**'n'--不建)\n");ch=getchar();if(ch=='y')RecN(RN,1);LookN(RN,1);RN[0]+=m;fflush(stdin);printf("是否向试题库中添加试题: "); printf("('y'--是,'n'--否)?\n");ch=getchar();if(ch=='y')Built_shitiKu();menu: page_title("把持选单");printf("请用数字键选择把持\n\n"); printf("1 开始练习\n");printf("2 检查得分记录\n");printf("0 退出\n");printf("******************\n");RN[0]+=m;m=0;switch(getch()){case '1' : m=excersice_begin();break;case '2' : Look_Mark(RN[0]);break;case '0' : {RecN(RN,1);exit(0);}}system("cls");goto menu;}3.3法式运行结果(拷屏)4.课程设计心得、存在问题及解决方法连续两个星期的课程设计做完了,感觉自己的能力获得了年夜年夜的提高.刚开始看见题目的时候,很不以为然,觉得这么简单.但当自己开始着手做的时候才发现其实不是那么回事.一个看似简单的问题,有时候却牵扯甚多.经过两个星期的上机实践学习,使我对C语言有了更进一步的认识和了解,要想学好它要重在实践,要通过不竭的上机把持才华更好地学习它,通过实践,我也发现我的好多缺乏之处,对C语言学习平时只是马马虎虎的过去了,真正自己去解决实际问题的时候才会发现自己学的何等糟糕,通过课程设计对自己的编程能力也有所提高;再有对C语言的文件把持这一块,真的是难了我好久.还有对函数调用的正确使用不够熟悉,还有对C语言中经常呈现的毛病也不了解,通过实践,使我在这几个方面的认识有所提高.通过实践的学习,我认到学好计算机要重视实践把持,不单仅是学习C语言,还是其它的语言,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加注重实践把持能力的培养,无论学习什么,亲自入手去做了才华获得最深刻的体会.。
利用栈求表达式的值课程设计最后老师改 - 副本

课程设计课程名称数据结构题目名称利用栈求表达式的值专业班级2014级网络工程(1)班学生姓名学号指导教师二○一六年六月十五日蚌埠学院计算机科学与技术系课程设计任务书蚌埠学院计算机科学与技术系本科课程设计成绩评定表目录1 概述 (6)1.1题目要求 (6)1.2输入要求 (6)1.3输出要求 (6)1.4实现要求 (7)2.需求分析 (8)2.1要求 (8)2.2任务描述 (8)2.3运行环境 (9)2.4开发工具 (9)3.总体设计 (10)3.1设计任务与目标 (10)3.2程序中的功能函数: (10)3.3方案设计与论证 (11)4算法说明 (12)4.1主要功能函数 (12)4.2函数间的调用关系 (13)4.4数据结构设计 (16)5 程序运行 (18)6 总结 (27)参考文献 (29)程序源代码 (30)1 概述栈是计算机中常用的一种数据结构,具有广泛的使用。
利用栈的性质及其操作原理编写一个使用栈计算表达式的程序有助于更好的掌握栈的使用规则和原理应用。
《数据结构课程设计》是理解和掌握数据结构的重要环节,主要任务是实现各种数据组织中的数据逻辑结构、存储结构以及有关操作的算法。
使学生学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、存储结构及相应的算法。
另一方面,通过团队合作、文档编制、主页设计等环节对学生进行全方位的训练,最终达到培养学生的数据抽象能力和软件设计的能力。
通过全部过程培养和锻炼学生的钻研能力、动手能力、分析问题和解决问题的实际能力。
1.1题目要求(1)按照分析、设计、编码、调试、测试的软件过程完成这个应用程序。
(2)为各项操作功能设计一个菜单,应用程序运行后,先显示这个菜单,然后用户通过菜单项选择希望进行的操作项目。
1.2输入要求(1)应用程序运行后在屏幕上显示一个菜单。
用户可以根据需求,选定相应的操作项目。
进入每个操作后,根据应用程序的提示信息,从键盘输入相应的信息。
用栈将二叉树的表达式表示

用栈将二叉树的表达式表示栈是一种常见的数据结构,它具有先进后出的特点。
在二叉树的表达式中,我们可以利用栈的这一特性来实现表达式的计算和转换。
下面我将为大家详细介绍如何使用栈来表示二叉树的表达式。
让我们来看一个简单的二叉树表达式:1 + 2 * 3。
我们可以将这个表达式表示为二叉树的形式,其中加号(+)是根节点,数字1是左子树的叶子节点,而乘号(*)是右子树的根节点,数字2和3分别是右子树的左右子节点。
接下来,我们可以使用栈来进行二叉树的表达式转换。
具体步骤如下:1. 遍历表达式,从左到右逐个读取字符。
2. 如果当前字符是数字,则将其作为叶子节点插入到栈中。
3. 如果当前字符是运算符,则将其作为根节点插入到栈中,并将栈顶的两个节点作为其左右子节点。
4. 重复步骤2和3,直到遍历完整个表达式。
5. 最后,栈中只会剩下一个节点,即为整个二叉树的根节点。
通过上述步骤,我们就可以使用栈将二叉树的表达式表示出来。
接下来,让我们来看一个具体的例子:2 * (3 + 4)。
我们可以按照上述步骤来进行转换。
首先,读取到数字2,将其作为叶子节点插入栈中。
接着,读取到乘号(*),将其作为根节点插入栈中,并将栈顶的两个节点(数字2和左括号)作为其左右子节点。
然后,读取到左括号,将其作为叶子节点插入栈中。
接着,读取到数字3,将其作为叶子节点插入栈中。
再次,读取到加号(+),将其作为根节点插入栈中,并将栈顶的两个节点(数字3和左括号)作为其左右子节点。
最后,读取到数字4,将其作为叶子节点插入栈中。
完成遍历后,栈中只会剩下一个节点,即为整个二叉树的根节点。
通过上述例子,我们可以看到,使用栈将二叉树的表达式表示出来是非常方便和有效的。
通过栈的先进后出特性,我们可以准确地构建二叉树的结构,并且可以在需要的时候进行表达式的计算。
这种方法不仅简单易懂,而且可以适用于各种复杂的表达式。
希望通过以上的介绍,大家对使用栈来将二叉树的表达式表示有了更加深入的了解。
(完整word版)利用栈求表达式的值

数据结构课程设计姓名:王宗敏班级:软件1021111217班学号:1021111217目录:1.需求分析……………………………2.概要设计……………………………3.详细设计……………………………4.调试分析……………………………5.用户使用说明………………………6.测试结果……………………………利用栈求表达式的值,可供小学生作业,并能给出分数。
1.需求分析任务:通过此系统可以实现如下功能:此系统能够输入一个表达式,并计算该表达式的值。
可以根据计算结果给出分数。
能供小学生进行简单的四则运算,此外这里特别强调括号的匹配!要求:根据以上功能说明,设计运算信息,堆栈的存储结构,设计程序完成功能;2. 概要设计在此说明每个部分的算法设计说明(可以是描述算法的流程图),每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义)。
3.详细代码#include "string.h"#include ”stdio.h”#include”conio.h"#define maxsize 100#include ”ctype.h"typedef char datatype;typedef struct{datatype stack[maxsize];int top;} seqstack;void stackinitiate(seqstack *s){s—>top=0;}int stacknotempty(seqstack s){if(s.top<=0)return 0;else return 1;}int stackpush(seqstack *s,datatype x) {if(s->top>=maxsize){printf(”堆栈已满无法插入!\n");return 0;}else{s—>stack[s—〉top]=x;s->top++;return 1;}}int stackpop(seqstack *s,datatype *d){if(s->top<=0){printf("堆栈已空无数据元素出栈!\n");return 0;}else{s-〉top——;*d=s->stack[s—〉top];return 1;}}int stacktop(seqstack s,datatype *d){if(s。
栈的应用:表达式求值1

《数据结构课程设计实验一:表达式求值》实验报告一、简介要求设计一个表达式求值的程序。
该程序必须可以接受包含(,),+,-,*,/,%,和^(求幂运算符,a^b=a b)的中缀表达式,并求出结果。
如果表达式正确,则输出表达式的结果;如果表达式非法,则输出错误信息。
输入要求:程序从“input.txt”文件中读取信息,在这个文件中如果有多个中缀表达式,则每个表达式独占一行,程序的读取操作在文件的结尾处停止。
输出要求:对于每一个表达式,将其结果放在“output.txt”文件的每一行中。
这些结果可能是值(精确到小数点后两位),也可能是错误信息“ERROR IN INFIX NOTATION”。
输入例子:1+2+3-44.99+5.99+6.99*1.062^2.5^3(5.6-2)%35%(3.2-2.1)3.0.2+1输出例子:2.0018.3950535.16Error in infix notation.Error in infix notation.Error in infix notation.输入的表达式是由操作数和运算符以及改变运算顺序的圆括号连接而成的式子。
由于不同的运算符间存在优先级,同一优先级的运算间又存在着运算结合顺序的问题(即左结合,还是右结合),所以简单的从左到右计算是不充分的。
而后缀表达式(后缀表达式是由一系列的运算符、操作数组成,其中运算符位于两个操作数之后,如123*+)则很容易通过应用栈实现表达式的计算,所以,我们要先把中缀表达式转换成后缀表达式,再进行计算。
二、算法说明a、定义一个栈存放运算符,将中缀表达式转化为后缀表达式。
基本过程如下:如果遇到空格,则认为是分隔符,不需处理。
●如遇到操作数,则直接输出。
●若遇到左括号,则将其压入栈中。
●若是遇到右括号,表明括号的中缀表达式已经扫描完毕,把括号中的运算符退栈,并输出。
●若遇到是运算符,当该运算符的优先级别大于栈顶运算符的优先级别时,则将它压栈;当该运算符的优先级别小于栈顶运算符的优先级别时,则将栈顶运算符退栈并输出,再次比较新的栈顶运算符,按同样方法处理,直到该运算符大于栈顶运算符的优先级为止,然后将该运算符压栈。
用栈的方式实现表达式求值

一、程序设计任务掌握栈的用法,实现表达式求值这一栈的典型应用问题:以字符序列的形式从终端输入语法正确的、不含变量的算术表达式,利用算符优先关系,实现对算术四则混合运算表达式求值。
当用户输入一个合法的表达式后,能够返回正确的结果。
能够计算的运算符包括:加、减、乘、除、括号。
二、具体代码实现如下#include<iostream.h>#include<fstream.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<cstdio> //cstdio本来就只是将stdio.h的内容用C++的头文件形式表现出来。
#define NULL 0typedef struct node //定义一个结点结构体{char date;struct node *next;}SNode;SNode *InitStack()//初始化空链栈{SNode *top;top=new SNode;//top=(SNode *)malloc(sizeof(SNode));top->next=NULL;return top;}void PushOptr(SNode *top,char x)//运算符进栈函数{SNode *p;p=new SNode;p->date=x;p->next=top->next;top->next=p;}char PopOptr(SNode *top)//运算符出栈函数{SNode *p;char x;if(top==NULL)return NULL;p=top->next;x=p->date;top->next=p->next;delete p;return x;}void PushOpnd(SNode *top,char x)//操作数进栈函数{SNode *p;p=new SNode;p->date=x;p->next=top->next;top->next=p;}char PopOpnd(SNode *top)//操作数出栈函数{SNode *p;char x;if(top==NULL)return NULL;p=top->next;x=p->date;top->next=p->next;delete p;return x;}char GetTop(SNode *top)//取栈顶元素{return (top->next)->date;}int In(char c){int n;switch(c){case '+':case '-':case '*':case '/':case '(':case ')':case '%':case '^':case '#': n=1;break;default : n=0;break;}return n;}char Precede(char x,char y) //符号优先级规则说明{int i,j;int form[9][9]={{1,1,-1,-1,-1,1,-1,-1,1},{1,1,-1,-1,-1,1,-1,-1,1},{1,1,1,1,-1,1,1,-1,1},{1,1,1,1,-1,1,1,-1,1},{-1,-1,-1,-1,-1,0,-1,-1,2},{1,1,1,1,2,1,1,1,1},{1,1,1,1,-1,1,1,-1,1},{1,1,1,1,-1,1,1,1,1},{-1,-1,-1,-1,-1,2,-1,-1,0}}; //定义一个二维数组存放运算符优先级switch(x){case '+':i=0;break;case '-':i=1;break;case '*':i=2;break;case '/':i=3;break;case '(':i=4;break;case ')':i=5;break;case '%':i=6;break;case '^':i=7;break;case '#':i=8;break;}switch(y){case '+':j=0;break;case '-':j=1;break;case '*':j=2;break;case '/':j=3;break;case '(':j=4;break;case ')':j=5;break;case '%':j=6;break;case '^':j=7;break;case '#':j=8;break;}if(form[i][j]==1) //当form[i][j]==1时,说明运算符i的优先级高于运算符jreturn '>';elseif(form[i][j]==-1) //当form[i][j]==-1时,说明运算符i的优先级低于运算符jreturn '<';else //当form[i][j]等于其他值时,说明运算符i的优先级等于运算符jreturn '=';}int Operate(char x,char z,char y)//操作函数{int a=x-'0',b=y-'0';switch(z){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;case '%':return a%b;case '^': for(int i=1;i<b;i++) a*=a; return a;// cout<<pow(a,b);}}char Eval_Exp(char t[]) //获取运算结果{char temp[30];strcpy(temp,t);strcat(temp,"#");char a,b,c,r,f,z;int result,i=0;SNode *top[2];top[0]=InitStack(); //top[0]指向栈顶PushOptr(top[0],'#'); //将‘#’进入空运算符栈top[1]=InitStack();c=temp[i];while(c!='#'||(GetTop(top[0]))!='#')//输入符号不为‘#’或者栈顶元素不为‘#’时执行while语句{if(!In(c)) //如果当前输入不为运算符时执行if语句{PushOpnd(top[1],c); //将输入的元素放入操作数栈中c=temp[++i];}else{r=Precede(GetTop(top[0]),c); //获取符号优先级比较结果switch(r){case '<':PushOptr(top[0],c); //将当前输入的运算符进运算符栈中c=temp[++i];break;case '=':PopOptr(top[0]); //出当前运算符栈中的栈顶元素c=temp[++i];break;case '>':b=PopOptr(top[0]); //出当前运算符栈中的栈顶元素a=PopOpnd(top[1]); //出当前操作数栈中栈顶元素z=PopOpnd(top[1]); //出当前操作数栈中栈顶元素result=Operate(z,b,a); //计算结果f=result+'0';PushOpnd(top[1],f); //将运算结果进操作数栈中break;}}}return f; //返回运算结果}void main(){char infilename[40],outfilename[40],ch[30];fstream infile;fstream outfile;cout<<"请输入操作文件名路径: ";cin>>infilename;infile.open(infilename,ios::in|ios::nocreate);if(!infile){cout<<"不能打开文件:"<<infilename<<endl;exit(1);}cout<<"请输入结果文件名路径: ";cin>>outfilename;outfile.open(outfilename,ios::out);if(!outfile){cout<<"不能打开文件:"<<outfilename<<endl;exit(2);}while(infile.getline(ch,80))outfile<<Eval_Exp(ch)-'0'<<endl;infile.close();outfile.close();}三、运行输出结果实例输入表达式实例:2+5*(6-2)/2运行结果如下:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告学院、系:吉林大学珠海学院计算机科学与技术系专业:网络工程班级:十三班课程设计科目数据结构学生姓名:林艾鑫指导教师:余江完成时间:2010年10月-12月题目十三、利用栈求表达式的值一、设计任务与目标编写程序实现表达式求值,即验证某算术表达式的正确性,若正确,则计算该算术表达式的值。
主要功能描述如下:1、从键盘上输入表达式,以“=”号结束表达式。
2、分析该表达式是否合法:(1)是数字,则判断该数字的合法性。
若合法,则压入数据到堆栈中。
(2)是规定的运算符,则根据规则进行处理。
在处理过程中,将计算该表达式的值。
(3)若是其它字符,则返回错误信息。
3、若上述处理过程中没有发现错误,则认为该表达式合法,并打印处理结果。
附加功能:1.规定表达式的合法性2.小数计算3.计算记录的保存与查看4.(1)规定表达式的合法性,括号配对,不能出现“6++3”、“6+-3”等符号重叠的情况。
(2)表达式开头只能是数字或“(”,表达式中只能有一个“=”。
程序中应主要包含下面几个功能函数:void initstack():初始化堆栈int make_str():语法检查并计算int push_num(double num):将操作数压入堆栈char procede(char top,char code):处理操作码int change_opnd(int operate):将字符型操作码转换成优先级int change_opnd(char code):将操作码压入堆栈char pop_opnd(opnd *op):将操作码弹出堆栈int caculate(int cur_opnd):简单计算+,-,*,/double pop_num(num *nu):弹出操作数二、方案设计与论证1.定义一个expression全局表达式结构体expr[1000]存放计算过的表达式(expstr[MAXSIZE])和计算结果(result)、一个计量器(i)、一个表达式字符串、一个操作码栈和一个操作数栈;2.把表达式字符串从头到尾逐一扫描,将输入的表达式进行语法检查;3.第一个字符只能是数字或“(”,最重一个字符只能是“=”;4.表达式括号必须配对,中间不能出现“=”;5.在“(”前面只能是“+、-、*、/、( ”,在“+、-、*、/、=、)”前面只能是数字或“)”;6.把表达式字符串从头到尾逐一扫描,直到表达式扫描完毕,操作码栈为空;7.把字符根据运算优先级别选择操作;8.把表达式中的数值部分字符串转成数值压入操作数栈;9.是“(”直接压入到操作码栈,级别比操作码栈顶元素高的,把运算符压入操作码栈;10.级别比操作码栈低的,弹出操作码栈的栈顶元素和操作数栈的两个栈顶元素,进行运算后再压入操作数栈;11.是“)”,若操作码栈顶是“(”,把弹出操作码栈顶元素,否则“)”视为级别最低的元素,重复7;12.最后计算出结果并将其存放在expr[i],计量器加1;13.重复计算后,将结果保存在文件里,并统计计算次数;14.查看多次计算结果,以表形式输出;15.查看本次计算记录,以表形式输出;16.清除计算记录,重新计算。
三、算法说明(一)程序总共有如下函数:主要函数:void start(opnd *op,num *nu)//程序主菜单void start2(opnd *op,num *nu)//第二层计算选择,子菜单void load()//显示所有计算记录void save()//保存计算结果void check()//显示本次计算结果void result(opnd *op,num *nu)//计算结果double caculate(opnd *op,num *nu)//简单计算+,-,*,/表达式处理函数:int make_str()//语法检查double change_num(char str[])//数字字符串转成double型数字char procede(char top,char code)//处理操作码,判断栈的操作int change_opnd(char code)//字符型操作码转换优先级,非表达式字符返回-2 栈操作函数:double get_num(num *nu)//查看操作数栈栈顶double pop_num(num *nu)//操作数栈出栈int push_num(num *nu,double da)//压入操作数栈int empty_num(num *nu)//判空void initstack(num *nu)char get_opnd(opnd *op)//查看栈顶char pop_opnd(opnd *op)//出栈int push_opnd(opnd *op,char co)//压栈int empty_opnd(opnd *op)//判空void initstack(opnd *op)//初始化栈(二)函数间的调用关系:●main():主函数→start();↗load() →start();●start()程序模式函数→清空文件→exit();↘make_str()→result(op,nu)→start2()→start();↗load →start();●start2()子菜单→save() →start2();↘check() →start2();●result(op,nu)计算结果→initstack(op) →initstack(nu) →push_opnd(op,'=') →↗push_num(nu,change_num(str2));→change_opnd(*ps) ↗push_opnd(op,*ps);↘procede(get_opnd(op),*ps) →pop_opnd(op);↘push_num(nu,caculate(op,nu)) ●caculate(op,nu)→b=pop_num(nu) →a=pop_num(nu) →pop_opnd(op)✓main()函数:调用了一个函数start(),start()判断执行查看所有计算记录函数load(),或是清空以往的所有计算记录,或是退出程序,或是检查输入表达式语法make_str()并计算表达式result(op,nu)的操作。
✓result(op,nu)函数:是计算表达式,调用了初始化栈函数和字符级别判断change_opnd(*ps),若是数字,则调用转化数字change_num(str2)然后压入操作数栈,若是运算符,刚调用判断操作procede(get_opnd(op),*ps),若是“<”,则压入操作码栈push_opnd(op,*ps),若是“=”,则弹出操作码栈顶pop_opnd(op),若是“>”,则弹出操作码栈的栈顶元素和操作数栈的两个栈顶元素,进行运算caculate(op,nu)后再压入操作数栈,计算完毕后按start()顺序运行。
start2()函数:在计算结果后调用跟随的选择菜单,进行查看结果check()、保存结果save()、查看计算记录load()、回到主菜单的操作。
(三) 流程图:四、全部源程序清单#include <stdio.h> #include <stdlib.h> #include <string.h>#include <math.h> #define MAXSIZE 100#define N 1000int i=0;//表达式数struct expression//表达式结构 {long double result;char expstr[MAXSIZE];}expr[N];//表达式的一个整体容器stypedef struct//操作码栈定义{char code[MAXSIZE];int top;}opnd;typedef struct//操作数栈定义{double date[MAXSIZE];int top;}num;//《——opnd栈操作——》:void initstack(opnd *op)//初始化栈{op->top=-1;}int empty_opnd(opnd *op)//判空{if(op->top==-1)return 0;else return 1;}int push_opnd(opnd *op,char co)//压栈{if(op->top==MAXSIZE-1){printf("The \"opnd\" stack is full.");return 0;}op->top++;op->code[op->top]=co;return 1;}char pop_opnd(opnd *op)//出栈{char a='\0';if(op->top==-1){printf("error:The \"opnd\" stack is empty.");return a;}a=op->code[op->top];op->top--;return a;}char get_opnd(opnd *op)//查看栈顶{char a='\0';if(op->top==-1){printf("error:The \"opnd\" stack is empty.");return a;}elsereturn op->code[op->top];}//《——num栈操作——》:void initstack(num *nu){nu->top=-1;}int empty_num(num *nu)//判空{if(nu->top==-1)return 0;else return 1;}int push_num(num *nu,double da)//压栈{if(nu->top==MAXSIZE-1){printf("error:The \"date\" stack is full.");return 0;}nu->top++;nu->date[nu->top]=da;return 1;}double pop_num(num *nu)//出栈{double a='\0';if(nu->top==-1){printf("error:The \"date\" stack is empty.");return a;}a=nu->date[nu->top];nu->top--;return a;}double get_num(num *nu)//查看栈顶{if(nu->top!=-1)return nu->date[nu->top];}//《——结束栈定义操作——》//《——函数操作——》:int change_opnd(char code)//将字符型操作码转换成优先级,非表达式字符反回-2{switch(code){case '=':return 1;break;case ')':return 2;break;case '+':return 3;break;case '-':return 3;break;case '*':return 4;break;case '/':return 4;break;case '(':return 0;break;//操作码级别>=0;case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '0':case '.': return -1;//操作数级别=-1;default: return -2;//其它符号级别=-2 }}char procede(char top,char code)//处理操作码,判断栈的操作{if(change_opnd(code)==0)//“(”入栈return ('<');elseif(change_opnd(code)==2&&change_opnd(top)==0)//“(”和“)”同时出现,“(”出栈,“)”不入栈return ('=');elseif(change_opnd(code)<=change_opnd(top))//弹出两个数字和一个符号进行计算return ('>');elsereturn ('<');//入栈}double change_num(char str[])//数字字符串转成double型数字{char *s=str;int p=1,q=0;//p=小数点前位数,q=小数点后位数char d[]=".",z[]="0";double da=0;if(strstr(str,d)==0)//判断是否有小数点p=strlen(str);elseif(strstr(str,d)==str)//没有输入小数点前的数,如“.032”{p=1;q=strlen(str)-1;strcpy(str,strcat(z,str));}else{p=strstr(str,d)-str;q=strlen(str)-p-1;}for(int i=0;i<p;i++) //小数点前的各位数乘以各自的阶数,然后叠加:123=1*100+2*10+3*1da=da+((int)str[i]-48)*pow(10,p-i-1);for(int j=0;j<q;j++) //小数点后的各位数乘以各自的阶数,然后叠加:0.123=1*0.1+2*0.01+3*0.001da=da+((int)str[strlen(str)-1-j]-48)*pow(0.1,q-j);return da;}int make_str()//语法检查{char *p,*p1;int n=0;printf("\n请输入表达式,以“=”结尾:");gets(expr[i].expstr);p=expr[i].expstr;p1=p;while(1){if(*p=='\0')if(*(p-1)=='=')//语法检查结束break;else{//没有以"="结尾printf("\n表达式以\"=\"结尾。