user-0 提问: C语言编写计，要满足下列条件算器

回复:
user: user-1
content: 仅供参考： #pragma warning(disable:4996) /*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数: ⑴正弦sin ⑵余弦cos ⑶正切tan ⑷开平方sqrt ⑸反正弦arcsin ⑹反余弦arccos ⑺反正切arctan ⑻常用对数lg ⑼自然对数ln ⑽ｅ指数exp ⑾乘幂函数^ ⑿向上取整ceil ⒀向下取整floor ⒁四舍五入取整round ⒂取符号sign ⒃取绝对值abs 用法： 如果要求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键入字母时不区分大小写,以方便使用。 16进制整数以0x或0X开头。 ----------------------------------------*/ #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> #include <stdio.h> #include <string.h> #include <locale.h> #include <windows.h> const char Tab = 0x9; const int  DIGIT = 1; #define MAXLEN 16384 char s[MAXLEN],t[MAXLEN], *endss; int pcs = 15; FILE *fp; double sign(double dVal) {          if (dVal>0.0) return  1.0;     else if (dVal<0.0) return -1.0;     else               return  0.0; } double round(double dVal, short iPlaces) {//iPlaces>=0     char tmp[30];     double dRetval;      sprintf(tmp, "%.*lf", iPlaces, dVal);     sscanf(tmp, "%lf", &dRetval);     return (dRetval); } 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;         case 17: x = ceil(x);   (*iop)--; break;         case 18: x = floor(x);  (*iop)--; break;         case 19: x = round(x,0);(*iop)--; break;         case 20: x = sign(x);   (*iop)--; break;         case 21: x = fabs(x);   (*iop)--; break;         }     return x; } int isKMG(char c) {     if (c=='k'||c=='K'||c=='m'||c=='M'||c=='g'||c=='G') return 1;     return 0; } double calc(char *expr, char **addr) {     static int deep; //递归深度     static char *fname[] = { "sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round","sign","abs",NULL };     double ST[10] = { 0.0 }; //数字栈     char op[10] = { '+' }; //运算符栈     char c, *rexp, *pp, *pf;     int ist = 1, iop = 1, last, i, n;     __int64 i64;      if (!deep) {         pp = pf = expr;         do {             c = *pp++;             if (c != ' '&& c != Tab && c != ',')//跳过半角逗号(通常作为千分位分割符)                 *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) && !isKMG(*pp)) {//目的是：当右圆括弧的右侧为左圆括弧或函数名字时，默认其为乘法                 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) {                     fprintf(fp,"π左侧遇）\n"); if (fp!=stdout) fclose(fp); exit(1);                 }                 ST[ist++] = 3.14159265358979323846264338328;                 ST[ist - 1] = fun(ST[ist - 1], op, &iop);                 pp += 2;                 last = DIGIT;                 if (isalpha(pp[0]) && pp[0]!='x' && pp[0]!='X') {                     fprintf(fp,"两个π或K/M/G相连\n"); if (fp!=stdout) fclose(fp); exit(2);                 }                 if (*pp == '(') {                     fprintf(fp,"π右侧遇（\n"); if (fp!=stdout) fclose(fp); exit(3);                 }             } else if (isKMG(pp[0])) {                 if (last == DIGIT) {                     fprintf(fp,"%c左侧遇）\n",pp[0]); if (fp!=stdout) fclose(fp); exit(1);                 }                 double value=1.0;                 switch (pp[0]) {                 case 'k':value=1000.0      ;break;                 case 'K':value=1024.0      ;break;                 case 'm':value=1000000.0   ;break;                 case 'M':value=1048576.0   ;break;                 case 'g':value=1000000000.0;break;                 case 'G':value=1073741824.0;break;                 }                 ST[ist++] = value;                 ST[ist - 1] = fun(ST[ist - 1], op, &iop);                 pp += 1;                 last = DIGIT;                 if (isalpha(pp[0]) && pp[0]!='x' && pp[0]!='X') {                     fprintf(fp,"两个π或K/M/G相连\n"); if (fp!=stdout) fclose(fp); exit(2);                 }                 if (*pp == '(') {                     fprintf(fp,"%c右侧遇（\n",pp[-1]); if (fp!=stdout) fclose(fp); 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 {                     fprintf(fp,"陌生函数名\n"); if (fp!=stdout) fclose(fp); exit(4);                 }             }         }         else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '^') {             char cc;             if (last != DIGIT) {                 fprintf(fp,"运算符粘连\n"); if (fp!=stdout) fclose(fp); 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 == '^') {                     fprintf(fp,"乘幂符连用\n"); if (fp!=stdout) fclose(fp); exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 fprintf(fp,"两数字粘连\n"); if (fp!=stdout) fclose(fp); exit(7);             }             if (pp[0] == '0' && (pp[1] == 'x' || pp[1] == 'X')) {                 sscanf(pp + 2, "%I64x%n", &i64, &n);                 rexp = pp + 2 + n;                 ST[ist++] = (double)i64;             }             else ST[ist++] = strtod(pp, &rexp);             ST[ist - 1] = fun(ST[ist - 1], op, &iop);             if (pp == rexp) {                 fprintf(fp,"非法字符\n"); if (fp!=stdout) fclose(fp); exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '(' || isalpha(*pp)) {                 op[iop++] = '*';                 last = !DIGIT;                 c = op[--iop];                 goto operate;             }         }     }     *addr = pp;     if (iop >= ist) {         fprintf(fp,"表达式有误\n"); if (fp!=stdout) fclose(fp); 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]; } void pretreatment() {//预处理     int i,L,n,r;     char *p,*q;     double v;     char D[2];      //x2star将两边不是字母且左边不是非数字或串开头紧跟0的x替换为*,目的是支持用x代替*,且和0x开头的16进制数不冲突     L=strlen(s);     for (i=1;i<L;i++) {         if (s[i]=='x' && (!isalpha(s[i-1]) || isKMG(s[i-1])) && !isalpha(s[i+1])) {             if (!(                  (i==1 && s[0]=='0')               || (i>1 && s[i-1]=='0' && !isdigit(s[i-2]))                )) s[i]='*';         }     }      //将"数字\.数字[kmgKMG]"用()括住     strcpy(t,s);     p=&t[0];     q=s;     while (1) {         r=sscanf(p,"%lf%n%1[GKMgkm]",&v,&n,D);         if (r==EOF) break;//         if (r==0) {             L=sprintf(q,"%c",*p);             q+=L;             p++;         } else if (r==1) {             L=sprintf(q,"%.*s",n,p);             q+=L;             p+=n;         } else if (r==2) {             L=sprintf(q,"(%.*s%c)",n,p,D[0]);             q+=L;             p+=n+1;         }     } } int main(int argc, char **argv) {     int a;      setlocale( LC_ALL,"chs");     fp=stdout;     if (argc<2) {         //if (GetConsoleOutputCP() != 936) system("chcp 936>NUL");//中文代码页         printf("计算函数表达式的值。\n支持(),+,-,*,x,/,%%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round,sign,abs,k,m,g,K,M,G\n");         while (1) {             printf("请输入表达式：");             fgets(s,MAXLEN,stdin);             if ('\n' == s[strlen(s)-1]) s[strlen(s) - 1] = 0;             if (s[0] == 0) break;//             pretreatment();printf("%s=%.15lg\n",s,calc(s, &endss));         }         return 0;     }     if (argc == 2 && 0 == strcmp(argv[1], "/?")) {         //if (GetConsoleOutputCP() != 936) system("chcp 936>NUL");//中文代码页         printf(             "计算由≥1个命令行参数给出的函数表达式的值。\n"             "最后一个参数是.0～.15表示将计算结果小数点后保留0～15位\n"             "最后一个参数是g1～g15表示将计算结果保留有效数字1～15位\n"             "最后一个参数是e0～e15表示将计算结果用科学计数法表示，且小数点后保留0～15位\n"             "最后一个参数是x表示将计算结果以16进制正整数格式输出\n"             "支持(),+,-,*,x,/,%%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round,sign,abs,k,m,g,K,M,G\n"             "16进制整数以0x或0X开头\n"             "忽略表达式中的半角逗号(通常作为千分位分割符)\n"             "如果第一个参数是/f且c:\\jsresult.txt可写，就将所有输出重定向到该文件\n"         );         return 0;     }     if (argc>2 && 0 == strcmp(argv[1], "/f")) {         fp=fopen("c:\\jsresult.txt","w");         if (NULL==fp) fp=stdout;         for (a=2;a<argc;a++) argv[a-1]=argv[a];         argc--;     }     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位             pretreatment();fprintf(fp,"%.*lf\n", pcs, calc(s, &endss));         } else if (1 == sscanf(argv[a], "g%d", &pcs) && 1 <= pcs && pcs <= 15) {//最后一个参数是g1～g15表示将计算结果保留有效数字1～15位             pretreatment();fprintf(fp,"%.*lg\n", pcs, calc(s, &endss));         } else if (1 == sscanf(argv[a], "e%d", &pcs) && 0 <= pcs && pcs <= 15) {//最后一个参数是e0～e15表示将计算结果用科学计数法表示，且小数点后保留0～15位             pretreatment();fprintf(fp,"%.*le\n", pcs, calc(s, &endss));         } else if (argv[a][0] == 'x' || argv[a][0] == 'X') {//最后一个参数是x表示将计算结果以16进制正整数格式输出             pretreatment();fprintf(fp,"0x%016I64x\n", (__int64)calc(s, &endss));         } else {             strncat(s, argv[a], MAXLEN - 1);             pretreatment();fprintf(fp,"%.15lg\n", calc(s, &endss));         }     } else {         pretreatment();fprintf(fp,"%.15lg\n", calc(s, &endss));     }     if (fp!=stdout) fclose(fp);     return 0; }