// // main.c // 科学计算器 // // Created by QzydeMac on 14/11/28. // Copyright (c) 2014年 Qzy. All rights reserved. // #include <stdio.h> #include <string.h> #include <stdlib.h> typedef enum BOOL { TRUE, FALSE }BOOL; double add(double number1,double number2);//+ double mins(double number1,double number2);//- double mul(double number1,double number2);//* double divi(double number1,double number2);/// char * removeMul_DivLoop(char * str); char * removeAdd_MinsLoop(char * str); char * removeBracket(char * str); char * loopRemoveBracket(char * str); char * removemul_div(char * str); char * getResult(char *str); long numberOfLenth(char * str); char * getTwoNumberComputerResult(char *str,int indexOfLeftBracket,int indexOfRightBracket); int main(int argc, const char * argv[]) { char * expression = (char *)malloc(sizeof(100)); printf("请输入算术公式:"); scanf("%s",expression); // expression = removeBracket(expression);//获取去除()的表达式:已经成功 expression = loopRemoveBracket(expression); printf("去括号expression:%s\n",expression); expression =removeMul_DivLoop(expression);//获取除去*/的表达式 printf("去乘除expression:%s\n",expression); expression = removeAdd_MinsLoop(expression); printf("计算结果:%s",expression); return 0; } //完成 char * removeBracket(char * str)//去括号 { //char * tempStr;//用来接收两个数字计算结果的字符串 char * tempStr = (char *)malloc(sizeof(100)); int j; char * replaceStr = (char *)malloc(sizeof(100));//一个一个除去()后的临时字符串,但是最后一次,表示()已经完全清除 // int tempStr[100];//多次记录去除括号后的字符串 int indexOfLeftBracket = 0,indexOfRightBracket = 0,i; for (i = 0; i < strlen(str); i++) { if (*(str + i)=='(') { indexOfLeftBracket = i;//记录成对括号,从左到右 } else if (*(str+i)==')') { indexOfRightBracket = i; break; } } //2*((123.01+5+3*4)*6)-((2-56)*8)*3+5 测试数据 //printf("%d %d %f\n",indexOfLeftBracket,indexOfRightBracket,atof(str+indexOfLeftBracket+1)); //atoi(str+index+1)第一对出现的()里面的(后面的数字 strncpy(tempStr, str+indexOfLeftBracket+1, indexOfRightBracket-indexOfLeftBracket-1); tempStr = removeMul_DivLoop(tempStr); tempStr = removeAdd_MinsLoop(tempStr); for (j = 0; j<indexOfLeftBracket; j++)//去除左( { replaceStr[j] = str[j];//正确 } replaceStr[j]='\0'; for (int i = 0; i<strlen(tempStr); i++)//添加两数字计算结果数字字符串 { replaceStr[j] = tempStr[i];//正确 j++; } replaceStr[j]='\0'; for (int i = indexOfRightBracket+1; i<strlen(str); i++)//去除右括号,并将后面的字符存储到新的字符串中 { replaceStr[j] = str[i]; j++; } replaceStr[j--]='\0'; strcpy(str, replaceStr); return str; } char * loopRemoveBracket(char * str) { int bracketCount = 0; for (int i = 0; i<strlen(str); i++)//循环次数 { if (*(str+i)=='(') { bracketCount++; } } for (int i = 0; i<bracketCount; i++) { str = removeBracket(str); } return str; } //已正确 long numberOfLenth(char * str)//获取操作符左边数字字符串的长度(正确函数) { char * ptr = NULL; long numberLenth = 0; ptr = str; if (*ptr =='-') { numberLenth+=1; } while ((ptr = strtok(ptr, "+-*/)"))) { break; } numberLenth+= strlen(ptr); return numberLenth; } char * removemul_div(char * str)//去乘除 { //每次循环将操作符前面的数字进行保存,如果后面的算术表达式为*/则进行处理,一直处理到没有算术表达式为止 char * result = NULL; int j; int leftNumberIndex = 0,rightNumberIndex = 0,indexOfRelpaceStr = 0; char * relpaceStr = (char *)malloc(sizeof(100)); memset(relpaceStr, '\0', 100); double leftNumber = atof(str); double rightNumber = 0; BOOL loop = TRUE; for (int i =0; i<strlen(str); i++) { if (*(str+i)=='*'||*(str+i)=='/') { loop = FALSE; rightNumber = atof(str+i+1); for (j = i+1; j<strlen(str); j++) { if (*(str+j)=='*'||*(str+j)=='/'||*(str+j)=='-'||*(str+j)=='+') { rightNumberIndex = j; break; } } if (j==strlen(str)) { rightNumberIndex = j; } if (leftNumberIndex==0) { leftNumberIndex = -1; } result=getTwoNumberComputerResult(str, leftNumberIndex, rightNumberIndex); //得到结果后在此处修改原字符串 for (i = 0; i<=leftNumberIndex; i++) { relpaceStr[indexOfRelpaceStr++] = str[i]; } for (int k = 0;k<strlen(result) ; k++) { relpaceStr[indexOfRelpaceStr++] = result[k]; } for (int k = rightNumberIndex; k<strlen(str); k++) { relpaceStr[indexOfRelpaceStr++] = str[k]; } relpaceStr[indexOfRelpaceStr] = '\0'; strcpy(str, relpaceStr); } else if((*(str+i)=='-'||*(str+i)=='+')&&(*(str+i+1)>='0'&&*(str+i+1)<='9')) { leftNumber = atof(str+i+1); leftNumberIndex = i; } if (loop==FALSE) { break; } } return str; } char * getResult(char *str)//返回结果 { char * temp = NULL; char * replaceString = (char *)malloc(sizeof(100)); int leftNumberIndex=0,rightNumberIndex = 0; for (int i = 0; i< strlen(str); i++) { if ((*(str+i)=='+'||*(str+i)=='-')&&(*(str+i+1)<='9'||*(str+i+1)>='0')) { int j; for (j = i+2; j<strlen(str); j++) { if (*(str + j)=='+'||*(str + j)=='-') { rightNumberIndex = j; break; } } if (j==strlen(str)) { rightNumberIndex=j; } temp = getTwoNumberComputerResult(str, leftNumberIndex-1, rightNumberIndex); strcpy(replaceString, temp); strcat(replaceString, str+rightNumberIndex); break; } } return replaceString; } char * getTwoNumberComputerResult(char *str,int indexOfLeftBracket,int indexOfRightBracket)//取得想要进行计算的两个数字结果 { double result = 0; char resultStr[100]; char * tempStr = (char *)malloc(sizeof(100));//strtok会改变原本的字符串,所以我们需要将原本的字符串进行备份 strcpy(tempStr, str); double leftNumber = atof(str+indexOfLeftBracket+1); long lenth = numberOfLenth(tempStr+indexOfLeftBracket+1);//得到算术符号的位置 double rightNumber = atof(tempStr+indexOfLeftBracket+lenth+2);//取到运算符右边的数值 switch (*(str+indexOfLeftBracket+lenth+1)) { case '+': result = add(leftNumber, rightNumber); break; case '-': result = mins(leftNumber, rightNumber); break; case '*': result = mul(leftNumber, rightNumber); break; case '/': result = divi(leftNumber, rightNumber); break; case '%': break; default: break; } return gcvt(result,6, resultStr); } char * removeMul_DivLoop(char * str) { int loop = 0; for (int i =0; i<strlen(str); i++) { if (*(str+i)=='*'||*(str+i)=='/') { loop++; } } for (int i = 0; i<loop; i++) { str=removemul_div(str); } return str; } char * removeAdd_MinsLoop(char * str) { int loopCount=0; char * tempStr = (char *)malloc(sizeof(100)); strcpy(tempStr, str); char * p = tempStr; while ((p=strtok(p, "+-"))) { loopCount++; p=NULL; } for (int i = 0; i<loopCount-1; i++) { str= getResult(str); } return str; } double add(double number1,double number2) { return number1+number2; } double mins(double number1,double number2) { return number1-number2; } double mul(double number1,double number2) { return number1*number2; } double divi(double number1,double number2) { return number1/number2; }
总结:算法:1.第一步是去除括号,算法是总是寻找左括号并记录它的下标,直到我们找到了第一个右括号,记录下右括号的下标,时这个括号肯定是一对括号,且该括号内部也肯定不在含有其他的括号存在,我们通过字符串的首地址,以及左右括号的下标,取出里面的表达式,进行单独运算,运算出结果后,用字符串进行返回(通过char*gcvt(double, int, char *函数),将该结果替换掉我们刚才进行运算的表达式,再次循环,从头查找下一个成对括号,直到所有都找到,第一步就结束了
2.第二步去除乘除,这个很简单,3.取出加减,得到结果
结果示例:
请输入算术公式:2*((123.01+5+3*4)*6)-((2-56)*8)*3+5 去括号expression:2*840.06--432*3+5 去乘除expression:1680.12--1296+5 计算结果:2981.12Program ended with exit code: 0