算法思路:
首先应该想怎样将操作数和操作符分开放入两个栈,此时可以用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#