欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一个用C语言实现的科学计算器

程序员文章站 2022-03-23 19:36:50
使用C语言写的科学计算器,可以实现四则运算、三角函数运算、指对数运算;优先级正确;能智能屏蔽空格,能识别输入错误和运算错误,能实现继续运算、清空运算结果和有效退出的功能 #i...

使用C语言写的科学计算器,可以实现四则运算、三角函数运算、指对数运算;优先级正确;能智能屏蔽空格,能识别输入错误和运算错误,能实现继续运算、清空运算结果和有效退出的功能

#include 
#include 
#include 

#define INPUT_MAX 1000
#define NODE_MAX 500
#define NUM_OPT 20
#define LEN_OPT 6
#define NUM_OPS 200

typedef enum{
	Opd=0,
	Opt=1
}Type;
typedef struct{
	int opt;
	double opd;
	Type tp;
}Node;

//括号栈,检测括号是否匹配
char brackets[NUM_OPS];
int bb=0;

int input(Node *in);
int translate(char *p,Node *re,int *len);
double translateopd(char *p,int *len);
int translateopt(char *p,int *len);
int cmp(const char *s,const char *d);
int calculate(Node *n,double *r);
int sclt(int opr,double *opd);
int dclt(int opr,double *opd1,double opd2);
int prid(int c);

/*功能:表达式输入和转换
 *      接收输入并翻译为操作符和操作数存入表达式链
 *输入:表达式链的地址
 *输出:执行状态,正确返回1,错误返回0
 */
int input(Node *in)
{
	//input->string
	char ins[INPUT_MAX]={0};
	int insi=0;
	char temp_in=0;
	int len=0;
	//检测开头的空格
	while(' '==(ins[0]=getchar()));
	//检测是不是直接输入了一个回车
	if(ins[0]!='\n')
	{
		do{
			temp_in=getchar();
			//只能忽略多余空格
			if(ins[insi]==' '&&temp_in==' ')
				continue;
			ins[++insi]=temp_in;
		}while(temp_in!='\n');
		ins[insi]=0;
	}

	insi=0;
	//输入回车直接输出0
	if(ins[0]=='\n')
		in->tp=Opd,in->opd=0.0,in++;
	else
		//压入表达式链
		while(ins[insi])
		{
			if(translate(ins+insi,in++,&len))
				insi+=len;
			else
				return 0;
		}
	//自动添加等号
	if((in-1)->opt!='=')
        in->opt='=',in->tp=Opt,in++;
	in->opt=-1,in->tp=Opt;
	return 1;
}
/*功能:翻译字符串为操作数或操作符
 *输入:字符串地址,翻译返回节点,操作数和操作符长度返回地址
 *输出:翻译结果状态
 */
int translate(char *p,Node *re,int *len)
{
	if(*p>='0'&&*p<='9')
	{
		re->tp=Opd;
		re->opd=translateopd(p,len);
		return 1;
	}
	else if(*p=='e'||*p=='p')
	{
		if(*p=='e')
		{
			re->tp=Opd;
			re->opd=M_E;
			*len=1;
			if(p[1]==' ')
				(*len)++;	//十分重要,此处必须加括号
			return 1;
		}
		else
		{
			if(p[1]=='i')
			{
				re->tp=Opd;
				re->opd=M_PI;
				*len=2;
				if(p[2]==' ')
					(*len)++;
				return 1;
			}
			else
				return 0;
		}
	}
	else
	{
		re->tp=Opt;
		re->opt=translateopt(p,len);
		if(re->opt)
			return 1;
		else
			return 0;
	}
}
/*功能:翻译操作数
 */
double translateopd(char *p,int *len)
{
	int flag=0;
	int pointnum=1;
	double temp=0;
	int i=0;
	do{
		if(!flag&&p[i]!='.')
			temp=temp*10+p[i++]-'0';
		else if(!flag&&p[i]=='.')
			flag=1,i++;
		else
			temp+=(p[i++]-'0')*pow(0.1,pointnum),pointnum++;
	}while((p[i]>='0'&&p[i]<='9')||p[i]=='.');
	if(p[i]==' ')
		i++;
	*len=i;
	return temp;
}
/*功能:翻译操作数
 *      如果运算符非法,则返回0,合法则返回非零标志
 */
int translateopt(char *p,int *len)
{
	char fu[NUM_OPT][LEN_OPT]={"+","-","*","/","^","(",")","sin","cos","tan","asin","acos","atan","ln","lg","="};
	int fu_int[NUM_OPT]={'+','-','*','/','^','(',')','s','c','t','s'+'a','c'+'a','t'+'a','n','g','='};
	int i=0;
	for(i=0;itp==Opt&&n->opt=='-')
		OPRD[db]=0.0,db++;	//Push(&OPRD,0.0); 
	while(1)
	{
		//判断前面有没有负号
		if(n->tp==Opd)
		{
			OPRD[db]=n->opd,db++,n++;	//Push(&OPRD,n->opd),n++;
		}
		else
		{
			//双目运算符
            if(prid(n->opt))
            {
                //if(!GetTop(OPRT,&top))
				if(tb)
					top=OPRT[tb-1];
                if(!tb)
                {
                    if(n->opt=='='||n->opt==')')
                    {
						if(n->opt==')')
						{
							bb--;	//if(!Pop(&brackets,&temp))
							if(bb<0)
							{
								printf("Bracket does not match!");
								return 0;
							}
						}
                        break;
                    }
                    else
						OPRT[tb]=n->opt,tb++,n++;	//Push(&OPRT,n->opt),n++;
                    continue;
                }
                if(prid(top)==0)
                {
                    //Pop(&OPRD,&a);
                    //Pop(&OPRT,&o);
					db--;
					a=OPRD[db];
					tb--;
					o=OPRT[tb];
                    if(sclt(o,&a))
                    {
						OPRD[db]=a,db++;	//Push(&OPRD,a);
                        continue;
                    }
                    else
                        return 0;
                }
                if(prid(top)>=prid(n->opt))
                {
                    //Pop(&OPRD,&b);
                    //Pop(&OPRD,&a);
                    //Pop(&OPRT,&o);
					db--;
					b=OPRD[db];
					db--;
					a=OPRD[db];
					tb--;
					o=OPRT[tb];
                    if(dclt(o,&a,b))
                    {
						OPRD[db]=a,db++;	//Push(&OPRD,a);
                    }
                    else
                        return 0;
                }
                else
                {
					OPRT[tb]=n->opt,tb++,n++;	//Push(&OPRT,n->opt),n++;
                }
            }
            else
            {
				//单目运算符和括号
                double x=0.0;
                if(n->opt=='(')
                {
					brackets[bb]='(',bb++;	//Push(&brackets,'(');
                    if(len=calculate(n+1,&x))
                    {
						OPRD[db]=x,db++;	//Push(&OPRD,x);
                        n+=len,n++;
						if(n->tp==Opt&&n->opt==-1)
						{
							printf("Bracket does not match!");
							return 0;
						}
                    }
                    else
                        return 0;
                }
                else
                {
					OPRT[tb]=n->opt,tb++;	//Push(&OPRT,n->opt);
                    n++;
                }
            }
        }
	}
	*r=OPRD[db-1];
	return n-nb+1;
}
/*功能:单目运算
 */
int sclt(int opr,double *opd)
{
    switch(opr)
    {
    case 's':
        *opd=sin(*opd);
        break;
    case 'c':
        *opd=cos(*opd);
        break;
    case 't':
        *opd=tan(*opd);
        break;
    case 'a'+'s':
        if(*opd<-1||*opd>1)
        {
            printf("Beyond asin()!");
            return 0;
        }
        else
            *opd=asin(*opd);
        break;
    case 'a'+'c':
        if(*opd<-1||*opd>1)
        {
            printf("Beyond acos()!");
            return 0;
        }
        else
            *opd=acos(*opd);
        break;
    case 'a'+'t':
        if(*opd>-3.141592654/2&&*opd<3.141592654/2)
            *opd=atan(*opd);
        else
        {
            printf("Beyond atan()!");
            return 0;
        }
        break;
    case 'n':
        if(*opd>0)
            *opd=log(*opd);
        else
        {
            printf("Beyond ln()!");
            return 0;
        }
        break;
    case 'g':
        if(*opd>0)
            *opd=log10(*opd);
        else
        {
            printf("Beyond lg()!");
            return 0;
        }
        break;
    }
    return 1;
}
/*功能:双目运算
 */
int dclt(int opr,double *opd1,double opd2)
{
    switch(opr)
    {
        case '+':
            *opd1 = *opd1+opd2;break;
        case '-':
            *opd1 = *opd1-opd2;break;
        case '*':
            *opd1 = (*opd1)*opd2;break;
        case '/':
            if(opd2>pow(0.1,8)||opd2<0-pow(0.1,8))
                *opd1 = (*opd1)/opd2;
            else
            {
                printf("Error 1/0 !");
                return 0;
            }
            break;
        case '^':
            *opd1 = pow(*opd1,opd2);break;
    }
    return 1;
}
/*功能:判断优先级
 */
int prid(int c)
{
    switch(c)
    {
        case '+':
        case '-':
		case '=':
		case ')':
        return 1;break;
        case '*':
        case '/':
        return 2;break;
        case '^':
        return 3;break;
        default :return 0;break;
    }
}
int main()
{
	int c=0;
	while(1)
	{
		Node nodes[NODE_MAX]={0};
		double r=0.0;
		//清空括号栈
		bb=0;	//InitStack(&brackets);
		printf("Enter: ");
		//输入
		if(!input(nodes))
		{
			printf("Input Error!");
			continue;
		}
		//计算
		if(calculate(nodes,&r))
		{
			if(bb)
			{
				printf("Bracket does not match!");
				continue;
			}
			if(floor(r)==r)
				printf("%d",(int)r);
			else
				printf("%.4f",r);
		}
		c=getchar();
		if(c=='q')	//退出
			break;
		else if(c=='c')	//清屏
			system("clear");
		if(c!='\n')
			getchar();
	}
	printf("Quit...\n");
	return 0;
}