//
//  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