这些函数中都有“重复”的,因为操作数(OPND)栈用double,操作符(OPTR)栈用char。C++中的模板可以解决这个问题吗?
这是对着书写的:
#include <iostream>
using namespace std;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 100
char Precede_Matrix[7][7] =
{
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'<', '<', '<', '<', '<', '=', '0',},
{'>', '>', '>', '>', '0', '>', '>',},
{'<', '<', '<', '<', '<', '0', '=',}
};
char Precede ( char a, char b )
{
int i = 0;
int j = 0;
switch (a)
{
case '+' : i = a - '+'; break;
case '-' : i = a - '-' + 1; break;
case '*' : i = a - '*' + 2; break;
case '/' : i = a - '/' + 3; break;
case '(' : i = a - '(' + 4; break;
case ')' : i = a - ')' + 5; break;
case '#' : i = a - '#' + 6; break;
default : cout << "Error1!" << endl;
}
switch (b)
{
case '+' : j = b - '+'; break;
case '-' : j = b - '-' + 1; break;
case '*' : j = b - '*' + 2; break;
case '/' : j = b - '/' + 3; break;
case '(' : j = b - '(' + 4; break;
case ')' : j = b - ')' + 5; break;
case '#' : j = b - '#' + 6; break;
default : cout << "Error2!" << endl;
}
char c = Precede_Matrix[i][j];
return c;
}
int Operate(int a, char oper, int b)
{
switch (oper)
{
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: cout << "Error3!" << endl; return 0;
}
}
struct stack_char
{
char *base;
char *top;
int stacksize;
}OPTR;
struct stack_int
{
int *base;
int *top;
int stacksize;
}OPND; // 两位数的只能用int来存?
void InitStack(struct stack_char &S)
{
S.base = (char *)malloc( STACK_INIT_SIZE * sizeof(char) );
if(!S.base)
cout << "Overflow1!" << endl;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}
void InitStack(stack_int &S)
{
S.base = (int *)malloc( STACK_INIT_SIZE * sizeof(int) );
if(!S.base)
cout << "Overflow2!" << endl;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}
void Push(stack_char &S, char e)
{
if(S.top - S.base >= S.stacksize) // 判满
{
S.base = (char *)realloc( S.base,
(S.stacksize + STACKINCREMENT) * sizeof(char) );
if(!S.base)
cout << "Overflow3!" << endl;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
* S.top++ = e;
}
void Push(stack_int &S, int e)
{
if(S.top - S.base >= S.stacksize) // 判满
{
S.base = (int *)realloc( S.base,
(S.stacksize + STACKINCREMENT) * sizeof(int) );
if(!S.base)
cout << "Overflow4!" << endl;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
* S.top++ = e;
}
void Pop (stack_char &S, char &e)
{
if(S.top == S.base) // 判空
cout << "Error4!" << endl;
e = * --S.top;
}
void Pop (stack_int &S, int &e)
{
if(S.top == S.base) // 判空
cout << "Error5!" << endl;
e = * --S.top;
}
char GetTop(stack_char S)
{
if (S.top == S.base) // 判空
cout << "Error6!" << endl;
return *(S.top - 1);
}
int GetTop(stack_int S)
{
if (S.top == S.base) // 判空
cout << "Error7!" << endl;
return *(S.top - 1);
}
int EvaluateExpression()
{
int a;
int b;
char x;
char theta;
InitStack(OPTR);
Push(OPTR, '#');
InitStack(OPND);
char c = getchar(); // 输入若是数字,只能是个位数
while ( !(c == '#' && GetTop(OPTR) == '#') )
{
if ( '0' <= c && c <= '9' ) // c is operand
{
c -= '0';
Push(OPND, c);
c = getchar();
}
else // c is operator or delimiter
{
switch (Precede (GetTop(OPTR), c))
{
case '<':
Push(OPTR, c);
c = getchar();
break;
case '=':
Pop(OPTR, x);
c = getchar();
break;
case '>':
Pop(OPTR, theta);
Pop(OPND, b);
Pop(OPND, a);
Push(OPND, Operate(a, theta, b));
break;
default: cout << "Error8!" << endl;
}
}
}
// OPTR栈的栈顶元素和当前读入的字符均为“#”
// 即“#”=“#”时整个表达式求值完毕
int result = GetTop(OPND);
free(OPTR.base);
free(OPND.base);
return result; // 要在释放前保留下结果
}
int main()
{
cout << EvaluateExpression() << endl;
return 0;
}
NYOJ上该题的标程:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char str[1005];
int start;
char s[50],ss[50];int i,j;
double Term();double Expression();double Factor();
double Term()
{
double f=Factor(),t;
--start;
if(str[start]=='*')
{
t=Term();
return t*f;
}
else if(str[start]=='/')
{
t=Term();
return t/f;
}
else {++start;return f;}
}
double Expression()
{
double t=Term(),e;
--start;
if(str[start]=='+')
{
e=Expression();
return e+t;
}
else if(str[start]=='-')
{
e=Expression();
return e-t;
}
else {++start;return t;}
}
double Factor()
{
--start;
double ret;
if(str[start]==')')
{
ret=Expression();
--start;
return ret;
}
else
{
i=0;
memset(ss,0,sizeof(ss));
while((str[start]>='0'&&str[start]<='9')||str[start]=='.')
s[i++]=str[start--];
++start;
for(j=0;j<i;j++)
{
ss[j]=s[i-1-j];
}
return atof(ss);
}
}
int main()
{
//freopen("1.txt","r",stdin);
int n;
scanf("%d",&n);
while(n--)
{
scanf("%s",str);
start=strlen(str)-1;
printf("%.2lf\n",Expression());
}
}
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;
}
同时功能上改进了,欢迎体验!
本文通过使用C++模板改进了一个表达式求值程序,解决了原始版本中操作数和操作符栈类型不统一的问题,并增强了程序的功能,使其能够处理包含小数的表达式。
1290

被折叠的 条评论
为什么被折叠?



