一.实验目的
通过一个具体实际应用例子,加深对数据结构课程的理解,能够综合利用数据结构以及C语言的知识设计程序,应用到实际问题中去。
二.实验题目
常见的小型计算器可以通过输入一个由操作数和操作符组成的表达式计算出结构,设计一个程序模拟上述功能。本实验要求至少建立两个栈和一个运算符优先级比较表,按照运算法优先级的不同操作两个栈,最终实现整个表达式的求值。本程序可以移植到任何一个小型计算器中。
三.实现提示
1.运算符优先级表如下图所示:
| + | - | * | / | ( | ) | # |
+ | > | > | < | < | < | > | > |
- | > | > | < | < | < | > | > |
* | > | > | > | > | < | > | > |
/ | > | > | > | > | < | > | > |
( | < | < | < | < | < | = | |
) | > | > | > | > | | > | > |
# | < | < | < | < | < | | = |
2.从键盘上输入的都是按照字符的形式,而实际的计算过程中需要将其转化成对应的操作符和操作数,将其转化可以通过对应的ASCII码表实现,通过查找ASCII码表来找出字符所对应的操作数以及操作符。
3.表达式中可能含有多位数以及带小数的数,对这种情况的处理主要是要通过一个子函数进行,依次读入字符据直到遇到下一个运算符结束,然后整体处理整个字符串,转化成数据。而对于带小数的情况则需要将整数部分和小数部分分开按照前述过程处理,最后再将两部分合并。
四.思考及选做
1.需要注意的是在程序实际运行的时候,对于有小数部分的情况计算的结果会出现截断误差,也就是说计算出的值有舍入情况,注意这一现象,深入理解计算机进行科学计算的本质。
五.我的实现
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define error 0
- #define ok 1
- #define overflow -1
- #define STACK_INIT_SIZE 100
- #define STACKINCREMENT 10
- #define OPSETSIZE 7
- typedef int Status;
-
-
-
- char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#'};
- unsigned char Prior[7][7] = {
- '>','>','<','<','<','>','>',
- '>','>','<','<','<','>','>',
- '>','>','>','>','<','>','>',
- '>','>','>','>','<','>','>',
- '<','<','<','<','<','=',' ',
- '>','>','>','>',' ','>','>',
- '<','<','<','<','<',' ','='
- };
-
-
-
-
- template <typename T>
- struct SqStack
- {
- T *top;
- T *base;
- int stacksize;
- };
-
-
-
-
- template <typename T1,typename T2>
- Status InitStack(T1 &S)
- {
- S.base=(T2 *)malloc(STACK_INIT_SIZE*sizeof(T2));
- if(!S.base) exit (overflow);
- S.top=S.base;
- S.stacksize=STACK_INIT_SIZE;
- return ok;
- }
-
-
-
-
- template <typename T1,typename T2>
- Status Push(T1 &S,T2 e)
- {
- if(S.top-S.base>=S.stacksize)
- {
- S.base=(T2 *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(T2));
- if(!S.base) exit (overflow);
- S.top=S.base+S.stacksize;
- S.stacksize+=STACKINCREMENT;
- }
- *S.top++=e;
- return ok;
- }
-
-
-
-
- template <typename T1,typename T2>
- Status Pop(T1 &S,T2 &e)
- {
- if(S.top==S.base) return error;
- e=*--S.top;
- return ok;
- }
-
-
-
-
- template <typename T1,typename T2>
- T2 GetTop(T1 S)
- {
- if(S.top==S.base)
- return error;
- else
- return *(S.top-1);
-
- }
-
-
-
-
- Status In(char Test,char* TestOp) {
- bool Find=false;
- for (int i=0; i< OPSETSIZE; i++) {
- if (Test == TestOp[i]) Find= true;
- }
- return Find;
- }
-
-
-
-
- float Operate(float a,unsigned char theta, float b) {
- switch(theta) {
- case '+': return a+b;
- case '-': return a-b;
- case '*': return a*b;
- case '/': return a/b;
- default : return 0;
- }
- }
-
-
-
-
- int ReturnOpOrd(char op,char* TestOp) {
- int i;
- for(i=0; i< OPSETSIZE; i++) {
- if (op == TestOp[i]) return i;
- }
- return 0;
- }
-
- char precede(char Aop, char Bop) {
- return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
- }
-
-
-
-
-
- float EvaluateExpression() {
-
- SqStack<char> OPTR;
- SqStack<float> OPND;
- char TempData[20];
- float Data,a,b;
- char theta,c,x,Dr[2];
-
- InitStack<SqStack<char>,char> (OPTR);
- Push (OPTR, '#');
- InitStack <SqStack<float>,float>(OPND);
- strcpy(TempData,"\0");
- c=getchar();
- while (c!= '#' || GetTop<SqStack<char>,char>(OPTR)!= '#')
- {
- if (!In(c, OPSET))
- {
- Dr[0]=c;
- Dr[1]='\0';
- strcat(TempData,Dr);
- c=getchar();
- if(In(c,OPSET))
-
- {
- Data=(float)atof(TempData);
- Push(OPND, Data);
- strcpy(TempData,"\0");
- }
- }
- else
- {
- switch (precede(GetTop<SqStack<char>,char>(OPTR), c)) {
- case '<':
- Push(OPTR, c);
- c=getchar();
- break;
- case '=':
- Pop(OPTR, x);
- c=getchar();
- break;
- case '>':
- Pop(OPTR, theta);
- Pop(OPND, b);
- Pop(OPND, a);
- Push(OPND, Operate(a, theta, b));
- break;
- }
- }
- }
- return GetTop<SqStack<float>,float>(OPND);
- }
-
- int main()
- {
- printf("请输入表达式,请以#结束:\n");
- printf("%f\n",EvaluateExpression());
- system("PAUSE");
- return 0;
- }