算法思路:
首先应该想怎样将操作数和操作符分开放入两个栈,此时可以用asc码的大小来区分,区分开以后通过fgetc()从文件中读取字符,读取到的字符再通过入栈操作push()入栈。然后再想入栈和出栈的规则,操作数栈需要实现的功能是把每一个遇到的操作数对应的字符串,转化为数值,可以用库函数atof()来实现。而整体的实现需要考虑操作符栈的栈顶元素和即将入栈元素c的优先级,具体算法:
1.c>栈顶(optr),c入栈(optr),获取下一个字符并输出
2.c=栈顶(optr),栈顶(optr)弹出
3.c<栈顶,栈顶(optr)弹出,操作数栈(opnd)弹出两次,根据操作符的类型,计算两数的结果并入栈
最后当c为#且字符栈为空,说明计算结束;
具体代码如下:
#include<stdio.h> #include<stdlib.h> #include<math.h> #define MAX 16 typedef struct stack { int base, top; int stacksize; }Stack;//建一个栈 float* Initstack1(Stack *m);//操作数栈的初始化 char* Initstack2(Stack *m);//操作符栈的初始化 void Push1(float *p, Stack *m, float c);//入栈 void Push2(char *p, Stack *m, char c);//入栈 float Pop1(float *p, Stack *m);//出栈 char Pop2(char *p, Stack *m);//出栈 char compare(char a, char b);//比较ab两个操作符的优先级 float gettop1(float *p, Stack *m);//访问栈顶元素 char gettop2(char *p, Stack *m);//访问栈顶元素 float Ope(float a, char c, float b);//根据c操作符对ab进行运算 int compared(char a, char b);//处理多位数字 void write(float *p, Stack *m, float c);//修改操作(数字栈) int main() { int i = 0,j; //循环标记变量 Stack opnd, optr; //定义两个栈用来存储操作数和操作符 float *p1 = NULL;char *p2 = NULL; //定义栈指针 char c,before='#'; //接收字符 char t; float a, b; //接收弹出的字符和数字 float result; //暂存ab计算结果 float d; //接受字符转化成数字的值 FILE *fp; //文件指针 errno_t err; //检查变量 char change[12] = { 0 }; //定义数组用于暂存字符串 p1 = Initstack1(&opnd); p2 = Initstack2(&optr); //栈的初始化 printf("文件中的表达式是:"); Push2(p2, &optr, '#'); //#先入栈 err = fopen_s(&fp, "E:\\hu.txt", "r"); //以读的方式打开E盘中的文件hu.txt //如果err等于0则表示文件打开成功,否则打开失败 if (err != 0) { printf("Failure to open hu.txt\n"); system("pause"); //程序暂停一下 exit(0); //程序退出 } c = fgetc(fp); //从文件中获取字符,获取之后对应指针会移动到下个字符 putchar(c); //打印字符c while ((c != '#') || (optr.base!=optr.top)) { //当c为#且字符栈为空,说明计算结束,应当退出循环 if ((c >= '0' && c <= '9') || (c=='.'))//将操作数与操作符区分开 { i = 0; do{ change[i] = c; //把操作数对应的字符串写进数组 i++; before = c; c = fgetc(fp); putchar(c); } while (compared(c, before) == 1); d = atof(change); //调用库函数atfo把字符串转化为浮点型的数据 Push1(p1, &opnd, d); //操作数入栈 for (j = 0; j < 12; j++) //清空数组 { change[j] = 0; } } else switch (compare(c, gettop2(p2, &optr))) { case '>': Push2(p2, &optr, c); //操作符入栈 before = c; c = fgetc(fp); putchar(c); break; case '=': if (gettop2(p2, &optr) != '#') { t = Pop2(p2, &optr); //弹出操作符 before = c; c = fgetc(fp); putchar(c); } else{ t = Pop2(p2, &optr); //弹出操作符 } break; case '<': t = Pop2(p2, &optr); b = Pop1(p1, &opnd); a = Pop1(p1, &opnd);//弹出两个操作数 result = Ope(a, t, b); //ab运算后返回运算结果 Push1(p1, &opnd, result); //运算结果入栈 break; } } result = gettop1(p1, &opnd); printf("\n结果是:%.4f\n", result); fclose(fp);//关闭文件 system("pause"); return 0; } float* Initstack1(Stack *m) { float *p; p = (float*)malloc(MAX * sizeof(float));//申请内存 m->base = m->top = 0; //初始化栈为空 m->stacksize = MAX; //设置栈的大小 return p; //p指向申请的内存块的首部,也指向栈的底部 } char* Initstack2(Stack *m) { char *p; p = (char*)malloc(MAX * sizeof(char)); m->base = m->top = 0; m->stacksize = MAX; return p; } void Push1(float *p, Stack *m, float c)//入栈操作(数字栈) { p[m->top] = c; m->top++; } void Push2(char *p, Stack *m, char c)//入栈操作(字符栈) { p[m->top] = c; m->top++; } float Pop1(float *p, Stack *m) //出栈操作(数字栈) { float t; m->top--; t = p[m->top]; return t; } char Pop2(char *p, Stack *m) //出栈操作(字符栈) { char t; m->top--; t = p[m->top]; return t; } float gettop1(float *p, Stack *m) //读取栈的数据但是不改变栈的结构(数字栈) { float t; m->top--; t = p[m->top]; m->top++; return t; } char gettop2(char *p, Stack *m) //读取栈的数据但是不改变栈的结构(字符栈) { char t; m->top--; t = p[m->top]; m->top++; return t; } char compare(char a, char b) //比较即将写入的操作符与栈顶操作符的优先级 { switch (a) { case '^': switch (b) { case '+': return '>'; break; case '-': return '>'; break; case '*': return '>'; break; case '/': return '>'; break; case '(': return '>'; break; case ')': return '>'; break; case '#': return '>'; break; } case '+': switch (b) { case '+': return '<'; break; case '-': return '<'; break; case '*': return '<'; break; case '/': return '<'; break; case '(': return '>'; break; case ')': return '<'; break; case '#': return '>'; break; case '^': return '<'; break; } case '-': switch (b) { case '+': return '<'; break; case '-': return '<'; break; case '*': return '<'; break; case '/': return '<'; break; case '(': return '>'; break; case ')': return '<'; break; case '#': return '>'; break; case '^': return '<'; break; } case '*': switch (b) { case '+': return '>'; break; case '-': return '>'; break; case '*': return '<'; break; case '/': return '<'; break; case '(': return '>'; break; case ')': return '<'; break; case '#': return '>'; break; case '^': return '<'; break; } case '/': switch (b) { case '+': return '>'; break; case '-': return '>'; break; case '*': return '<'; break; case '/': return '<'; break; case '(': return '>'; break; case ')': return '<'; break; case '#': return '>'; break; case '^': return '<'; break; } case '(': switch (b) { case '+': return '>'; break; case '-': return '>'; break; case '*': return '>'; break; case '/': return '>'; break; case '(': return '>'; break; case '#': return '>'; break; case '^': return '<'; break; } case ')': switch (b) { case '+': return '<'; break; case '-': return '<'; break; case '*': return '<'; break; case '/': return '<'; break; case '(': return '='; break; case ')': return '<'; break; case '^': return '<'; break; } case '#': switch (b) { case '+': return '<'; break; case '-': return '<'; break; case '*': return '<'; break; case '/': return '<'; break; case ')': return '<'; break; case '#': return '='; break; case '^': return '<'; break; } } } float Ope(float a, char c, float b)//对ab进行+-*/运算 { switch (c) { case '+': return (a + b); case '-': return (a - b); case '*': return (a * b); case '/': if (b == 0) { printf("零做除数!!\n"); exit(0); } return (a / b); case '^': return (pow(a, b)); } } int compared(char a, char b) //处理多位数字 { if ((((a >= '0') && (a <= '9')) && ((b >= '0') && (b <= '9'))) || (a == '.') || (b == '.')) { return 1; } else return 0; } void write(float *p, Stack *m, float c)//修改操作(数字栈) { m->top--; p[m->top] = c; m->top++; }
文件内容:40.2-(30-20)*0.1#