复杂四则运算程序实现

当我们遇到很复杂的四则运算,怎么通过编程实现呢?例如:34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))/(43-45*343)此字符串输入,求取表达式的结果是多少呢?自己头脑是什么思路?回想以前的数学的证明题,都是从最简单的思考开始,此表达式字符串分析也不例外。

只考虑加减法

加减法是同级运算,故只需字符串向后移动即可,实现比较简单。最关键的是在于获取操作数。初始直接获取操作数getNum,后续遇到+,-符号的时候,都需要调用getNum来获取操作数。故两个操作数被获取,完成加减操作,完成的结果又是第一个操作数,重复此过程,从而得到最后的结果。

# include<iostream>

using  namespace std;


void removeSpace(char *str){
    char *p1=str,*p2=str;
    while ((*p1=*p2++)) {
        if (*p1 != ' ') {
            p1++;
        }
    }
}

bool isNumber(const char ch){
    return '0'<=ch && ch<='9';
}

double getNum(char *str,int *index){
    double v=0.0;
    while(isNumber(*(str+*index))){
        v=v*10+*(str+*index)-'0';
        (*index)++;
    }
    if (*(str+*index)!='.'){
        return v;
    }
    double decimal=1.0;
    while(isNumber(*(str+(++*index)))){
        decimal/=10;
        v+=decimal*(*(str+*index)-'0');
    }
    return v;
}



double lowerCount(char *str,int *index){
    double v1=getNum(str,index);
    while(*(str+*index)){
        switch (*(str+(*index)++)){
            case '+':
                v1+=getNum(str,index);
                break;
            case '-':
                v1-=getNum(str,index);
                break;
            case '\0':
                return v1;
        }
    }
    return v1;
}

int main(int argc, char **argv){
    char str[100]={"2+10+7+10"};
    removeSpace(str);
    int index=0;
    cout<<lowerCount(str,&index)<<endl;
}


加减法基础上增加乘除法

由于加减法的优先级比乘除法低,故加减法的操作数获取需要调用乘除法的结果。而乘除法本身是同级的,故乘除法的操作数可以通过getNum来进行获取(重复上述加减法过程),直到遇到非*,/字符返回结果作为加减法的操作数。

# include<iostream>

using  namespace std;


void removeSpace(char *str){
    char *p1=str,*p2=str;
    while ((*p1=*p2++)) {
        if (*p1 != ' ') {
            p1++;
        }
    }
}

bool isNumber(const char ch){
    return '0'<=ch && ch<='9';
}

double getNum(char *str,int *index){
    double v=0.0;
    while(isNumber(*(str+*index))){
        v=v*10+*(str+*index)-'0';
        (*index)++;
    }
    if (*(str+*index)!='.'){
        return v;
    }
    double decimal=1.0;
    while(isNumber(*(str+(++*index)))){
        decimal/=10;
        v+=decimal*(*(str+*index)-'0');
    }
    return v;
}

double moreCount(char *str,int *index){
    double v1=getNum(str,index);
    while(*(str+*index)){
        switch (*(str+*index)){
            case '*':
                (*index)++;
                v1*=getNum(str,index);
                break;
            case '/':
                (*index)++;
                v1/=getNum(str,index);
                break;
            default:
                return v1;
        }
    }
    return v1;
}


double lowerCount(char *str,int *index){
    double v1=moreCount(str,index);
    while(*(str+*index)){
        switch (*(str+(*index)++)){
            case '+':
                v1+=moreCount(str,index);
                break;
            case '-':
                v1-=moreCount(str,index);
                break;
            case '\0':
                return v1;
        }
    }
    return v1;
}


int main(int argc, char **argv){
    char str[100]={"2*10+7*10+4*5+2*3"};
    removeSpace(str);
    int index=0;
    cout<<lowerCount(str,&index)<<endl;
}


乘除法基础上加括号

括号运算的优先级高于乘除法,而括号内的运算本质又是+,-,*,/,()构成,因此乘除法通过getNum获取操作数的时候,需要考虑括号表达式,若有括号,则把括号的结果作为乘除法的操作数;若无括号,直接读取数字作为操作数。而括号表达式内的子串又是一个复杂的+,-,*,/,()表达式构成,因此计算括号内的结果我们可以递归调用加减法计算函数,从而最终能够完成括号表达式的结果。

# include<iostream>

using  namespace std;


void removeSpace(char *str){
    char *p1=str,*p2=str;
    while ((*p1=*p2++)) {
        if (*p1 != ' ') {
            p1++;
        }
    }
}

bool isNumber(const char ch){
    return '0'<=ch && ch<='9';
}


char * bracket(char* str, int* index){
    int num=1,start=++(*index);
    while(*(str+*index)){
        if (*(str+*index)=='('){
            num++;
            (*index)++;
            continue;
        }
        if (*(str+*index)==')'){
            if (--num==0){
                char * p=(char*)malloc(sizeof(char)*(*index-start+1));
                memcpy(p,str+start,*index-start);
                p[*index-start+1]='\0';
                (*index)++;
                return p;
            }
        }
        (*index)++;
    }
    return nullptr;
}

double lowerCount(char *str,int *index);
double getNum(char *str,int *index){
    double v=0.0;
    if (*(str+*index)=='('){
        char *substr=bracket(str,index);
        int pindex=0;
        double v1=lowerCount(substr,&pindex);
        free(substr);
        return v1;
    }

    while(isNumber(*(str+*index))){
        v=v*10+*(str+*index)-'0';
        (*index)++;
    }
    if (*(str+*index)!='.'){
        return v;
    }
    double decimal=1.0;
    while(isNumber(*(str+(++*index)))){
        decimal/=10;
        v+=decimal*(*(str+*index)-'0');
    }
    return v;
}


double moreCount(char *str,int *index){
    double v1=getNum(str,index);
    while(*(str+*index)){
        switch (*(str+*index)){
            case '*':
                (*index)++;
                v1*=getNum(str,index);
                break;
            case '/':
                (*index)++;
                v1/=getNum(str,index);
                break;
            default:
                return v1;
        }
    }
    return v1;
}


double lowerCount(char *str,int *index){
    double v1=moreCount(str,index);
    while(*(str+*index)){
        switch (*(str+(*index)++)){
            case '+':
                v1+=moreCount(str,index);
                break;
            case '-':
                v1-=moreCount(str,index);
                break;
            case '\0':
                return v1;
        }
    }
    return v1;
}


int main(int argc, char **argv){
    char str[100]={"2*(10+7*10)+4*5+2*3"};
    removeSpace(str);
    int index=0;
    cout<<lowerCount(str,&index)<<endl;
}

总结

一个复杂的问题,往往从最简单的开始进行考虑,一步一步往里面添加条件,从而问题能够有效的解决。而递归解决问题也需要这样建立问题解决方法。递归抓住两点:1.怎样方式递归的?2.递归退出的条件是什么?而上述复杂的四则运算递归终止条件:内部表达式不再有任何括号。
递归不再局限于函数本身来调用自己,也可以函数本身通过间接方式来调用到自己。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章