来自邓俊辉老师的数据结构(C++版)第95页
readNumber函数(可读整数和小数)
注意:下列代码是直接用C++内部写好的stack实现的,而不是书中给出的stack模板
//发现更简洁的readNumber函数
float readNumber(string& s) {
float sum = 0.0;
int pos = s.find('.');
for (int i = 0; i < s.size(); i++) {
if (i == pos) { continue; }
else sum = sum * 10 + (s[i] - 48);
}
if (pos) sum = sum / ((s.size() - pos - 1)*10);
return sum;
}
//是对书中内容的补充,通过Stack来读取整数或小数并运算
#include<iostream>
#include<stack>
using namespace std;
typedef enum { ADD, SUB, MUI, DIV, POW, FAC, L_P, R_P, EOE } Operator;//0-8
const char pri[9][9] = {
'>','>','<','<','<','<','<','>','>',//0
'>','>','<','<','<','<','<','>','>',//1
'>','>','>','>','<','<','<','>','>',//2
'>','>','>','>','<','<','<','>','>',//3
'>','>','>','>','>','<','<','>','>',//4
'>','>','>','>','>','>',' ','>','>',//5
'<','<','<','<','<','<','<','=',' ',//6
' ',' ',' ',' ',' ',' ',' ',' ',' ',//7
'<','<','<','<','<','<','<',' ','='//8
};
//这里取S[]的引用很关键!!!不然S++在readNumber返回后就没效果了
float readNumber(char* &S, stack<float> &opnd) {
float x = 0.0;
bool point=false;//判断是否为小数
int i = 0;//计小数点后的位数
while (isdigit(*S)||*S=='.') {
if (*S != '.') {
if (point == false) x = x * 10 + (*(S++) - 48);//减去48,ASCII转成数字
if (point == true) { x = x * 10 + (*(S++) - 48); i++; }
}
else { S++; point = true; }
}
int temp = 1;
for (int j = 0; j < i; j++) temp *= 10;
x = x / temp;
opnd.push(x);//压入操作数栈
return x;
}
int change(char c) {
switch (c)
{case '+':return ADD;
case '-':return SUB;
case '*':return MUI;
case '/':return DIV;
case '^':return POW;
case '!':return FAC;
case '(':return L_P;
case ')':return R_P;
case '\0':return EOE;}
}
char orderBetween(char c1, char c2) {
return pri[change(c1)][change(c2)];
}
float fac(int n) { return (2 > n) ? 1 : n * fac(n - 1);}//自然数的阶乘(小数的阶乘呢???不会实现...)
float calcu(char optr, float opnd) { return fac(opnd);}
float calcu(float opnd1, char op, float opnd2) {
float result = 1;
switch (op) //判断运算符
{
case '+': {result = opnd1 + opnd2; return result; }
case '-': {result = opnd1 - opnd2; return result; }
case '*': {result = opnd1 * opnd2; return result; }
case '/': {result = opnd1 / opnd2; return result; }
case '^': {for (int i = 0; i < opnd2; i++) result *= opnd1; return result; }
}//switch
}
float evaluate(char* S) {
stack<float> opnd; stack<char> optr;
optr.push('\0');
while (!optr.empty()) {
if (isdigit(*S)) {
readNumber(S, opnd);
//append(RPN, opnd.top());
}
else
switch (orderBetween(optr.top(), *S)) {
case '<':
optr.push(*S); S++;
break;
case '=':
optr.pop(); S++;
break;
case '>': {
char op = optr.top(); optr.pop();
if ('!' == op) {
//因为我没有写stack的模板,而是直接用的是C++内部的stack.h头文件
//stack.h 中pop函数的返回值为void,所以需要在pop之前先通过top函数取栈顶(top函数返回值为栈顶元素)然后再pop出栈
float pOpnd = opnd.top(); opnd.pop();
opnd.push(calcu(op, pOpnd));//实施一元运算
}
else {
float pOpnd2 = opnd.top(); opnd.pop();
float pOpnd1 = opnd.top(); opnd.pop();
opnd.push(calcu(pOpnd1, op, pOpnd2));//实施二元运算
}
break;
}
default:exit(-1);
}//switch
}//while
float Result = opnd.top();//先转存计算结果,再pop
opnd.pop();
return Result;//弹出并返回最后的计算结果
}
int main() {
char S1[] = "2.3+3.5"; cout << "2.3+3.5=" << evaluate(S1) << endl;
char S2[] = "7.3-3.5"; cout << "7.3-3.5=" << evaluate(S2) << endl;
char S3[] = "2*6"; cout << "2*6=" << evaluate(S3) << endl;
char S4[] = "8/2"; cout << "8/2=" << evaluate(S4) << endl;
char S5[] = "(2+3)+2^3+3!"; cout << "(2+3)+2^3+3!=" << evaluate(S5) << endl;
return 0;
}