*/ --------------------------------------------------------------------------------------
*/ 出自: 编程中国 http://www.bc-cn.net
*/ 作者: josen0205 QQ:7007873
*/ 时间: 2007-9-22 编程论坛首发
*/ 声明: 尊重作者劳动,转载请保留本段文字
*/ --------------------------------------------------------------------------------------
为了方便了解流程,在程序中把计算过程也输出了.而且栈操作的实现部分也是自己实现的.
程序用两个栈,optr寄存运算符,opnd寄存操作数和运算结果.输入的表达式以等号结束,例如:2*(1+2)=
/**************表达式计算器************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <malloc.h>
#define STACK_SIZE 100
#define APPEND_SIZE 10
union SNode{
float data; /*存放操作数或者计算结果*/
char ch; /*存放运算符*/
};
struct Stack{
SNode *top;
SNode *base;
int size;
};
/*栈操作函数*/
int InitStack(Stack &S); /*创建栈*/
int DestroyStack(Stack &S); /*销毁栈*/
int ClearStack(Stack &S); /*清空栈*/
int GetTop(Stack S, SNode &e); /*取出栈顶结点并返回节点值*/
int Push(Stack &S,SNode e); /*将结点e压入栈*/
int Pop(Stack &S,SNode &e); /*删除栈顶结点并返回其节点值*/
/*表达式计算器相关函数*/
char get_precede(char s,char c); /*判断运算符s和c的优先级*/
int isOpr(char c); /*判断输入的字符是不是运算符,是则返回0,否返回1*/
float operate(float x, char opr, float y); /*计算x和y经过运算符opr计算后的结果*/
float compute(); /*表达式结算器主函数*/
char *killzero(float result); /*去掉结果后面的0*/
int InitStack(Stack &S)
{
S.base=(SNode *)malloc(STACK_SIZE * sizeof(union SNode));
if(S.base==NULL)
{
printf("动态分配内存失败!");
return -1;
}
S.top=S.base;
S.size=STACK_SIZE;
return 0;
}
int DestroyStack(Stack &S)
{
free(S.base);
return 0;
}
int ClearStack(Stack &S)
{
S.top=S.base;
return 0;
}
int GetTop(Stack S,SNode &e)
{
if(S.top==S.base)
{
printf("栈以为空!");
return -1;
}
e=*(S.top-1);
return 0;
}
int Push(Stack &S,SNode e)
{
if(S.top-S.base>=S.size)
{
S.base=(SNode *)realloc(S.base,(S.size+APPEND_SIZE)*sizeof(union SNode));
if(S.base==NULL)
{
printf("动态分配内存失败!");
return -1;
}
S.top=S.base+S.size;
S.size+=APPEND_SIZE;
}
*S.top=e;
S.top++;
return 0;
}
int Pop(Stack &S,SNode &e)
{
if(S.top==S.base)
{
printf("栈为空!");
return -1;
}
e=*(S.top-1);
S.top--;
return 0;
}
char get_precede(char s,char c)
{
switch(s)
{
case '+':
case '-':
if(c=='+'||c=='-') return '>';
else if(c=='*'||c=='/') return '<';
else if(c=='(') return '<';
else if(c==')') return '>';
else return '>';
case '*':
case '/':
if(c=='+'||c=='-') return '>';
else if(c=='*'||c=='/') return '>';
else if(c=='(') return '<';
else if(c==')') return '>';
else return '>';
case '(':
if(c=='+'||c=='-') return '<';
else if(c=='*'||c=='/') return '<';
else if(c=='(') return '<';
else if(c==')') return '=';
else return 'E';
case ')':
if(c=='+'||c=='-') return '>';
else if(c=='*'||c=='/') return '>';
else if(c=='(') return 'E';
else if(c==')') return '>';
else return '>';
case '#':
if(c=='+'||c=='-') return '<';
else if(c=='*'||c=='/') return '<';
else if(c=='(') return '<';
else if(c==')') return 'E';
else return '=';
default:
break;
}
return 0;
}
int isOpr(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='=')
return 0;
else
return 1;
}
float operate(float x, char opr, float y)
{
float result;
switch (opr)
{
case '+':
result = x + y;
break;
case '-':
result = x - y;
break;
case '*':
result = x * y;
break;
case '/':
if (y == 0)
{
printf("Divided by zero!\n");
return 0;
}
else
{
result = x / y;
break;
}
default:
printf("Bad Input.\n");
return 0;
}
return result;
}
float compute() /*计算的时候运算符栈顶结点的优先级始终最低*/
{
Stack optr,opnd;
union SNode opr_in,opn_in,opr_top,opn_tmp,e,a,b,opr_t;
char c;
char buf[16];
int i=0;
InitStack(optr); /*用于寄存运算符*/
InitStack(opnd); /*用于寄存操作数和计算结果*/
memset(buf,0,sizeof(buf));
printf("Enter your expression:");
opr_in.ch='#';
Push(optr,opr_in); /*'#'入栈*/
GetTop(optr,opr_top);
c=getchar();
while(c!='='||opr_top.ch!='#')
{
if(isOpr(c)!=0) /*不是运算符则保存到buf中,以便得到操作数*/
{
buf[i]=c;
i++;
c=getchar();
}
else /*是运算符*/
{
buf[i]='\0';
if(i) /*判断buf是否为空,不为空则取出值,压入操作数寄存器,并将buf置为空*/
{
opn_in.data=(float)atof(buf);
Push(opnd,opn_in);
printf("opnd入栈:[%f]\n",opn_in.data);
i=0;
memset(buf,0,sizeof(buf));
}
opr_in.ch=c;
switch(get_precede(opr_top.ch,c)) /*根据运算符优先级做相应操作*/
{
case '<': /*优先级小于栈顶结点,则运算符入栈*/
Push(optr,opr_in);
printf("optr入栈:[%c]\n",opr_in.ch);
c=getchar();
break;
case '=': /*优先级等于栈顶结点,即是括号,去掉括号*/
Pop(optr,e);
printf("optr出栈:去掉括号\n");
c=getchar();
break;
case '>': /*优先级大于栈顶结点,取操作数和运算符计算*/
Pop(optr,opr_t);
printf("optr出栈:[%c]\n",opr_t.ch);
if(Pop(opnd,b)<0)
{
printf("Bad Input!\n");
fflush(stdin);
return -1;
}
printf("opnd出栈:[%f]\n",b.data);
if(Pop(opnd,a)<0)
{
printf("Bad Input!\n");
fflush(stdin);
return -1;
}
printf("opnd出栈:[%f]\n",a.data);
opn_tmp.data=operate(a.data,opr_t.ch,b.data); /*计算*/
Push(opnd,opn_tmp); /*将计算结果压入操作数寄存器*/
printf("结果入栈:[%f]\n",opn_tmp.data);
break;
}
}
GetTop(optr,opr_top); /*取出运算符寄存器栈顶结点*/
}
GetTop(opnd,opn_tmp);
DestroyStack(optr);
DestroyStack(opnd);
return opn_tmp.data;
}
char *killzero(char *res,float result)
{
int i;
sprintf(res,"%f",result);
i=(int)strlen(res)-1;
while(i&&res[i]=='0')
{
res[i]='\0';
i--;
}
if(res[i]=='.')
res[i]='\0';
return res;
}
int main()
{
char ch;
char res[64];
float result;
while(1)
{
result=compute();
printf("\nThe result is:%s\n",killzero(res,result));
printf("Do you want to continue(y/n)?:") ;
ch=getch();
putchar(ch);
if(ch=='n'||ch=='N')
break;
else
system("cls");
}
return 0;
}
[此贴子已经被作者于2007-11-12 22:00:51编辑过]
----------------解决方案--------------------------------------------------------
好长啊~~~呵呵~厉害
----------------解决方案--------------------------------------------------------
这真是用c做出来的吗??
好多都是我没学到过的!!
厉害啊!!!
有很多不明白的;
估计我们老师还没教到这里!!
我要在一年内赶上你们!!!
----------------解决方案--------------------------------------------------------
学习。。
----------------解决方案--------------------------------------------------------
楼主,你这个程序还有点小BUG
我刚才试了下,如果输入4+5/0=
应该提示出错的,这个在你的过程中体现了,但你的程序最后却给出了结果为4
也就是说,虽然5/0是错误的,但你默认把这个直设置为零了
应该,出现分母为零的情况时,直接跳出程序并提示错误
不过,很赞楼主的程序,你可以用MFC做个外表,这样就更直接点了
----------------解决方案--------------------------------------------------------