算术表达式计算器
算术表达式计算器这是用C语言写的一个计算器,功能有点简单,只能对算术表达式进行计算! 源程序在VC++6.0下编译通过. 有兴趣的网友,可以下载测试一下.
设计的主要思路是:在只将表达式扫描一遍的条件下,运用一个能提取出一个数据项和一个符号项的函数,通过循环调用这个函数,并利用栈操作函数,实现对表达式的计算.对括号匹配的处理是用一个计数器变量,出现左括号加1,出现右括号减1,值为0说明括号匹配.
在给出源程序之前,先介绍一下,几个比较重要的函数.
函数 getexp
这个函数的原型是:int getexp(double *data,char *); 它能够提取出表达式中的数据项和符号项,对这个函数的调用,至少能提取出一个符号项, 根据提取的项不同,其返回值从1到8有个;返回负数表示在提取的过程中有错误;对负数的处理是;除了第一项的负数外,其它的负数必须用括号括起来;
函数 PopData , PushData , PopOprt ,PushOprt
这四个函数分别实现数据入栈\出栈,操作符入栈\出栈;
函数 calculat
原型是: int calculat(double data1,char oprt,double data2);能对两个数据根据oprt 进行计算,计算出现错误返回负数,否则返回正数;
函数 checkgram
原型是:int checkgram(int fsitua,int lsitua);配合getexp的返回值使用,对表达式进行语法检查;
函数 priority
原型是:int priority(char cal1,char cal2);比较操作符的优先级,为了保持一致性,把'\0'和括号也看作操作符;
函数 char_to_double
原型:double char_to_double(char DigitString[],int markpot,int markend);将字符串转变成双精度数;
下面是源
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define MAX_DATA_BIT 100
#define YES 1
#define NO 0
#define POINT_UNEXIST -15
#define MAXSIZE 100
int EXP_INIT=YES;
int BRACKET_COUNT=0;
//标识运算符,不包括括号
int iscalchar(char c);
//标识空白字符,不包括换行符
int is_space(char c);
//标识表达式第一个合法字符
int isFIRSTallow(char c);
//标识表达式的合法字符
int isallow(char c);
//函数,将字符串转换成双精度数
double char_to_double(char DigitString[],int markpot,int markend);
//得到表达式的首项,并检查字符是否合法
int getexp(double *data,char *oprt);
typedef struct
{
char oprt_stack[MAXSIZE];
double data_stack[MAXSIZE];
char oprt_in,oprt_out,*oprt_curp;
double data_in,data_out,*data_curp;
}stack;
/* 一组栈操作函数 */
/*操作成功返回1,失败返回0 */
int PopData(stack *p);
int PushData(stack *p);
int PopOprt(stack *p);
int PushOprt(stack *p);
void clear(stack *p);
//语法检查函数,返回2表示表达式结束
int checkgram(int fsitua,int lsitua);
//功能函数,比较两个运算符的优先级
int priority(char cal1,char cal2);
//错误处理函数,丢弃出错后所有字符,并打印出错信息
void error(int state);
//计算函数,有发现简单逻辑错误的功能
int calculat(double data1,char oprt,double data2,double *result);
stack STK;
void main()
{
int FState,LState,GramState,CalcuState;
double result,TempData;
char TempOprt;
STK.data_curp=STK.data_stack;
STK.oprt_curp=STK.oprt_stack;
while(1){
clear(&STK);
EXP_INIT=YES;
BRACKET_COUNT=0;
LState=100;
GramState=1;
CalcuState=1;
printf("input express> ");
do{
FState=LState;
if((LState=getexp(&STK.data_in,&STK.oprt_in))<0){
error(LState);
break;
}
if((GramState=checkgram(FState,LState))<0){
error(GramState);
break;
}
//-------------对表达式的计算------------------------------------------------------
if(LState==1||LState==2||LState==3||LState==4)
PushData(&STK);
if(LState==2||(LState==6&&(FState==3||FState==7))){
TempOprt=STK.oprt_in;
STK.oprt_in='*';
}
while(priority(*(STK.oprt_curp),STK.oprt_in)>0
&& *STK.oprt_curp!='(' && STK.oprt_curp!=STK.oprt_stack){
PopData(&STK);
TempData=STK.data_out;
PopData(&STK);
PopOprt(&STK);
CalcuState=calculat(STK.data_out,STK.oprt_out,TempData,&result);
if(CalcuState<0) break;
STK.data_in=result;
PushData(&STK);
}
if(*STK.oprt_curp=='(' && (LState==3||LState==7)) PopOprt(&STK);
if(!(LState==3||LState==4||LState==7||LState==8)) PushOprt(&STK);
if(LState==2||(LState==6&&(FState==3||FState==7))){
STK.oprt_in=TempOprt;
PushOprt(&STK);
}
if(CalcuState<0){
error(CalcuState);
break;
}
}while (LState!=4&&LState!=8);
if((LState==4||LState==8)&&BRACKET_COUNT!=0) error(-8);
if((LState==4||LState==8) && BRACKET_COUNT==0 && GramState>0 && CalcuState>0 && FState+LState!=108)
printf("the result is: %f\n",STK.data_in);
putchar('\n');
if(STK.oprt_in!='\n') while(getchar()!='\n');
STK.oprt_in='\0';
}
}
int isoprt( char c)
{
if (c=='+'||c=='-'||c=='*'||c=='/'||c=='^')
return 1;
else
return 0;
}
int is_space(char c)
{
if (c==' '||c=='\t'||c=='\v')
return 1;
else
return 0;
}
int isFIRSTallow(char c)
{
if (c=='.'||c=='-'||c=='('||isdigit(c))
return 1;
else
return 0;
}
int isallowed(char c)
{
if (c=='.'||isoprt(c)||c=='('||isdigit(c)||c==')')
return 1;
else
return 0;
}
double char_to_double(char data[],int markpot,int markend)
{
int i;
double sumz=0,sumf=0;
if (data[0]!='-'){
for (i=0;i<markpot;++i)
sumz=sumz*10+(data[i]-'0');
for (i=markend-1;i>markpot;--i)
sumf=sumf*0.1+(data[i]-'0');
return sumz+sumf*0.1;
}
else
{
for (i=1;i<markpot;++i)
sumz=sumz*10+(data[i]-'0');
for (i=markend-1;i>markpot;--i)
sumf=sumf*0.1+(data[i]-'0');
return -(sumz+sumf*0.1);
}
}
int getexp (double *data,char *oprt)
{
int c,i=0,mrkpot=POINT_UNEXIST;
char temp[MAX_DATA_BIT];
while (is_space(c=getchar()));
if (c=='\n') {*oprt=c;return 8;}
if (!isallowed(c)) return -1;
if (EXP_INIT==YES) {
if(!isFIRSTallow(c)) return -4;
if(c=='('){++BRACKET_COUNT;*oprt=c;return 6;}
else{
temp[i]=c;
if (c=='.') mrkpot=i;
++i;
}
}
else {
if (!isallowed(c)) return -1;
if (c=='(') {
++BRACKET_COUNT;
*oprt=c;
EXP_INIT=YES;
return 6;
}
if (c==')') {
--BRACKET_COUNT;
*oprt=c;
return 7;
}
if (isoprt(c)) {
*oprt=c;
return 5;
}
else {
temp[i]=c;
if (c=='.') mrkpot=i;
++i;
}
}
//期望等到一个完整的数据项************************
while ((isdigit(c=getchar())||c=='.') && i<MAX_DATA_BIT){
if (c=='.'&&mrkpot!=POINT_UNEXIST) return -2;
else {
temp[i]=c;
if (c=='.') mrkpot=i;
++i;
}
}
//**************************************************
if (i==1&&!isdigit(temp[0])||i==2&&!isdigit(temp[0])&&!isdigit(temp[1])) {*oprt=c;return -2;}
if(i==MAX_DATA_BIT&&(isdigit(c)||c=='.')) {*oprt=c;return -3;}//返回值还需要进行字符常量化
if (mrkpot==POINT_UNEXIST) mrkpot=i;
*data=char_to_double (temp,mrkpot,i);
EXP_INIT=NO;
if (is_space(c)) while (is_space(c=getchar()));
if (c=='\n') {*oprt=c;return 4;}
if (!isoprt(c)&&c!='('&&c!=')') {*oprt=c;return -1;}
*oprt=c;
if (isoprt(c)) return 1;
if (c=='(') {
++BRACKET_COUNT;
EXP_INIT=YES;
return 2;
}
else {
--BRACKET_COUNT;
return 3;
}
}
int priority (char cal1,char cal2)
{
if (cal1=='\0'||cal1=='('||cal2=='('||cal2=='^'||((cal2=='*'||cal2=='/')&&(cal1=='+'||cal1=='-')))
return -1;
else
return 1;
}
void error (int state)
{
if (state==-1)
printf("表达式出现不合法字符!\n");
else if(state==-2)
printf("表达式有不合法数据项!\n");
else if(state==-3)
printf("表达式中数据太大了!\n");
else if(state==-4)
printf("表达式有语法错误!\n");
else if(state==-5)
printf("表达式逻辑错误\n除数不能为0!\n");
else if(state==-6)
printf("表达式逻辑错误\n幂运算错误!\n");
else if(state==-7)
printf("栈操作失败,表达式可能太长!\n");
else if(state==-8){
printf("表达式的括号不匹配!");
}
}
int calculat (double data1,char calchar,double data2,double *result)
{
switch(calchar){
case '+':*result=data1+data2;return 1;
case '-':*result=data1-data2;return 1;
case '*':*result=data1*data2;return 1;
case '/':if (data2!=0.0) {*result=data1/data2;return 1;}
else return -5;
case '^':if (data2>0.0||data1!=0) {*result=pow(data1,data2);return 1;}
else return -6; /*没有零的零次方*/
}
}
int checkgram (int fsitua,int lsitua) //返回-20表示表达式结束
{
switch (fsitua)
{
case 1:case 5:if (lsitua==1||lsitua==2||lsitua==3||lsitua==4||lsitua==6) return 1;
else return -4;
case 2: case 6:if (lsitua==1||lsitua==2||lsitua==3||lsitua==6) return 1;
else return -4;
case 3: case 7:if (lsitua==5||lsitua==6||lsitua==7||lsitua==8) return 1;
else return -4;
default:return 1;
}
}
int PopData(stack *p)
{
if (p->data_curp == p->data_stack) return -1;
else {
p->data_out = *p->data_curp;
*p->data_curp=0;
p->data_curp--;
return 1;
}
}
int PushData(stack *p)
{
if (p->data_curp==p->data_stack+MAXSIZE-1) return -1;
else {
p->data_curp++;
*p->data_curp=p->data_in;
return 1;
}
}
int PopOprt(stack *p)
{
if (p->oprt_curp == p->oprt_stack) return -1;
else {
p->oprt_out = *p->oprt_curp;
*p->oprt_curp = '\0';
p->oprt_curp --;
return 1;
}
}
int PushOprt(stack *p)
{
if (p->oprt_curp == p->oprt_stack + MAXSIZE-1) return -1;
else {
p->oprt_curp ++;
*p->oprt_curp = p->oprt_in;
return 1;
}
}
void clear(stack *p)
{
while(p->data_curp != p->data_stack)
*(p->data_curp--) = 0;
while(p->oprt_curp != p->oprt_stack)
*(p->oprt_curp--) = '\0';
}