数据结构 课程设计(表达式计算)
- 格式:doc
- 大小:356.00 KB
- 文档页数:18
高级语言程序设计《算术表达式求值》课程设计报告算术表达式求值系统可以实现实现对算术四则混合运算表达式求值,并打印求值过程中运算符栈、操作数栈的变化过程。
第二章系统分析开始运行时界面如下:你可以输入一个表达式,按E对其进行求值。
#include <stdio.h>#include <conio.h>#include <stdlib.h>#include <string.h>#define N 100double numStack[N]={0};//操作数栈int numTop;char opStack[N];//运算符栈int opTop;void print_num(double str1[],int n) {int i;printf("\n操作数栈:\n");for(i=0;i<n;i++)printf("%g ",str1[i]);}void print_op(char str2[],int m) {int j;printf("\n运算符栈:\n");for(j=0;j<m;j++)printf("%c ",str2[j]);}int op(char ch)//判断运算符优先级{if(ch=='+'||ch=='-') return 2;if(ch=='*'||ch=='/') return 3;if(ch=='(') return -1;return 0;}double result(double num1,char op,double num2)//计算{if(op=='+') return num1+num2;if(op=='-') return num1-num2;if(op=='*') return num1*num2;if(op=='/') return num1/num2;return 0;}int compute(char str[]){double num=0;int i=0,j=1,k=1;numTop=opTop=0;while(str[i]!='\0'||opTop>0){if(str[i]>='0'&&str[i]<='9')num=num*10+str[i]-'0';else if( k==1&&str[i]=='-'&&(i==0||op(str[i-1])) )k=-1;else{if(i>0&&!op(str[i-1])&&str[i]!='('&&str[i-1]!=')') {numStack[numTop++]=num*k;if(opTop!=0&&numTop!=0)print_num(numStack,numTop);num=0; j=1; k=1;}if(opTop==0||str[i]=='('){opStack[opTop++]=str[i];print_op(opStack,opTop);}else if(str[i]==')'){while(opTop>0&&opStack[--opTop]!='('){numStack[numTop-2]=result(numStack[numTop-2],opStack[opTop],numStack[numTop-1]);if(opTop!=0&&numTop!=0){print_num(numStack,numTop);print_op(opStack,opTop);}numTop--;}if(opStack[opTop]!='(') return 0;}else{if(str[i]=='\0'&&numTop==0) return 0;while(opTop>0&&op(str[i])<=op(opStack[opTop-1])){numStack[numTop-2]=result(numStack[numTop-2],opStack[--opTop],numStack[numTop-1]);if(opTop!=0&&numTop!=0){print_num(numStack,numTop-1); print_op(opStack,opTop);}numTop--;}if(str[i]!='\0')opStack[opTop++]=str[i];if(opTop!=0&&numTop!=0)print_op(opStack,opTop);}}if(str[i]!='\0')i++;}if(numTop!=1||opTop!=0)return 0;return 1;}void menu(){system("cls");printf("_______________________________\n");printf(" Clear(C) | Equal(E) | Quit(Q) \n");printf("-------------------------------\n");}int main(void){int i=0,j=0,k;char str[N]="\0";char num[N]="\0";char save[N]="\0";char ch;double temp;unsigned long temp2;menu();printf("input an expression,press key 'E' to compute\n");ch=getch();while( 1 ){if(ch==')'||op(ch)||ch>='0'&&ch<='9'){str[i++]=ch;str[i]='\0';menu();printf("input an expression,press key 'E' to compute\n"); printf("%s",str);if( ch=='-'&&(i==1||op(str[i-2]))||ch>='0'&&ch<='9' ){num[j++]=ch;num[j]='\0';}elsej=0;}if(ch=='C'||ch=='c'){if(strlen(str))str[--i]='\0';menu();printf("input an expression,press key 'E' to compute\n");printf("%s",str);}if(ch=='E'||ch=='e'){if(compute(str)){printf("\n=%g\n",numStack[0]); j=0; temp=numStack[0];if(temp<0){temp=-temp;num[j++]='-';num[j]='\0';}temp2=(unsigned long)temp;k=1;while(temp2/k>=10) k*=10;while(k){num[j++]=temp2/k+'0';num[j]='\0';temp2=temp2%k;k/=10;}temp=temp-(int)temp;if(temp!=0){num[j++]='.';num[j]='\0';temp+=0.0000005;}for(k=6;k>0;k--){if(temp==0) break;temp*=10;num[j++]=(int)temp+'0';num[j]='\0';temp=temp-(int)temp;}}i=0; j=0; str[0]='\0';}if(ch=='Q'||ch=='q'){printf("\nare you sure to quit?(Y/N)\n");ch=getch();if(ch=='Y'||ch=='y') break;else{menu();printf("input an expression,press key 'E' to compute\n");printf("%s",str);}}ch=getch();}return 0;}第五章系统测试1.先输入: 3+2*5 后按E求值2.再输入:12/4-5 后按E求值3.再输入Q4.输入Y,退出系统。
《数据结构》课程设计利用栈求表达式的值班级: 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)。
XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。
假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。
引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。
(2)显示输入序列与栈得变化过程。
三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。
(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);s、top=s、base;s、stacksize=50;return OK;}char GetTop(SqStack s,char &e) //运算符取栈顶元素{if (s、top==s、base) //栈为空得时候返回ERROR{ﻩ printf("运算符栈为空!\n");ﻩ return ERROR;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。
数据结构课程设计四则运算表达式求值(C语⾔版) 明⼈不说暗话,直接上,输⼊提取码z3fy即可下载。
⽂件中包含程序,程序运⾏⽂件,设计报告和测试样例,应有尽有,欢迎⼩伙伴们在中下载使⽤。
本课程设计为四则运算表达式求值,⽤于带⼩括号的⼀定范围内正负数的四则运算标准(中缀)表达式的求值。
注意事项:1、请保证输⼊的四则表达式的合法性。
输⼊的中缀表达式中只能含有英⽂符号“+”、“-”、“*”、“/”、“(”、“)”、“=”、数字“0”到“9”以及⼩数点“.”,输⼊“=”表⽰输⼊结束。
例如9+(3-1)*3.567+10/2=,特别是请勿输⼊多余空格和中⽂左右括号。
2、输⼊的中缀表达式默认限定长度是1001,可根据具体情况调整字符串数组的长度。
3、请保证输⼊的操作数在double数据类型范围内,单个数字有效数字长度不可超过15位。
本课程设计中操作数是C语⾔中的双精度浮点数类型。
4、本课程设计中的运算数可以是负数,另外如果是正数可直接省略“+”号(也可带“+”号)。
下⾯的程序正常运⾏需要在上⾯的百度⽹盘中下载相应⽂件,否则⽆法正常使⽤哦。
1/*本程序为四则运算表达式求值系统,⽤于计算带⼩括号的四则运算表达式求值。
2具体算法:3先将字符串处理成操作单元(操作数或操作符),再利⽤栈根据四则运算4的运算法则进⾏计算,最后得出结果。
*/56 #include<stdio.h>7 #include<ctype.h>8 #include<stdlib.h>9 #include<string.h>10 #include<stdlib.h>11 #include<ctype.h>1213const int Expmax_length = 1001;//表达式最⼤长度,可根据适当情况调整14struct Ope_unit15 {//定义操作单元16int flag;//=1表⽰是操作数 =0表⽰是操作符 -1表⽰符号单元17char oper;//操作符18double real;//操作数,为双精度浮点数19 };2021void Display();//菜单22void Instru(); //使⽤说明23int Check(char Exp_arry[]);24void Evalua(); //先调⽤Conver操作单元化,再调⽤Calculate函数计算结果并输出25int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[]);//将字符串处理成操作单元26int Isoper(char ch);//判断合法字符(+ - * / ( ) =)27int Ope_Compar(char ope1,char ope2);//操作符运算优先级⽐较28double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag);//⽤栈计算表达式结果29double Four_arithm(double x,double y,char oper);//四则运算3031int main()32 {33int select;34while(1)35 {36 Display();37 printf("请输⼊欲执⾏功能对应的数字:");38 scanf("%d",&select);39 printf("\n");40switch(select)41 {42case1: Evalua(); break;43case2: Instru(); break;44case0: return0;45default : printf("⽆该数字对应的功能,请重新输⼊\n");46 system("pause");47 }48 }49return0;50 }5152int Check(char Exp_arry[])53 {//检查是否有⾮法字符,返回1表⽰不合法,0表⽰合法54int Explength=strlen(Exp_arry),i;55for(i=0;i<Explength;i++)56 {57if(!Isoper(Exp_arry[i]) && Exp_arry[i] != '.' && !isdigit(Exp_arry[i]))58return1;59if(isdigit(Exp_arry[i]))60 {61int Dig_number=0,Cur_positoin=i+1;62while(isdigit(Exp_arry[Cur_positoin]) || Exp_arry[Cur_positoin]=='.')63 {64 Dig_number++;65 Cur_positoin++;66 }67if(Dig_number >= 16)//最多能够计算15位有效数字68return1;69 }70 }71return0;72 }7374void Evalua()75 {//先调⽤Conver函数将字符串操作单元化,再调⽤Calculate函数计算结果并输出76char Exp_arry[Expmax_length];77int flag=0;//假设刚开始不合法,1表达式合法,0不合法78struct Ope_unit Opeunit_arry[Expmax_length];7980 getchar();//吃掉⼀个换⾏符81 printf("请输⼊四则运算表达式,以=结尾:\n");82 gets(Exp_arry);83 flag=Check(Exp_arry);84if(flag)85 printf("该表达式不合法!\n");86else87 {88int Opeunit_count = Conver(Opeunit_arry,Exp_arry);89double ans = Calculate(Opeunit_arry,Opeunit_count,flag);90if(flag)91 {92 printf("计算结果为:\n");93 printf("%s%lf\n",Exp_arry,ans);94 }95else96 printf("该表达式不合法!\n");97 }98 system("pause");99 }100101int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[])102 {//将字符串操作单元化103int Explength=strlen(Exp_arry);104int i,Opeunit_count=0;105for(i=0;i<Explength;i++)106 {107if(Isoper(Exp_arry[i]))//是操作符108 {109 Opeunit_arry[Opeunit_count].flag=0;110 Opeunit_arry[Opeunit_count++].oper=Exp_arry[i];111 }112else//是操作数113 {114 Opeunit_arry[Opeunit_count].flag=1;115char temp[Expmax_length];116int k=0;117for(; isdigit(Exp_arry[i]) || Exp_arry[i]=='.' ;i++)118 {119 temp[k++]=Exp_arry[i];120 }121 i--;122 temp[k]='\0';123 Opeunit_arry[Opeunit_count].real=atof(temp);//将字符转化为浮点数124125//负数126if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0127 && Opeunit_arry[Opeunit_count-1].oper=='-')128 {129 Opeunit_arry[Opeunit_count-1].flag = -1;130 Opeunit_arry[Opeunit_count].real *= -1;131 }// -9132if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0133 && Opeunit_arry[Opeunit_count-1].oper=='-' && Opeunit_arry[Opeunit_count-2].flag==0 134 && Opeunit_arry[Opeunit_count-2].oper !=')')135 {136 Opeunit_arry[Opeunit_count-1].flag = -1;137 Opeunit_arry[Opeunit_count].real *= -1;138 }// )-9139140//正数141if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0142 && Opeunit_arry[Opeunit_count-1].oper=='+')143 {144 Opeunit_arry[Opeunit_count-1].flag = -1;145 }// +9146if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0147 && Opeunit_arry[Opeunit_count-1].oper=='+' && Opeunit_arry[Opeunit_count-2].flag==0148 && Opeunit_arry[Opeunit_count-2].oper !=')')149 {150 Opeunit_arry[Opeunit_count-1].flag = -1;151 }// )+9152 Opeunit_count++;153 }154 }155/*for(i=0;i<Opeunit_count;i++)156 {//查看各操作单元是否正确,1是操作数,0是操作符157 if(Opeunit_arry[i].flag == 1)158 printf("该单元是操作数为:%lf\n",Opeunit_arry[i].real);159 else if(Opeunit_arry[i].flag == 0)160 printf("该单元是操作符为:%c\n",Opeunit_arry[i].oper);161 else162 printf("该单元是负号符为:%c\n",Opeunit_arry[i].oper);163 }*/164return Opeunit_count;165 }166167double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag)168 {//根据运算规则,利⽤栈进⾏计算169int i,dS_pointer=0,oS_pointer=0;//dS_pointer为操作数栈顶指⽰器,oS_pointer为操作符栈顶指⽰器170double Dig_stack[Expmax_length];//操作数栈(顺序存储结构)171char Ope_stack[Expmax_length];//操作符栈172173for(i=0;i<Opeunit_count-1;i++)174 {175if( Opeunit_arry[i].flag != -1 )176 {177if(Opeunit_arry[i].flag)//是操作数178 {179 Dig_stack[dS_pointer++]=Opeunit_arry[i].real;//⼊操作数栈180//printf("%lf\n",Digit[dS_pointer-1]);181 }182else//是操作符 + - * / ( )183 {184//操作符栈为空或者左括号⼊栈185if(oS_pointer==0 || Opeunit_arry[i].oper=='(')186 {187 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;188//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);189 }190else191 {192if(Opeunit_arry[i].oper==')')//是右括号将运算符⼀直出栈,直到遇见左括号193 {194 oS_pointer--;//指向栈顶195 dS_pointer--;//指向栈顶196while(Ope_stack[oS_pointer] != '(' && oS_pointer != 0)197 {198 Dig_stack[dS_pointer-1] = Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 199 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈200201 dS_pointer--;//前⼀个操作数出栈202//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);203 }204 oS_pointer--;//左括号出栈205206 oS_pointer++;//恢复指向栈顶之上207 dS_pointer++;208 }209else if(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer-1]))//和栈顶元素⽐较210 {211 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;212//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);213 }214else//运算符出栈,再将该操作符⼊栈215 {216 oS_pointer--;//指向栈顶217 dS_pointer--;//指向栈顶218while(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer])==0 && oS_pointer != -1) 219 {//当前操作符⽐栈顶操作符优先级⾼220 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 221 Ope_stack[oS_pointer--]);222 dS_pointer--;223//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);224 }225 oS_pointer++;//恢复指向栈顶之上226 dS_pointer++;227 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;228 }229 }230 }231 }232 }233/*for(i=0;i<oS_pointer;i++)234 printf("操作符栈%oS_pointer\Ope_u_count",Operator[i]);235 for(i=0;i<dS_pointer;i++)236 printf("操作数栈%lf\n",Digit[i]);*/237 oS_pointer--;//指向栈顶元素238 dS_pointer--;//指向栈顶元素239while(oS_pointer != -1)240 {241 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 242 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈243 dS_pointer--;//前⼀个操作数出栈244//printf("操作数栈顶元素为%lf\Ope_u_count",Digit[dS_pointer]);245 }246//printf("%dS_pointer,%dS_pointer\n",oS_pointer,dS_pointer);247if(oS_pointer==-1 && dS_pointer==0)248 flag=1;//为1表⽰表达式合法249return Dig_stack[0];250 }251252int Ope_Compar(char ope1,char ope2)253 {//操作符运算优先级⽐较254char list[]={"(+-*/"};255int map[5][5]={//先⾏后列,⾏⽐列的运算级优先级低为0,⾼为1256// ( + - * /257/* ( */1,0,0,0,0,258/* + */1,0,0,0,0,259/* - */1,0,0,0,0,260/* * */1,1,1,0,0,261/* / */1,1,1,0,0 };262int i,j;263for(i=0;i<5;i++)264if(ope1==list[i]) break;265for(j=0;j<5;j++)266if(ope2==list[j]) break;267return map[i][j];268 }269270double Four_arithm(double x,double y,char oper)271 {//四则运算272switch(oper)//保证不含其它运算符273 {274case'+': return x+y;275case'-': return x-y;276case'*': return x*y;277case'/': return x/y;//y不能为0278default : return0;279 }280 }281282int Isoper(char ch)283 {//判断合法字符 + - * / ( ) =284if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='=')285return1;286return0;287 }288289void Display()290 {//打印菜单291 system("cls");292 printf("/******************************************************************************/\n");293 printf("\t\t 欢迎使⽤本四则运算表达式求值系统\n");294 printf("\n\t说明:建议请您先阅读使⽤说明,再输⼊相应的数字进⾏操作,谢谢配合!\n"); 295 printf("\n\t\t1 四则运算表达式求值\n");296 printf("\n\t\t2 使⽤说明\n");297 printf("\n\t\t0 退出\n");298 printf("/******************************************************************************/\n");299 }300301void Instru()302 {//打印使⽤说明303 FILE *fp;304char ch;305if( ( fp=fopen("使⽤说明.txt","r") ) == NULL)306 {307 printf("⽂件打开失败!\n");308 exit(0);309 }310for(; (ch = fgetc(fp)) != EOF; )311 putchar(ch);312 fclose(fp);313 printf("\n");314 system("pause");315 }。
数据结构课程设计实验报告起止时间:2015.12.28-2015.12.311、输入:tan452、输出:13、执行结果::设计过程中遇到的问题及解决办法:问题:算数表达式以字符串输入,操作数和操作符的提取;解决办法:两两操作符之间如有数字将中间的数字提取强制转换成double型;参考文献:(在设计中参考的书籍、网站等资料)1. 朱振元,《数据结构——C++语言描述》,清华大学出版社,2008年,页码:2. /detail/gszhouyi/738777指导老师评议:成绩评定:指导教师签名:附件:(程序源代码)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define N 100#define pai 3.1415926typedef struct yxj{char operat;int rank;}yxj;typedef struct str{char data[N];}zs;void sjhs(void){char s[10],a[10];double y,x;printf("请输入(sin cos tan 角度制)表达式:\n");scanf("%s",s);if(strstr(s,"sin")!=0){int i=0,j=0;while(s[i]!='\0'){if(s[i]>='0'&&s[i]<='9')s[j++]=s[i];i++;}s[j]='\0';x=atof(s);y=sin(x*pai/180);}else if(strstr(s,"cos")!=0){int i=0,j=0;while(s[i]!='\0'){if(s[i]>='0'&&s[i]<='9')s[j++]=s[i];i++;}s[j]='\0';x=atof(s);y=cos(x*pai/180);}else if(strstr(s,"tan")!=0){int i=0,j=0;while(s[i]!='\0'){if(s[i]>='0'&&s[i]<='9')s[j++]=s[i];i++;}s[j]='\0';x=atof(s);y=tan(x*pai/180);}else{printf("格式错误\n");return;}printf("%lf\n",y);printf("*****1、继续*****\n");printf("*****0、返回上一层*****\n");scanf("%s",a);if(strcmp(a,"0")==0)return;else if(strcmp(a,"1")==0)sjhs();elseprintf("没有该选项\n");}void szys(yxj mark[]){yxj os[N];char a[10];char ch;double ns[N];zs zhan[20];int numb[N];int Len,p=0,q=1,i,o=1,n=0;char data[N];os[0]=mark[0];ns[0]=0;printf("请输入算术(+ - * / ^)表达式(以= 结束):\n");scanf("%s",data);if(strcmp(data,"+")==0||strcmp(data,"-")==0||strcmp(data,"*")==0||strcmp(data,"/")==0 ||strcmp(data,"^")==0||strcmp(data,"=")==0){printf("格式错误\n");return;}Len=strlen(data);numb[0]=0;for(i=0;i<20;i++)zhan[i].data[0]='\0';for(i=0;i<Len;i++){int t=0;if((data[i]=='^'||data[i]=='+'||data[i]=='-'||data[i]=='*'||data[i]=='/'||data[i]=='('||data[i]==')'||data[i]=='=')) {int j,k=0;if((data[i]=='='||data[i]=='^'||data[i]=='+'||data[i]=='-'||data[i]=='*'||data[i]=='/')&&(data[i-1]=='^'||data[i-1]=='+'||data[i-1]=='-'||data[i-1]=='*'||data[i-1]=='/')){printf("格式错误\n");return;}numb[q++]=i;while(zhan[(p+k)/2].data[0]!='\0'){k++;}for(j=numb[q-2];j<numb[q-1];j++)if(data[j]>='0'&&data[j]<='9'||data[j]=='.')zhan[(p+k)/2].data[t++]=data[j];zhan[(p+k)/2].data[t]='\0';if(zhan[(p+k)/2].data[0]!='\0')ns[n++]=atof(zhan[(p+k)/2].data);p++;for(j=0;j<8;j++)if(mark[j].operat==data[i])break;while(1){.if(mark[j].operat=='('){os[o++]=mark[j];break;}else if(mark[j].rank>os[o-1].rank&&mark[j].operat!='(') {os[o++]=mark[j];break;}else{double numb1,numb2,numb;switch(ch=os[--o].operat){case '+':{numb1=ns[--n];numb2=ns[--n];numb=numb1+numb2;ns[n++]=numb;break;}case '-':{numb1=ns[--n];numb2=ns[--n];numb=numb2-numb1;ns[n++]=numb;break;}case '*':{numb1=ns[--n];numb2=ns[--n];numb=numb2*numb1;ns[n++]=numb;break;}case '/':{numb1=ns[--n];numb2=ns[--n];if(numb1==0){printf("无效操作\n");return;}else{numb=numb2/numb1;ns[n++]=numb;}break;}case '^':{numb1=ns[--n];numb2=ns[--n];numb=pow(numb2,numb1);ns[n++]=numb;break;}}}}}else if(data[i]>='0'&&data[i]<='9');else if(data[i]=='.');else{printf("格式错误,请重新输入:\n");szys(mark);break;}}printf("%lf\n",ns[0]);printf("*****1、继续*****\n");printf("*****0、返回上一层*****\n");scanf("%s",&a);if(strcmp(a,"0")==0)return;else if(strcmp(a,"1")==0)szys(mark);elseprintf("没有该选项\n");}int main (){yxj mark[9];mark[0].operat='#';mark[0].rank=-1;mark[1].operat='+';mark[1].rank=1;mark[2].operat='-';mark[2].rank=1;mark[3].operat='*';mark[3].rank=2;mark[4].operat='/';mark[4].rank=2;mark[5].operat='(';mark[5].rank=-1;mark[6].operat=')';mark[6].rank=-1;mark[7].operat='=';mark[7].rank=0;mark[8].operat='^';mark[8].rank=3;while(1){char i[10];printf("*****1、四则运算计算器*****\n");printf("*****2、三角函数计算器*****\n");printf("*****0、退出*****\n");scanf("%s",&i);if(strcmp(i,"0")==0)break;else if(strcmp(i,"1")==0)szys(mark);else if(strcmp(i,"2")==0)sjhs();elseprintf("没有该选项\n");}}。
一、设计思想(一)中缀转后缀的设计思想设计一个能实现表达式自动求值计算,算术表达式由操作数、算符和括号组成。
由于运算符的优先级不同还要考虑括号。
所以表达式不可能一直的从左到右进行,所以就借助栈来实现这个表达式的求值。
首先要把算术表达式变换成与之等值的无括号表达式,也就是中缀转后缀,它也是这个算法的关键。
设计两个栈,一个为字符型的,存放运算符,用以将算术表达式变成无括号的表达式;另一个浮点型的,存放操作数,用以对无符号的表达式进行求值。
我们要假设运算符的优先级:( ) , * /, + - 。
首先将一左括号‘(’入栈,作为栈底元素;接着从左到右对算术表达式进行扫描。
每次读一位,若遇到左括号‘(’,则进栈;若遇到的是操作数,则立即输出;若又遇到运算符,如果它的优先级比栈顶元素的优先级数高的话,则直接进栈,否则输出栈顶元素,直到新的栈顶元素的优先级数比它低的,然后将它压栈;若遇到是右括号‘)’,则将栈顶的运算符输出,直到栈顶的元素为‘(’,然后,左右括号互相底消;到设计的结束标志的时候表示表达式已经扫描完毕,表达式已经全部输入,将栈中的运算符全部输出,删除栈底的左括号。
以上完成了中缀表达式转后缀表达式,输出无括号的后缀表达式。
读后缀表达式,若遇数值,操作数进栈;若遇运算符,让操作数栈的栈顶和次栈顶依次出栈并与此运算符进行运算,运算结果入操作数栈;重复这个步骤,直到遇到结束标志,则此时栈中的结果便是所求的后缀表达式的值,接着输出结果。
以上就是设计这个算法的主要的思想。
(二) 直接计算的设计思想直接计算其实跟上一个相似,它是在上面扫两遍的思想进行修改的得来。
首先,要建立两个栈,一个为字符型的,存放运算符,另一个浮点型的,存放操作数,我们开始对表达式进行扫描。
首先要确定运算符的优先级:(、)、*、/、+、-。
如果扫描到的是数字符号,把它们转换成浮点型数据或其他可运算的数据类型,存入操作数栈中。
如果扫描到的是运算符号,第一个运算符进栈,遇到‘(’存入运算符栈中,我们按照第一种算法的方法将表达式依次扫描。
计算机科学系《数据结构课程设计》报告课题名称:算术表达式求值目录1.问题描述-----------------------------------------------------------32.基本要求-----------------------------------------------------------33.工具/准备工作----------------------------------------------------34.分析与实现--------------------------------------------------------45. 课程设计体会与感悟------------------------------------------161.问题描述从键盘上输入中缀算术表达式,包括括号,计算出表达式的值。
2.基本要求(1)程序能对所输入的表达式做简单的判断,如表达式有错,能给适当提示。
(2)能处理单目运算符:+,-。
3.工具/准备工作在开始项目之前,应回顾复习相关内容。
需要一台计算机装有visual C++。
4.分析与实现对于中缀表达式,一般运算规则如下:(1)先乘方,再乘除,最后加减;(2)同级运算从左算到右;(3)先括号内再括号外;(4)用到的头文件”utility.h”,”lk_stack.h”,”node.h”,”calculator.h”.根据实践经验,可以对运算符设置统一的优先级,从而方便比较。
表中给出了包括加、上面讨论的的+、—为双目运算符,如为单目运算符,编程实现时,可在前面加上0而转化为双目运算符。
如在+、—的前一个字符(如当前字符不是运算符时,规定用0表示)为‘=’或‘(’,则为单目运算符。
具体实现算法时,可设置两个工作栈,一个为操作栈,一个为操作符栈optr,另外一个为操作数栈opnd,算法基本思路如下:(1)将optr栈和opnd栈清空,在optr栈中加入一个‘=‘。
目录1 题目的内容及要求 (2)2 需求分析 (2)3 概要设计 (2)4 详细设计 (4)5 源代码 (6)6 运行结果及分析 (13)7 收获及体会 (14)1 题目的内容及要求从文件读取表达式,判断表达式是否合理,将表达式转换成后缀形式,按后缀表达式求值;题目涉及加减乘除,带括弧的混合运算;随时可以退出。
2 需求分析利用栈设计一个程序,该程序能够用于表达式求值,程序将读入的中缀表达式转换为后缀表达式,然后读取后缀表达式,输出结果。
本程序具有检测表达式语法是否正确的功能,如果表达式出现错误的时候,程序会提示操作人员执行的表达式不合理,语法是不能执行的。
语法正常的情况下,程序可以实现了加、减、乘、除以及带括号的基本运算。
程序在执行表达式的时候,先检查表达式是否合理,不合理则输出表达式不符合要求,合理则将中缀表达式转化为后缀表达式,然后则对表达式求值,输出结果。
3 概要设计本程序选用的是线性表数据结构。
它按照后进先出的原则存储数据,先进的数据被压入栈底,最后的数据在栈顶,需要度数据的时候才栈顶开式探出数据。
程序采用的是顺序存储结构,可以将逻辑上相邻的数据元素在物力上相邻的存储单元里,节电之间的关系由存储单元相邻的关系来决定。
选择线性表结构是因为程序是用栈来设计的,可以将优先运算的送至栈顶,低级别的运算则最后根据先后进栈的顺序来执行。
选择顺序存储结构是因为顺序存储结构存取数据数度快,占用的存储空间小。
系统的功能模块划分:Translate()的功能是将中缀表达式转换为后缀表达式DispPostfix()的功能是输出后缀表达式ProcessExpress()的功能是将原表达式进行预处理,检查符号是否匹配,转化为中缀式。
endright的功能是先对表示式的运算符进行处理,考虑其计算的优先级。
FindSymbol()的功能是对表达式的括号进行优先处理。
FindWord()的功能是检查表达式是否有语法错误。
实验表达式求值问题1. 问题描述表达式是数据运算的基本形式。
人们的书写习惯是中缀式,如:11+22* (7-4 )/3. 中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。
表达式还有后缀表达式(如:11 22 7 4 - * 3 / + )和前缀表达式(+ 11 / * 22 - 7 4 3 )。
后缀表达式和前缀表达式中没有括号,给计算带来方便。
如后缀表达式计算时按运算符出现的先后进行计算。
本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。
2. 数据结构设计1)顺序栈类定义:首先应在类中定义成员函数,以此来完成顺序栈的相关操作,如下:class SqStackprivate:T *base; // 栈底指针int top; // 栈顶int stacksize; // 栈容量public:SqStack(int m); // 构建函数~SqStack(){delete [] base;top=0;stacksize=0;} // 析构函数void Push(T x); // 入栈T Pop(); // 出栈T GetTop(); // 获取栈顶元素int StackEmpty(); // 测栈空void ClearStack(); // 清空栈void StackTop(); // 返回栈顶指针void StackTranverse(); // 显示栈中元素};2)顺序栈类实现:对顺序栈进行初始化,初始化的首要操作就是创建一个空顺序栈。
Step1 :申请一组连续的内存空间为顺序栈使用:base=new T[m];i f(base==NULL)cout<<" 栈创建失败,退出!"<<endl; exit(1);}{Step2 :给栈顶、栈容量赋相应的值:stacksize=m;t op=-1;(2)顺序栈入栈:入栈需要在栈顶插入一个新元素并相应的调整栈顶。
课程设计报告课程名称:数据结构课程设计设计题目:表达式求值(计算器)学院:信息科学与工程学院专业:计算机科学与技术(软件外包)姓名:指导教师:二零一五年十二月二十九日一、设计容与要求1、问题描述设计一个算术计算器,能运算包括四则运算、括号的表达式的运算。
2、设计要求实现()、+、-、*、/、^ 等运算,实现小数和整数混合运算,优先级的处理,能判断算术表达式是否正确等。
二、算法设计1、输入并建立表达式,运用数组结构体构建将整型数字与操作符结合定义运算符的优先级。
typedef struct yxj{char operat;int rank;}yxj;2、分别建立一个操作数栈和操作符栈存放数字和操作符,定义操作符栈第一个元素优先级最低。
3、自左向右扫描字符串遇到字符串中的数字时一律提取转换成double型存入操作数栈。
遇到操作符时,则将当前运算符的优先级数与运算符栈顶元素的优先级数相比较。
若当前运算符的优先级数大,则进栈;反之,则取出栈顶的运算符,并在数栈中连续取出两个栈顶元素作为运算对象进行运算,并将运算结果存入数栈,然后继续比较当前运算符与栈顶元素的优先级。
直到当前运算符进栈。
4、对比运算符进行+ - * /()^ 运算。
三、程序代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define N 100typedef struct yxj{char operat;int rank;}yxj;typedef struct str{char data[N];}zs;void szys(yxj mark[]){yxj os[N];char ch;double ns[N];zs zhan[20];int numb[N];int Len,p=0,q=1,i,o=1,n=0;char data[N];os[0]=mark[0];printf("请输入算术(+ - * / ^)表达式(以 = 结束):\n");scanf("%s",data);Len=strlen(data);numb[0]=0;for(i=0;i<20;i++)zhan[i].data[0]='\0';for(i=0;i<Len;i++){int t=0;if(data[i]=='^'||data[i]=='+'||data[i]=='-'||data[i]=='*'||data[i]=='/'||data[ i]=='('||data[i]==')'||data[i]=='='){int j,k=0;if((data[i]=='='||data[i]=='^'||data[i]=='+'||data[i]=='-'||data[i]=='*'||data [i]=='/')&&(data[i-1]=='^'||data[i-1]=='+'||data[i-1]=='-'||data[i-1]=='*'||data[i -1]=='/')){printf("格式错误\n");return;}numb[q++]=i;while(zhan[(p+k)/2].data[0]!='\0'){k++;}for(j=numb[q-2];j<numb[q-1];j++)if(data[j]>='0'&&data[j]<='9'||data[j]=='.')zhan[(p+k)/2].data[t++]=data[j];zhan[(p+k)/2].data[t]='\0';if(zhan[(p+k)/2].data[0]!='\0')ns[n++]=atof(zhan[(p+k)/2].data);p++;for(j=0;j<8;j++)if(mark[j].operat==data[i])break;while(1){if(mark[j].operat=='('){os[o++]=mark[j];break;}else if(mark[j].rank>os[o-1].rank&&mark[j].operat!='(') {os[o++]=mark[j];break;}else{double numb1,numb2,numb;ch=os[--o].operat;if(ch=='+'){numb1=ns[--n];numb2=ns[--n];numb=numb1+numb2;ns[n++]=numb;}if(ch=='-'){numb1=ns[--n];numb2=ns[--n];numb=numb2-numb1;ns[n++]=numb;}if(ch=='*'){numb1=ns[--n];numb2=ns[--n];numb=numb2*numb1;ns[n++]=numb;}if(ch=='/'){numb1=ns[--n];numb2=ns[--n];if(numb1==0){printf("无效操作\n");return;}else{numb=numb2/numb1;ns[n++]=numb;}}if(ch=='^'){numb1=ns[--n];numb2=ns[--n];numb=pow(numb2,numb1);ns[n++]=numb;}}}}else if(data[i]>='0'&&data[i]<='9');else if(data[i]=='.');else{printf("格式错误,请重新输入:\n");szys(mark);break;}}printf("%lf\n",ns[0]);}int main (){yxj mark[9];mark[0].operat='#';mark[0].rank=-1;mark[1].operat='+';mark[1].rank=1;mark[2].operat='-';mark[2].rank=1;mark[3].operat='*';mark[3].rank=2;mark[4].operat='/';mark[4].rank=2;mark[5].operat='(';mark[5].rank=-1;mark[6].operat=')';mark[6].rank=-1;mark[7].operat='=';mark[7].rank=0;mark[8].operat='^';mark[8].rank=3;while(1){char i[N];printf("*****1、计算器*****\n");printf("*****0、退出 *****\n");scanf("%s",&i);if(strcmp(i,"0")==0)break;else if(strcmp(i,"1")==0)szys(mark);elseprintf("没有该选项\n");}}四、运行测试1.正常四则运算2.乘方运算3.除数为零时4.格式出现错误5.小数运算五、结论这次课程设计让我们更加了解大一学到的C和这个学期学到的数据结构。
数据结构表达式求值正文:1. 引言本文档旨在介绍数据结构中表达式求值的相关知识和算法。
通过对不同类型的表达式进行解析、转换和计算,可以实现数学运算、逻辑判断等功能。
2. 表达式基础概念2.1 表达式定义:一个由操作符(如加减乘除)、操作数(变量或常量)以及括号组成的序列。
2.2 中缀表示法:将操作符置于两个相邻的操作数之间,例如a +b c。
2.3 后缀表示法:将所有操作符都放到其相关联的两个对象后面,例如 abc+。
3. 中缀转后缀在计算机内部处理表达时通常使用后缀形势更为方便,在此我们需要先把中边形势得出来再做进一步分析与运行4.栈应用-前驱关系图这里是讲述了当遇见某些特殊字符要怎么去处理5.从左至右扫描并分类输入串:这里主要说明了如果用户给定字符串有误该怎样提示错误信息6.数字直接输出, 操作者入堆栈:当检测到当前读取元素是数字就会直接打印7 . 遇到操作符时,比较其与栈顶运算符的优先级:这里主要是讲述了当遇见某些特殊字符要怎么去处理8 . 操作者入堆栈当检测到当前读取元素是数字就会直接打印9. 遇括号则进行如下判断:如果为左括号,则将此运算符压入堆叠。
(2)如果为右括号。
则依次弹出S中的所有运算符,并加至输出串尾部, 直至删除一个相应的左括号(不包含该左扩展)。
10.重复步骤3-6 ,直至表达式结束附件:无法律名词及注释:1. 表达式求值:指对给定数学或逻辑表达式进行计算并得出结果的过程。
2. 中缀表示法:一种常用于书写和理解数学表达式的形式,其中操作符位于两个相关联的对象之间。
3. 后缀表示法(也称逆波兰表示法):一种以后置方式排列操作数和操作符来构造代数、布尔函数等合成函数公式或语言文法规范的记录方法和数据结构.。
数据结构(C语言版)课程设计报告表达式求值说明书XX大学数据结构课程设计说明书题目:表达式求值院系:计算机科学与工程学院专业班级:计算机班学号:学生姓名:指导教师:2021年X月X日XX大学课程设计(论文)任务书计算机科学与工程学院学号学生姓名专业(班级)设计题目表达式求值设计技术参数系统平台:Windows7/WindowsXP开发工具:VC++6.0设计要求(1)能够计算的运算符包括:加、减、乘、除、圆括号。
(2)能够计算的数要求在实数范围内。
(3)能执行多重括号嵌套运算。
(4)对于异常表达式给出错误提示。
工作量课程设计报告要求不少于3000字。
源程序要求不少于300行工作计划2021.11.21-12.01根据课程设计大纲的要求,查找相关资料,完成需求分析;2021.12.02-12.16进行系统的概要设计;2021.12.17-12.31进行系统的详细设计和源代码的书写;2021.01.01-01.17对系统进行调试分析,写出课程设计报告。
参考资料[1]何钦铭主编.C语言程序设计.北京:高等教育出版社,2021.[2]谭浩强编著.C程序设计(第四版).北京:清华大学出版社,2021.[3]严蔚敏,吴伟民编著.数据结构(C语言版)北京:清华大学出版社,2021.[4]严蔚敏,吴伟民编著.数据结构题集北京:清华大学出版社,2021.指导教师签字教研室主任签字2021年X月X日学生姓名:学号:专业班级:课程设计题目:表达式求值指导教师评语:成绩:指导教师:年月日XX大学课程设计(论文)成绩评定表目录1需求分析12概要设计12.1设计思路12.2存储结构设计12.3功能模块设计13详细设计14运行与测试15总结1参考文献2(要求:给出一级目录和二级目录,宋体,四号字,1.5倍行距,页码使用罗马数字,居中)(报告正文部分):(要求:正文部分一律用小四号字,宋体,行距20磅。
一级标题靠左,加粗。
二级大标题靠左,不加粗。
目录1.前言 (2)2.问题描述 (3)3.总体设计··········································································错误!未定义书签。
3.1 概要设计 ······································································错误!未定义书签。
表达式求值(数据结构)表达式求值(数据结构)一、引言表达式求值是计算机科学中一个重要的概念,它是计算机程序中常见的操作之一。
通过对表达式中的运算符和操作数进行计算,可以得到表达式的结果。
本文将介绍表达式求值的相关知识和算法,并提供一个基于数据结构的表达式求值的范本。
二、基本概念1.表达式:由操作数、运算符和括号组成的符号串,用于表示一个计算过程。
2.操作数:表达式中用于参与计算的数值或变量。
3.运算符:表达式中用于进行运算的符号,如加减乘除等。
4.括号:用于控制运算优先级和改变运算次序的符号。
三、表达式求值的算法表达式求值的基本思路是通过遍历表达式字符串并利用栈来进行计算。
1.建立一个操作数栈和一个运算符栈。
2.从左到右遍历表达式字符串,依次处理每个字符。
3.如果当前字符是操作数,则直接入操作数栈。
4.如果当前字符是运算符,则进行如下处理:●如果运算符栈为空或栈顶运算符是左括号,则将当前运算符入运算符栈。
●如果当前运算符的优先级高于栈顶运算符的优先级,则将当前运算符入运算符栈。
●如果当前运算符的优先级低于或等于栈顶运算符的优先级,则从运算符栈顶取出一个运算符进行计算,并将结果入操作数栈,直到栈顶运算符的优先级低于当前运算符,然后将当前运算符入运算符栈。
5.如果当前字符是左括号,则将其入运算符栈。
6.如果当前字符是右括号,则从运算符栈顶取出一个运算符进行计算,并将结果入操作数栈,直到取出的运算符是左括号。
7.遍历完表达式字符串后,将运算符栈中剩余的运算符依次取出进行计算,并将结果入操作数栈。
8.操作数栈中最后剩下的元素即为表达式的求值结果。
四、示例代码```pythonclass ExpressionEvaluation:def __init__(self, expression):self.expression = expressionself.operators = []self.operands = []self.precedence = {'+': 1, '.': 1, '': 2, '/': 2}def evaluate(self):for char in self.expression:if char.isdigit():self.operands.append(int(char))elif char in self.precedence:while self.operators andself.operators[.1] != '(' and self.precedence[char] <= self.precedence[self.operators[.1]]:lculate()self.operators.append(char)elif char == '(':self.operators.append(char)elif char == ')':while self.operators[.1] != '(':lculate()self.operators.pop()while self.operators:lculate()return self.operands[.1]def calculate(self):operator = self.operators.pop()operand2 = self.operands.pop()operand1 = self.operands.pop()if operator == '+':self.operands.append(operand1 + operand2)elif operator == '.':self.operands.append(operand1 ●operand2) elif operator == '':self.operands.append(operand1 operand2) elif operator == '/':self.operands.append(operand1 / operand2) expression = \。
数据结构课程设计报告(二)表达式求值(计算器).课程设计报告课程名称:数据结构课程设计设计题目:表达式求值(计算器)学院:信息科学与工程学院专业:计算机科学与技术(软件外包)姓名:指导教师:二零一五年十二月二十九日word教育资料.一、设计内容与要求1、问题描述设计一个算术计算器,能运算包括四则运算、括号的表达式的运算。
2、设计要求实现()、+、- 数据结构课程设计设计题目:表达式求值(计算器)学院:信息科学与工程学院专业:计算机科学与技术(软件外包)姓名:指导教师:二零一五年十二月二十九日word教育资料.一、设计内容与要求1、问题描述设计一个算术计算器,能运算包括四则运算、括号的表达式的运算。
2、设计要求实现()、+、:\n"); scanf("%s",data); Len=strlen(data); numb[0]=0; for(i=0;i20;i++) zhan[i].data[0]='\0'; for(i=0;i='0'data[i]='9'); else if(data[i]=='.'); else { printf("格式错误,请重新输入:\n"); szys(mark); break; } } printf("%lf\n",ns[0]);}int main (){ yxj mark[9]; mark[0].operat='#'; mark[0].rank=-1; mark[1].operat='+'; mark[1].rank=1; mark[2].operat='-'; mark[2].rank=1; mark[3].operat='*'; mark[3].rank=2; mark[4].operat='/'; mark[4].rank=2; mark[5].operat='('; mark[5].rank=-1; mark[6].operat=')'; mark[6].rank=-1; mark[7].opera该选项\n"); }}四、运行测试1.正常四则运算2.乘方运算3.除数为零时4.格式出现错误5.小数运算五、结论这次课程设计让我们更加了解大一学到的C和这个学期学到的数据结构。
表达式求值一目的利用《数据结构》课程的相关知识完成一个具有一定难度的综合设计题目,利用C/C++语言进行程序设计,并规范地完成课程设计报告。
通过课程设计,巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
设计一个程序,演示以字符序列的形式输入不含变量的实数表达式求值的计算结果二需求分析设计一个程序,演示以字符序列的形式输入不含变量的实数表达式求值的计算结果。
对于这个程序我们从输入,输出,和功能三方面来分析。
1.程序输入:从键盘上输入表达式,一个算术表达式,由常量、运算符和括号组成(以字符串形式输入,不含变量)。
为了简化,操作数只能为浮点数,操作符为“ +”、“-”、“*”、“/”、“(”、“)”,用“#“表示结束。
2.程序输出:表达式运算结果,运算符栈、运算数栈、输入字符和主要操作变化过程,如运算符栈、运算数栈的出入记录,字符出入栈的过程,打印出完整的过程。
3.功能要求及说明:从键盘上输入表达式。
分析该表达式是否合法(包含分母不能为零的情况):(1)是数字,则判断该数字的合法性。
(2)是规定的运算符,则根据规则进行处理。
在处理过程中,将计算该表达式的值。
(3)若是其它字符,则返回错误信息。
若上述处理过程中没有发现错误,则认为该表达式合法,并打印处理结果。
三概要设计1.数据结构的选择:任何一个表达式都是由操作符,运算符和界限符组成的。
我们分别用顺序栈来寄存表达式的操作数和运算符。
栈是限定于紧仅在表尾进行插入或删除操作的线性表。
为了实现算符优先算法,可以使用两个工作栈。
一个称做SqStack1,用以寄存运算符;另一个称做SqStack2,用以寄存操作数或运算结果。
首先置操作数栈为空栈,表达式起始符“#”作为运算符栈的栈底元素,然后依次读入表达式的每个字符,若是操作数则进入SqStack2栈,若是运算符则和SqStack1栈的栈顶运算符比较优先权后做相应操作,直至整个表达式求值完毕。
**大学数据结构课程设计说明书学生姓名:***学号: **********学院: **********学院专业: 网络工程题目: 利用栈求表达式的值成绩指导教师******2009 年 7 月 9 日1.设计目的数据结构课程设计的目的是,通过设计掌握数据结构课程中学到的基本理论和算法并综合运用于解决实际问题中,它是理论与实践相结合的重要过程。
设计要求学会如何对实际问题定义相关数据结构,并采用恰当的设计方法和算法解决问题,同时训练学生进行复杂程序设计的技能和培养良好的程序设计习惯。
2.设计内容和要求利用栈求解表达式的值。
设计内容:1)建立试题库文件,随机产生n个题目;2)题目涉及加减乘除,带括弧的混合运算;3)利用栈求解表达式的值;4)随时可以退出;5)保留历史分数,能回顾历史,给出与历史分数比较后的评价基本要求:1)系统功能的完善;2)代码中有必要的注释3.本设计所采用的数据结构栈的数组表示方法(静态分配整型指针)typedef struct{typedef data[MAXSIZE];int top;};4.功能模块详细设计1.功能一:中缀表达式转化为后缀表达式;2.功能二:后缀表达式求值;3.功能三:文件读写;4.功能四:作业评分;5.功能五:历史成绩本次成绩比较;6.功能六:输入“~”符号退出程序4.1 详细设计思想1.首先实现表达式的求值:要用栈求解一个表达式,就要将这个表达式翻译成正确求值的一个机器指令序列,即正确解释表达式,了解算术四则混合运算的规则:(1).先乘除,后加减;(2).从左算到右;(3).先括号内,后括号外再根据这个运算优先的规定来实现对表达式的编译或解释执行.任何一个表达式都是由操作数(st)和操作符(op)组成的,根据四则运算基本法则,在运算的每一步中,任意两个相继出现的操作符op1和op2之间的优先关系最多有以下3种:(1).op1的优先级低于op2(2).op1的优先级等于op2(3).op1的优先级小于op2为实现运算符优先,可以使用两个操作栈,操作栈st,用于存放操作数及运算结果;操作栈op,用于存放操作符。
福建农林大学计算机与信息学院计算机类课程设计报告课程名称:算法与数据结构课程设计题目:表达式计算姓名:系:数学系专业:数学与应用数学年级:学号:指导教师:宁正元职称:教授20**年12月25 日目录1、课程设计的目的 (1)2、课程设计的要求 (1)3、课程设计的内容 (1)3.1主函数中一些重要变量的作用 (1)3.2重要步骤算法思路分析 (1)3.3源程序代码 (3)3.4程序调试与测试结果 (12)3.5结果分析 (16)4、总结 (16)5、参考文献 (16)表达式计算1、课程设计的目的1.掌握C语言的相关知识;2.熟悉掌握结构体和共用体的定义和使用;3.熟悉掌握栈和相关操作函数的定义和使用;4.熟悉掌握数组和相关操作的定义和使用2、课程设计的要求1.对从键盘输入一个表达式,先检查合法性:如不合法,则给出错误信息,再返回;如合法,则对其进行整理,利用栈和数组进行相关数据保存,再进行运算,最后输出计算结果。
2.计算范围:包括一般的算术运算(加、减、乘、除、括号)和常用的函数运算(三角函数、自然指数函数、自然对数函数、绝对值函数、平方根函数)。
3.其他功能可自行添加。
3、课程设计的内容3.1主函数中一些重要变量的作用double sz[MAXSIZE];用于存放数值的数组char fh[MAXSIZE]; 用于存放运算符的数组char temp[MAXSIZE];用于存放输入的表达式的数组float sum; 用于记录当前读到的数中以读到的数值int i_b,i_t,ld,lsz; i_b后面备用; i_t记录读到哪一个字符;ld记录小数的位数; lsz记录sz的有效长度; shed KH,HS; KH用于放括号的栈;HS用于放函数的栈3.2重要步骤算法思路分析(均以合法表达式为例)先用数组temp对输入的表达式进行储存,再对其进行一位一位地读取和处理:1.对数值和运算符的处理:1)对运算符的处理比较简单,当遇到运算符时,直接存入数组fh即可;2)对数值的处理,由于不知道数是几位,所以要用两个变量sum、ld,(sum记录已读取得数字,ld记录小数位数),具体操作请见下面流程图:2.对括号运算和函数运算的处理:对括号运算和函数运算的处理比较麻烦,特别市它们的嵌套使用,如式子:1+(2-(3+4)*5)*6当读到2前的‘(’时,由于括号运算的优先级高于加、减、乘、除,所以应对其先进行保存,当读到3前的‘(’时,同样也要先进行保存。
当读到4后的‘)’时,应把3前的‘(’取出来,与之配对,再运算之间的式子,同样当读到5后的‘)’时,应把2前的‘(’取出来,配对,再运算。
所以对于‘(’的保存与读取具有先进后出的特点,栈刚好也有这个特点,因此用栈可以对其进行储存;同理,对函数的处理也是这样的,如式子:sin(abs(-1))应先保存sin函数名,再保存abs函数名;而进行计算时,应先计算abs函数再计算sin 函数,也有先进后出的特点。
再考虑这些栈的元素的特点:对于保存函数名的栈,它的元素必要有两个分量:一个保存函数名,可以用char类型,另一个分量要记录该函数在式中的位置,可以用int类型。
对于保存扣号的栈,因为考虑到有2种括号:一种是一般算式中的括号,如式子2*(3+4)中的括号;另一种是函数中把参数与一般数值区分开的括号,如式子sin(-1)中的括号。
又考虑到要保存的都是’(’,所以该栈也只要2个分量,一个是该括号的种类,可以用int类型的0和1表示(0表示一般算式中的括号,1表示函数参数前的括号),另一个分量是保存该括号在式中的位置。
又考虑到两种栈统一性,我们先定义一个共用体:union sig //sign1记录括号是属于函数的还是运算的,sign2记录是什么函数{ int sign1;char sign2;};在定义栈元素的结构体:typedef struct node{ union sig sign;int jilu;}node; //记录括号或函数的结构体3.3源程序代码#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#define MAXSIZE 100union sig //sign1记录括号是属于函数的还是运算的,sign2记录是什么函数{ int sign1;char sign2; };typedef struct node{ union sig sign;int jilu; }node; //记录括号或函数的结构体struct shed{ node data[MAXSIZE];int top; };typedef struct shed shed; //定义栈void setnull(shed *S) //初始化栈函数{ S->top=-1; }void push(shed *S,node x) //入栈函数{ S->top++;S->data[S->top]=x; }node pop(shed *S) //出栈函数{ S->top--;return(S->data[S->top+1]); }int panduan(char *x) //该函数检验输入的表达式是否正确,正确返回1,错误返回0。
{ char a[4]={'s','i','n','\0'};int i=0,j=0,k;char tem[4];while(x[i]!='\0'){ if((x[i]=='*'||x[i]=='/')&&i==0){ printf("!!输入错误:第一个字符是运算符!!\n");return 0;break;}if(x[i]=='p'){ if(x[i+1]!='i'){ printf("!!输入错误:%c%c不存在!!\n",x[i],x[i+1]);return 0;break;}if(x[i+2]>='a'&&x[i+2]<='z'){ printf("!!输入错误:%c%c%c不存在!!\n",x[i],x[i+1],x[i+2]);return 0;break;}i++;}else if((x[i]>='a'&&x[i]<'p')||(x[i]>'p'&&x[i]<='z')){ if(x[i+3]!='('){ printf("!!输入错误:函数名错误!!\n");return 0;break;}tem[0]=x[i];tem[1]=x[i+1];tem[2]=x[i+2];tem[3]='\0';if(strcmp(tem,"sin")&&strcmp(tem,"cos")&&strcmp(tem,"tan")&&strcmp(tem,"qrt")){ if(strcmp(tem,"exp")&&strcmp(tem,"log")&&strcmp(tem,"abs")){ printf("!!输入错误:函数名错误!!\n");return 0;break;}}i=i+2;}if(x[i-1]=='+'||x[i-1]=='-'||x[i-1]=='*'||x[i-1]=='/'){ if(x[i]=='+'||x[i]=='-'||x[i]=='*'||x[i]=='/'){ printf("!!输入错误:连续输入运算符!!\n");return 0;break;}}if((x[i]==')'||x[i]=='=')&&k==1){ printf("!!输入错误:运算符后没数字!!\n");return 0;break;}if((x[i-1]>='0'&&x[i-1]<='9')&&(x[i]>='a'&&x[i]<='z')) { printf("!!输入格式错误:数字后紧接着函数!!\n");return 0;break;}if((x[i-1]>='0'&&x[i-1]<='9')&&(x[i]=='(')){ printf("!!输入格式错误:数字后紧接着‘(’!!\n");return 0;break;}if((x[i-1]=='(')&&(x[i]==')')){ printf("!!输入错误:‘()’内无表达式!!\n");return 0;break;}if((x[i-1]==')')&&(x[i]=='(')){ printf("!!输入错误:‘)’与‘(’间缺少运算符!!\n");return 0;break;}if(x[i]=='(') j++;if(x[i]==')') j--;if(x[i]=='.'){ k=0;while(x[i+(++k)]>='0'&&x[i+k]<='9');if(x[i+k]=='.'){ printf("!!输入错误:多输入了小数点!!\n");return 0;}}i++;}if(j!=0){ if(j>0)printf("!!输入格式错误:少输入了%d个‘)’\n",j);elseprintf("!!输入格式错误:少输入了%d个‘(’\n",-j);return 0;}elsereturn 1;}int yunsuan(int a,int lsz,double *sz,char *fh)//把sz数组中的数从sz[a]到sz[lsz]根据数组fh中的运算符进行计算//返回值为计算后lsz的值{ int i,j;for(i=a;i<lsz;i++) //该趟循环计算和除{ if(fh[i]=='*'||fh[i]=='/'){ if(fh[i]=='*')sz[i]*=sz[i+1];elsesz[i]/=sz[i+1];j=i+1;while(j<lsz) //计算完一个后就把sz和fh中后面的元素向前移动一位{ sz[j]=sz[j+1];fh[j-1]=fh[j];j++;}i--;lsz--; //数组的长度也减1}}for(i=a;i<lsz;i++) //该趟循环计算加和减{ if(fh[i]=='+')sz[i]+=sz[i+1];elsesz[i]-=sz[i+1];j=i+1;while(j<lsz){ sz[j]=sz[j+1];fh[j-1]=fh[j];j++;}i--;lsz--;}return lsz;}void main(){loop1:printf("!!该计算器计算范围:\n");printf("》加、减、乘、除、括号(+,-,*,/,())\n");printf("》三角函数(sin,cos,tan)、平方根(qrt)、绝对值(abs)\n");printf("》自然数指数函数(exp)、自然数对数函数(log)\n");loop2:double sz[MAXSIZE]; //用于保存数值的数组char fh[MAXSIZE]; //用于保存运算符的数组char temp[MAXSIZE]; //用于对输入的表达式进行临时保存的数组float sum=0;int i_b,i_t=0,ld=0,lsz=0;//i_t记录读到哪一个字符;ld记录小数的位数;lsz记录sz的有效长度;shed KH,HS; //KH用于放括号的;HS用于放函数的setnull(&KH);setnull(&HS);node ele; //后面备用printf("**************************************************\n");printf("请输入表达式:(!!输入“clc”:清屏)\n");scanf("%s",&temp);if(!strcmp(temp,"clc")){ system("cls");goto loop1;}if(!panduan(temp))goto loop2;while(temp[i_t]!='\0'){ if(temp[i_t]=='.')ld=1;if(temp[i_t]>='0'&&temp[i_t]<='9'){ if(ld==0)sum=10*sum+(temp[i_t]-'0');else{ sum+=float((temp[i_t]-'0')*pow(10,-ld));ld++;}}if(temp[i_t]=='+'||temp[i_t]=='-'||temp[i_t]=='*'||temp[i_t]=='/'||temp[i_t]==')'){ if(temp[i_t-1]!=')'){ sz[lsz++]=sum;sum=0;ld=0;}if(temp[i_t]==')'){ lsz--;ele=pop(&KH);i_b=ele.jilu;lsz=yunsuan(i_b,lsz,sz,fh);i_b=ele.sign.sign1;if(i_b==1){ ele=pop(&HS);switch (ele.sign.sign2){case 's':sz[lsz]=sin(sz[lsz]);break;case 'c':sz[lsz]=cos(sz[lsz]);break;case 't':sz[lsz]=tan(sz[lsz]);break;case 'l':sz[lsz]=log(sz[lsz]);break;case 'e':sz[lsz]=exp(sz[lsz]);break;case 'a':sz[lsz]=fabs(sz[lsz]);break;case 'q':sz[lsz]=sqrt(sz[lsz]);break;}}lsz++;}elsefh[lsz-1]=temp[i_t];}if(temp[i_t]=='('){ ele.sign.sign1=0;ele.jilu=lsz;push(&KH,ele);}if(temp[i_t]>='a'&&temp[i_t]<='z'){ if(temp[i_t]=='p'){ sum=3.141592653589793238462;i_t++;}else{ ele.sign.sign2=temp[i_t];ele.jilu=lsz;push(&HS,ele);ele.sign.sign1=1;ele.jilu=lsz;push(&KH,ele);i_t+=3;}}i_t++;}if(temp[i_t-1]!=')'||lsz-1>0){ sz[lsz]=sum;sum=0;yunsuan(0,lsz,sz,fh);}printf("计算结果:\n");printf("%lf\n",sz[0]);printf("**************************************************\n");goto loop2;}3.4程序调试与测试结果1.程序运行后:2. 检测输入的合法性:3.检测清屏功能(以下屏幕内容是上一屏幕的一部分):按下Enter后:4. 检测一般算术运算(加、减、乘、除及括号):5.检测函数运算:3.5结果分析由具体结果及分析知:该计算器的各项功能基本能够实现,各项功能的实现细节考虑还算周到,而且能够达到预期的效果,但是还有一些不足之处,比如实现的功能过于简单,不能进行符号运算等等。