Code Bye

c语言 函数型计算器,求添加计算平方、三角函数的功能

C语言写的代码能计算加减乘除表达式,但是不能计算平方和三角函数

// EX6_08.CPP
// A program to implement a calculator

#include <stdio.h>  // For input/output
#include <stdlib.h>	// For the exit() function
#include <ctype.h>  // For the isdigit() function
#include <string.h> // For the strcpy() function

void eatspaces(char * str);					// Function to eliminate blanks
double expr(char * str);					// Function evaluating an expression
double term(char * str, int * pindex);	    // Function analyzing a term
double number(char * str, int * pindex);    // Function to recognize a number
char * extract(char * str, int * index);    // Function to extract a substring

const int MAX = 80;			// Maximum expression length including ""\0""

int main(void)
{
	char buffer[MAX];		// Input area for expression to be evaluated
	char c;
	int i;

	printf("Welcome to your friendly calculator.\n");
	printf("Enter an expression, or an empty line to quit.\n");

	for(;;)
	{
		i=0;
		scanf("%c",&c); // Read an input line
		while(c!=""\n"")
        {
            buffer[i++]=c;
            scanf("%c",&c);


		}
		buffer[i]=""\0"";

		eatspaces(buffer);						// Remove blanks from input

		if(!buffer[0])							// Empty line ends calculator
			 return 0;

		printf( "\t= %f\n\n",expr(buffer));		// Output value of expression
	}

}


// Function to eliminate blanks from a string
void eatspaces(char * str)
{
	int i=0;				 // ""Copy to"" index to string
	int j=0;				 // ""Copy from"" index to string

	while((*(str+i) = *(str+j++)) != ""\0"")	 // Loop while character copied is not \0
		if(*(str+i) != "" "")					 // Increment i as long as
			 i++;							 //	character is not a blank
	return;
}


// Function to evaluate an arithmetic expression
double expr(char * str)
{
	double value = 0;					// Store result here
	int index = 0;						// Keeps track of current character position

	value = term(str, &index);	        // Get first term

	for(;;)								// Infinite loop, all exits inside
	{
		switch(*(str+index++))	        // Choose action based on current character
		{
			 case ""\0"":					// We""re at the end of the string
				return value;			//	so return what we have got

			 case ""+"":							// + found so add in the
				value += term(str, &index);		//	next term
				break;

			 case ""-"":							// - found so subtract
				value -= term(str, &index);		//	the next term
				break;

			 default:											 // If we reach here the string
				printf("Arrrgh!*#!! There""s an error.\n");
				exit(1);
			}
	 }
}


// Function to get the value of a term
double term(char * str, int * pindex)
{
	double value = 0;					// Somewhere to accumulate the result

	value = number(str, pindex);		// Get the first number in the term

	// Loop as long as we have a good operator
	while((*(str+(*pindex))==""*"")||(*(str+(*pindex))==""/""))
	{

		if(*(str+(*pindex))==""*"")					// If it""s multiply,
        {
            ++(*pindex);
			 value *= number(str, pindex);			//	multiply by next number
        }

		if(*(str+(*pindex))==""/"")					// If it""s divide,
        {
            ++(*pindex);
			 value /= number(str, pindex);			//	divide by next number
        }
	 }
	 return value;						 // We""ve finished, so return what we""ve got
}


// Function to recognize a number in a string
double number(char * str, int * pindex)
{
	double value = 0.0;						// Store the resulting value

	char * psubstr;                         // Pointer for substring
	if(*(str + (*pindex)) == ""("")           // Start of parentheses
    {
        ++(*pindex);
        psubstr = extract(str, pindex);     // Extract substring in brackets
        value = expr(psubstr);              // Get the value of the substring
        return value;                       // Return substring value
    }

	while(isdigit(*(str+(*pindex))))		// Loop accumulating leading digits
		value=10*value + (*(str+(*pindex)++) - 48);

											// Not a digit when we get to here

	if(*(str+(*pindex))!=""."")				// so check for decimal point
		return value;						// and if not, return value

	double factor = 1.0;					// Factor for decimal places
 	while(isdigit(*(str+(++(*pindex)))))	// Loop as long as we have digits
	{
		factor *= 0.1;								 // Decrease factor by factor of 10
		value=value + (*(str+(*pindex))-48)*factor;	 // Add decimal place
	}

	return value;										 // On loop exit we are done
}

// Function to extract a substring between parentheses
// (requires string.h)
char * extract(char * str, int * pindex)
{
    char buffer[MAX];           // Temporary space for substring
    char * pstr = NULL;         // Pointer to new string for return
    int numL = 0;               // Count of left parentheses found
    int bufindex = *pindex;     // Save starting value for index
    do
    {
        buffer[(*pindex) - bufindex] = *(str + (*pindex));
        switch(buffer[(*pindex) - bufindex])
        {
            case "")"":
                if(numL == 0)
                {
                    buffer[(*pindex) - bufindex] = ""\0"";    // Replace "")"" with ""\0""
                    ++(*pindex);
                    pstr = (char *) malloc((*pindex) - bufindex + 1);
                    if (!pstr)
                    {
                        printf("Memory allocation failed, program terminated.") ;
                        exit(1);
                    }
                    strcpy(pstr, buffer);   // Copy substring to new memory
                    return pstr;            // Return substring in new memory
                }
                else
                    numL--;     // Reduce count of ""("" to be matched
                break;
            case ""("":
                    numL++;     // Increase count of ""("" to be // matched
                    break;
        }
    } while(*(str + (*pindex)++) != ""\0"");      // Loop - don""t overrun end of string
    printf("Ran off the end of the expression, must be bad input.\n");
    exit(1);
}

 
平方return x*x;
三角函数:直接库函数,#include <math.c> sin()
 
這個計算器 的計算,是不是只能計算
類似於a*b+c*d这样格式的表逹式?

對於三角函數,楼上已經說了。有對應的庫,google一下就有大把答案。

 
再math中有好多库函数,可以利用
 
原理的话
平方可以用二分法
三角函数貌似只能用级数

50分

仅供参考:
/*---------------------------------------
函数型计算器(VC++6.0,Win32 Console)程序由 yu_hua 于2007-07-27设计完成
功能:
目前提供了10多个常用数学函数:
    ⑴正弦sin
    ⑵余弦cos
    ⑶正切tan
    ⑷开平方sqrt
    ⑸反正弦arcsin
    ⑹反余弦arccos
    ⑺反正切arctan
    ⑻常用对数lg
    ⑼自然对数ln
    ⑽e指数exp
    ⑾乘幂函数∧
用法:
如果要求2的32次幂,可以打入2^32<回车>
如果要求30度角的正切可键入tan(Pi/6)<回车>
注意不能打入:tan(30)<Enter>
如果要求1.23弧度的正弦,有几种方法都有效:
sin(1.23)<Enter>
sin 1.23 <Enter>
sin1.23  <Enter>
如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter>
此外两函数表达式连在一起,自动理解为相乘如:sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77)
当然你还可以依据三角变换,再用sin(1.23+0.77)也即sin2验证一下。
本计算器充分考虑了运算符的优先级因此诸如:2+3*4^2 实际上相当于:2+(3*(4*4))
另外函数名前面如果是数字,那么自动认为二者相乘.
同理,如果某数的右侧是左括号,则自动认为该数与括弧项之间隐含一乘号。
如:3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1)
又如:4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5)
此外,本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。
----------------------------------------*/
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <stdio.h>
#include <string.h>
#include <windows.h>
using namespace std;
const char Tab=0x9;
const int  DIGIT=1;
const int MAXLEN=16384;
char s[MAXLEN],*endss;
int pcs=15;
double fun(double x,char op[],int *iop) {
    while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>
        switch (op[*iop-1]) {
        case  7: x=sin(x);  (*iop)--;break;
        case  8: x=cos(x);  (*iop)--;break;
        case  9: x=tan(x);  (*iop)--;break;
        case 10: x=sqrt(x); (*iop)--;break;
        case 11: x=asin(x); (*iop)--;break;
        case 12: x=acos(x); (*iop)--;break;
        case 13: x=atan(x); (*iop)--;break;
        case 14: x=log10(x);(*iop)--;break;
        case 15: x=log(x);  (*iop)--;break;
        case 16: x=exp(x);  (*iop)--;break;
        }
    return x;
}
double calc(char *expr,char **addr) {
    static int deep; //递归深度
    static char *fname[]={ "sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp",NULL};
    double ST[10]={0.0}; //数字栈
    char op[10]={""+""}; //运算符栈
    char c,*rexp,*pp,*pf;
    int ist=1,iop=1,last,i;

    if (!deep) {
        pp=pf=expr;
        do {
            c = *pp++;
            if (c!="" ""&& c!=Tab)
                *pf++ = c;
        } while (c!=""\0"");
    }
    pp=expr;
    if ((c=*pp)==""-""||c==""+"") {
        op[0] = c;
        pp++;
    }
    last = !DIGIT;
    while ((c=*pp)!=""\0"") {
        if (c==""("") {//左圆括弧
            deep++;
            ST[ist++]=calc(++pp,addr);
            deep--;
            ST[ist-1]=fun(ST[ist-1],op,&iop);
            pp = *addr;
            last = DIGIT;
            if (*pp == ""(""||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是:当右圆括弧的右恻为左圆括弧或函数名字时,默认其为乘法
                op[iop++]=""*"";
                last = !DIGIT;
                c = op[--iop];
                goto operate ;
            }
        }
        else if (c=="")"") {//右圆括弧
            pp++;
            break;
        } else if (isalpha(c)) {
            if (!strnicmp(pp,"Pi",2)) {
                if (last==DIGIT) {
                    cout<< "π左侧遇)" <<endl;exit(1);
                }
                ST[ist++]=3.14159265358979323846264338328;
                ST[ist-1]=fun(ST[ist-1],op,&iop);
                pp += 2;
                last = DIGIT;
                if (!strnicmp(pp,"Pi",2)) {
                    cout<< "两个π相连" <<endl;exit(2);
                }
                if (*pp==""("") {
                    cout<< "π右侧遇(" <<endl;exit(3);
                }
            } else {
                for (i=0; (pf=fname[i])!=NULL; i++)
                    if (!strnicmp(pp,pf,strlen(pf))) break;
                if (pf!=NULL) {
                    op[iop++] = 07+i;
                    pp += strlen(pf);
                } else {
                    cout<< "陌生函数名" <<endl;exit(4);
                }
            }
        } else if (c==""+""||c==""-""||c==""*""||c==""/""||c==""%""||c==""^"") {
            char cc;
            if (last != DIGIT) {
                cout<< "运算符粘连" <<endl;exit(5);
            }
            pp++;
            if (c==""+""||c==""-"") {
                do {
                    cc = op[--iop];
                    --ist;
                    switch (cc) {
                    case ""+"":  ST[ist-1] += ST[ist];break;
                    case ""-"":  ST[ist-1] -= ST[ist];break;
                    case ""*"":  ST[ist-1] *= ST[ist];break;
                    case ""/"":  ST[ist-1] /= ST[ist];break;
                    case ""%"":  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;
                    case ""^"":  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;
                    }
                } while (iop);
                op[iop++] = c;
            } else if (c==""*""||c==""/""||c==""%"") {
operate:        cc = op[iop-1];
                if (cc==""+""||cc==""-"") {
                    op[iop++] = c;
                } else {
                    --ist;
                    op[iop-1] = c;
                    switch (cc) {
                    case ""*"":  ST[ist-1] *= ST[ist];break;
                    case ""/"":  ST[ist-1] /= ST[ist];break;
                    case ""%"":  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;
                    case ""^"":  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;
                    }
                }
            } else {
                cc = op[iop-1];
                if (cc==""^"") {
                    cout<< "乘幂符连用" <<endl;exit(6);
                }
                op[iop++] = c;
            }
            last = !DIGIT;
        } else {
            if (last == DIGIT) {
                cout<< "两数字粘连" <<endl;exit(7);
            }
            ST[ist++]=strtod(pp,&rexp);
            ST[ist-1]=fun(ST[ist-1],op,&iop);
            if (pp == rexp) {
                cout<< "非法字符" <<endl;exit(8);
            }
            pp = rexp;
            last = DIGIT;
            if (*pp == ""(""||isalpha(*pp)) {
                op[iop++]=""*"";
                last = !DIGIT;
                c = op[--iop];
                goto operate ;
            }
        }
    }
    *addr=pp;
    if (iop>=ist) {
        cout<< "表达式有误" <<endl;exit(9);
    }
    while (iop) {
        --ist;
        switch (op[--iop]) {
        case ""+"":  ST[ist-1] += ST[ist];break;
        case ""-"":  ST[ist-1] -= ST[ist];break;
        case ""*"":  ST[ist-1] *= ST[ist];break;
        case ""/"":  ST[ist-1] /= ST[ist];break;
        case ""%"":  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;
        case ""^"":  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;
        }
    }
    return ST[0];
}
int main(int argc,char **argv) {
    int a;

    if (argc<2) {
        if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页
        cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp"<<endl;
        while (1) {
            cout << "请输入表达式:";
            gets(s);
            if (s[0]==0) break;//
            cout << s <<"=";
            cout << setprecision(15) << calc(s,&endss) << endl;
        }
    } else if (argc==2 && 0==strcmp(argv[1],"/ ")) {
        if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页
        cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0~.15表示将计算结果保留小数0~15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp"<<endl;
    } else {
        strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;
        if (argc>2) {
            for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s
            if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0~.15表示将计算结果保留小数0~15位
                printf("%.*lf\n",pcs,calc(s,&endss));
            } else {
                strncat(s,argv[a],MAXLEN-1);
                printf("%.15lg\n",calc(s,&endss));
            }
        } else {
            printf("%.15lg\n",calc(s,&endss));
        }
    }
    return 0;
}
 
前两天CSDN C/C++论坛离了zhao4zhong1这根胡萝卜还真开不了席了!
 
楼主如果还想在这方面探究下去的话:
http://www.codeproject.com/Articles/286121/Compiler-Patterns

参考Tiny C Compiler源代码。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明c语言 函数型计算器,求添加计算平方、三角函数的功能