程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言入門知識 >> 一個用C語言實現的科學計算器

一個用C語言實現的科學計算器

編輯:C語言入門知識

使用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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved