//
// 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
转载于:https://blog.51cto.com/8947509/1584542