标签:
高级计算器是指输入一个数学表达式,然后计算出这个表达式的值的程序。
比如输入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; }
标签:
原文地址:http://www.cnblogs.com/guyueliushang/p/4244168.html