主要是中缀表达式求值。
1.字符转数字
double Translation(int& pos) //将字符转换为数字
{
double integer = 0.0; // 整数部分
//double remainder = 0.0; //(double类型情况时)余数部分
while (s[pos] >= '0' && s[pos] <= '9')
{
integer *= 10;
integer += (s[pos] - '0'); //这一句是重点,将字符转换为数字即:减去‘0’
pos++;
}
/*if (s[pos] == '.')
{
pos++;
int c = 1;
while (s[pos] >= '0' && s[pos] <= '9')
{
double t = s[pos] - '0';
t *= pow(0.1, c);
c++;
remainder += t;
pos++;
}
}*/
return integer;
}
字符转数字这部分的重点就在于用字符减去'0'可得其数值,前一位乘十,加上这一位。不断继续,直到输入的不是数字为止。
2.返回运算符级别
int GetLevel(char ch)
{
switch (ch)
{
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '(':
return 0;
case '#':
return -1;
};
}
3.对两个数进行运算
double Operate(double a1, char op, double a2)
{
switch (op)
{
case '+':
return a1 + a2;
case '-':
return a1 - a2;
case '*':
return a1 * a2;
case '/':
return a1 / a2;
};
}
4.主要运算函数(用栈)
double Compute()
{
stack<char> optr; // 操作符栈
stack<int> opnd; // 操作数栈
optr.push('#'); //置于符栈顶
int len = strlen(s);
bool is_minus = true; // 判断'-'是减号还是负号, true表示负号
for (g_pos = 0; g_pos < len;)
{
//1. 负号
if (s[g_pos] == '-' && is_minus) // 是负号
{
opnd.push(0);
optr.push('-');
g_pos++;
}
//2. 是右括号 )
else if (s[g_pos] == ')')
{
is_minus = false; //括号后不会出现负号,只可能是减号
g_pos++;
while (optr.top() != '(')
{
double a2 = opnd.top();
opnd.pop();
double a1 = opnd.top();
opnd.pop();
char op = optr.top();
optr.pop();
double result = Operate(a1, op, a2);
opnd.push(result);
}
optr.pop(); // 删除'('
}
//3. 数字
else if (s[g_pos] >= '0' && s[g_pos] <= '9')
{
is_minus = false; //数字后不会出现负号,只可能是减号
opnd.push(Translation(g_pos));
}
//4. ( 左括号
else if (s[g_pos] == '(')
{
is_minus = true; //左括号后不会出现减号,只可能是负号
optr.push(s[g_pos]);
g_pos++;
}
//5. + - * / 四种
else
{
while (GetLevel(s[g_pos]) <= GetLevel(optr.top())) //当前优先级小于栈尾优先级
{
double a2 = opnd.top();
opnd.pop();
double a1 = opnd.top();
opnd.pop();
char op = optr.top();
optr.pop();
double result = Operate(a1, op, a2);
opnd.push(result);
}
optr.push(s[g_pos]);
g_pos++;
}
}
(虽然学校oj上的题目降低了难度,参数为正整数,既不用考虑小数点又不用考虑'-'是负号还是减号,但是这里都体现出来了。)
除去这些,总共需要考虑四种情况。
(1)左括号:
遇到左括号,直接入运算符栈。
(2)右括号:
(注意!)当运算符栈顶元素不为左括号时:进行运算直至运算符栈顶元为左括号为止。
运算过程:取数字栈栈顶并赋值-弹栈-取数字栈栈顶并赋值-弹栈-取运算符栈顶-弹栈-运算-将运算结果入栈(循环此过程直至运算符栈顶元素为左括号)
(3)数字:
遇到数字,直接入数字栈。
(4)+、-、*、/ 四种运算符:
(注意!)当当前运算符的优先级小于或等于栈顶运算符优先级时【也就是三种情况:①当前为+、-,栈顶为*、/②当前为+、-栈顶也为+、-③当前为*、/栈顶也为*、/。即先运算优先级高的或者优先级相同时在前面的(从左到右计算)】,先不入栈!先进行运算【(与以上运算过程相同)】。直至当前运算符优先级大于栈顶运算符(*、/在最后,不用先运算)。再将当前运算符入栈。
看着别人的代码总结了一下注意点,重点还是要自己敲一遍,把各种逻辑理清,到时候暴露出来的问题才是真正的大问题,到时候再来解决。