码迷,mamicode.com
首页 > 其他好文 > 详细

样例一:高级计算器

时间:2015-01-23 16:09:06      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

高级计算器是指输入一个数学表达式,然后计算出这个表达式的值的程序。
比如输入1+3*(5-10),就应该输出-14。
这是一道语法分析题,需要先进行语法分析,然后根据分析结果执行输入的语句。
我们分析一下数学的公式,可以看出有如下的定义:
表达式(expression):多个项(term)的和或差。
项(term):多个简单项(simple term)的乘积或商。
简单项(simple term):数或者带括号的表达式。
比如1和3和4都是简单项,1*3*4是项,1*3*4+2*4*6就是表达式。特殊的是括号表达式如(1+3)算作一个简单项,因为其运算优先级和简单项是一样高的。
这是一个递归型的定义,所以我们用递归来解决这个问题。

 

技术分享
#include 
using namespace std;
double calcExp(char[], int);

int charsTaken;//这是函数的第二个返回值,表示一个函数成功匹配了多少个字符。

/*
简单项(simple term)指的是(表达式)或数字或者-数字或者+数字。
*/
double calcSimpleTerm(char exp[], int start) {
    double ret;
    if (exp[start] == () {
        start++;
        //如果是(表达式)的形式,首先计算表达式的值
        ret = calcExp(exp, start);
        if (charsTaken >= 0) {
            start += charsTaken;
            if (exp[start] == )) {
                return (charsTaken = charsTaken + 2, ret);//左括号+中间的表达式的字符数+右括号
            } else {
                cout << "处理因子时发现格式错误,缺少右括号,在第" << start << "个字符处" << endl;
                return (charsTaken = -1, 0);
            }
        }
    } else if ((exp[start] >= 0 && exp[start] <= 9) || exp[start] == . || exp[start] == - || exp[start] == +) {
        //如果是数字
        ret = atof(exp + start);
        //atof虽然能把字符串解释为浮点数,但是却不能返回吃掉的字符数量,所以要人工数一下。
        //数的过程要注意小数点,只能出现一次。
        if (exp[start] == - || exp[start] == +)
            charsTaken = 1, start++;
        else
            charsTaken = 0;
        bool metDot = false;
        while ((exp[start] >= 0 && exp[start] <= 9) || exp[start] == .) {
            if (exp[start] == .) {
                if (metDot)
                    break;
                else
                    metDot = true;
            }
            start++;
            charsTaken++;
        }
        return ret;
    } else {
        cout << "处理因子时发现格式错误,未定义的字符" << exp[start] << ",在第" << start << "个字符处" << endl;
        return (charsTaken = -1, 0);
    }
    return (charsTaken = -1, 0);//这句会在出错的时候执行到。
}

/*
计算一个项(term),因子的定义为简单项(simple term)的积或商或简单项。
*/
double calcTerm(char exp[], int start) {
    //首先尝试读入一个简单项,firstST保存了当前计算过的项的值。
    double firstST = calcSimpleTerm(exp, start);
    if (charsTaken >= 0) {
        //读入成功之后判断下一个字符是不是乘号或除号
        start += charsTaken;
        int retCharsTaken = charsTaken;//用来记录当前读过多少个字符
        while (exp[start] == * || exp[start] == /) {
            double next = calcSimpleTerm(exp, start + 1);
            if (charsTaken < 0) {
                return (charsTaken = -1, 0);
            }
            if (exp[start] == *)
                firstST *= next;
            else {
                if (next != 0)
                    firstST /= next;
                else {
                    cout << "除零错" << endl;
                    return (charsTaken = -1, 0);
                }
            }
            start += charsTaken + 1;
            retCharsTaken += charsTaken + 1;
        }
        if (exp[start] == \0 || exp[start] == ) || exp[start] == + || exp[start] == -) {
            //这标志着这个term的结束
            return (charsTaken = retCharsTaken, firstST);
        } else {
            cout << "处理因子时发现格式错误,未定义的字符" << exp[start] << ",在第" << start << "个字符处" << endl;
            return (charsTaken = -1, 0);
        }
    }
    return (charsTaken = -1, 0);
}

/*
计算一个表达式(expression),表达式的定义为项(term)的和或差。
*/
double calcExp(char exp[], int start) {
    double firstTerm = calcTerm(exp, start);
    if (charsTaken >= 0) {
        start += charsTaken;
        int retCharsTaken = charsTaken;
        while (exp[start] == + || exp[start] == -) {
            double next = calcTerm(exp, start + 1);
            if (charsTaken < 0) {
                return (charsTaken = -1, 0);
            }
            if (exp[start] == +)
                firstTerm += next;
            else {
                firstTerm -= next;
            }
            start += charsTaken + 1;
            retCharsTaken += charsTaken + 1;
        }
        if (exp[start] == ) || exp[start] == \0) {
            return (charsTaken = retCharsTaken, firstTerm);
        } else {
            cout << "处理表达式时发现格式错误,未定义的字符" << exp[start] << ",在第" << start << "个字符处" << endl;
            return (charsTaken = -1, 0);
        }
    }
    return (charsTaken = -1, 0);
}

int main() {
    char exp[100];
    cout << "输入只包含括号,数字和+-*\/运算符的数学公式:" << endl;
    cin.getline(exp, 100);
    cout << calcExp(exp, 0) << endl;
    return 0;
}
View Code

 

样例一:高级计算器

标签:

原文地址:http://www.cnblogs.com/guyueliushang/p/4244168.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!