这些函数中都有“重复”的,因为操作数(OPND)栈用double,操作符(OPTR)栈用char。C++中的模板可以解决这个问题吗?
这是对着书写的:
NYOJ上该题的标程:
2012/5/17 更新:
终于用模板解决了那个问题
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> using namespace std; #define STACK_INIT_SIZE 1024 #define STACKINCREMENT 30 char Precede_Matrix[7][7] = { {'>', '>', '<', '<', '<', '>', '>',}, {'>', '>', '<', '<', '<', '>', '>',}, {'>', '>', '>', '>', '<', '>', '>',}, {'>', '>', '>', '>', '<', '>', '>',}, {'<', '<', '<', '<', '<', '=', '0',}, {'>', '>', '>', '>', '0', '>', '>',}, {'<', '<', '<', '<', '<', '0', '=',} }; char Precede ( char a, char b ) { int i = 0; int j = 0; switch (a) { case '+' : i = 0; break; case '-' : i = 1; break; case '*' : i = 2; break; case '/' : i = 3; break; case '(' : i = 4; break; case ')' : i = 5; break; case '#' : i = 6; break; default : cout << "Error1!" << endl; } switch (b) { case '+' : j = 0; break; case '-' : j = 1; break; case '*' : j = 2; break; case '/' : j = 3; break; case '(' : j = 4; break; case ')' : j = 5; break; case '#' : j = 6; break; default : cout << "Error2!" << endl; } return ( Precede_Matrix[i][j] ); } double Operate(double a, char oper, double b) { switch (oper) { case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': return a / b; default: cout << "Error3!" << endl; return -1; } } struct stack_char { char *base; char *top; int stacksize; }; struct stack_double { double *base; double *top; int stacksize; }; // 计算结果可能是两位数,只能用double,不能用char来存? template <class T2, class T1> void InitStack(T1 &S) { S.base = (T2 *)malloc( STACK_INIT_SIZE * sizeof(T2) ); if(!S.base) cout << "Overflow2!" << endl; S.top = S.base; S.stacksize = STACK_INIT_SIZE; } template <class T1, class T2> void Push(T1 &S, T2 e) { if(S.top - S.base >= S.stacksize) // 判满 { S.base = (T2 *)realloc( S.base, (S.stacksize + STACKINCREMENT) * sizeof(T2) ); if(!S.base) cout << "Overflow3!" << endl; S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; } *S.top++ = e; } template <class T1, class T2> void Pop (T1 &S, T2 &e) { if(S.top == S.base) // 判空 cout << "Error5!" << endl; e = *--S.top; } template <class T2, class T1> T2 GetTop(T1 S) { if (S.top == S.base) // 判空 cout << "Error6!" << endl; return *(S.top - 1); } bool IsOperand(char c) { if( ('0' <= c && c <= '9') || c == '.' ) // c是数字或小数点 return true; else return false; } int main(void) { string str; while (cin >> str) { str.push_back('#'); // 最后是#(结束标志) double a; double b; char x; char theta; stack_char OPTR; InitStack<char> (OPTR); Push(OPTR, '#'); stack_double OPND; InitStack<double> (OPND); int i = 0; char c = str[i++]; double operand = 0; while ( !(c == '#' && GetTop<char> (OPTR) == '#') ) { if ( IsOperand(c) ) // c is operand { operand = atof( &str[i - 1] ); // 把从c开头的数转化成double Push(OPND, operand); while( IsOperand(str[i]) ) i++; c = str[i++]; } else // c is operator or delimiter { switch (Precede (GetTop<char> (OPTR), c)) { case '<': Push(OPTR, c); c = str[i++]; break; case '=': Pop(OPTR, x); c = str[i++]; break; case '>': Pop(OPTR, theta); Pop(OPND, b); Pop(OPND, a); Push(OPND, Operate(a, theta, b)); break; default: cout << "Error8!" << endl; break; } } } // OPTR栈的栈顶元素和当前读入的字符均为“#” // 即“#”=“#”时整个表达式求值完毕 cout << GetTop<double> (OPND) << endl; free(OPTR.base); free(OPND.base); } return 0; }
同时功能上改进了,欢迎体验!