二哥想自己做一个计算器,但是他需要一个程序来计算输入表达式的结果。你能帮助他吗? Input Format 输入仅一行,给出一个算数表达式。表达式中包含:小括号,加减乘除,指数运算符,负号,整数,空格。其中负号的优先级最高(-),其次是指数运算(^),然后是乘除(*/),最后是加减(+-)。 这里规定除法为整除运算,如 5 / 2 = 2, 8 / -3 = -2 等等,与C++中的整除一致。另外注意指数运算为右结合,即 2^3^2 = 2^9 = 512 而非 2^3^2 = 8^2 = 64 。 输入的字符串长度不超过100。 Output Format 如果输入的表达式出现括号不匹配或者除零错误,输出一行“Error”(不含引号),否则输出运算结果。输入保证不包含任何其它类型的错误。 输入的数,输出的答案,以及中间结果均保证是不超过 long long 范围的整数。
时间: 2024-02-17 11:01:41 浏览: 20
可以使用栈来实现表达式的计算。具体实现过程可以分为以下几个步骤:
1. 创建两个栈,一个用于存储数字,一个用于存储操作符和括号。
2. 依次读取表达式中的每个字符,对于每个字符进行分类讨论:
- 如果是数字,则将其转化为整数并入数字栈。
- 如果是左括号,则将其入操作符栈。
- 如果是右括号,则进行括号内的运算并将结果入数字栈,直至遇到左括号。
- 如果是操作符,则将其与操作符栈顶元素进行比较,如果栈顶元素优先级高于或等于该操作符,则进行计算并将结果入数字栈,直至栈顶元素优先级低于该操作符,将该操作符入操作符栈。
- 如果是负号,则判断其前一个字符是否为数字或右括号,如果是则视为负数,将其转化为整数并入数字栈,否则视为运算符,将其入操作符栈。
- 如果是空格,则忽略不处理。
3. 当表达式中的所有字符读取完毕后,依次将操作符栈中的元素取出进行计算,并将结果入数字栈,直至操作符栈为空。
4. 最终数字栈中只剩下一个元素,即为表达式的计算结果。
下面是实现过程的代码:
```c++
#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;
bool isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
int getPriority(char c) {
if (c == '+' || c == '-') return 1;
if (c == '*' || c == '/') return 2;
if (c == '^') return 3;
return 0;
}
long long calc(stack<long long>& nums, stack<char>& ops) {
long long b = nums.top();
nums.pop();
long long a = nums.top();
nums.pop();
char op = ops.top();
ops.pop();
long long res;
if (op == '+') res = a + b;
else if (op == '-') res = a - b;
else if (op == '*') res = a * b;
else if (op == '/') res = a / b;
else if (op == '^') res = pow(a, b);
return res;
}
int main() {
string expr;
getline(cin, expr);
stack<long long> nums;
stack<char> ops;
bool negative = false; // 标记负号
for (int i = 0; i < expr.length(); i++) {
char c = expr[i];
if (isdigit(c)) {
long long num = c - '0';
while (i + 1 < expr.length() && isdigit(expr[i + 1])) {
num = num * 10 + (expr[i + 1] - '0');
i++;
}
if (negative) {
num = -num;
negative = false;
}
nums.push(num);
}
else if (c == '(') {
ops.push(c);
}
else if (c == ')') {
while (ops.top() != '(') {
nums.push(calc(nums, ops));
}
ops.pop(); // 弹出左括号
}
else if (isOperator(c)) {
while (!ops.empty() && ops.top() != '(' && getPriority(ops.top()) >= getPriority(c)) {
nums.push(calc(nums, ops));
}
ops.push(c);
}
else if (c == '-') {
if (i == 0 || !isdigit(expr[i - 1]) && expr[i - 1] != ')') {
negative = true;
}
else {
while (!ops.empty() && ops.top() != '(' && getPriority(ops.top()) >= getPriority(c)) {
nums.push(calc(nums, ops));
}
ops.push(c);
}
}
}
while (!ops.empty()) {
nums.push(calc(nums, ops));
}
if (nums.size() != 1) {
cout << "Error" << endl;
}
else {
cout << nums.top() << endl;
}
return 0;
}
```
需要注意的一些细节:
1. 当读取到负号时,需要判断其前一个字符是否为数字或右括号,如果是则视为负数,否则视为运算符。
2. 当读取到数字时,需要将其转化为整数并入数字栈,如果后面还有数字则需要将其合并为一个完整的整数。同时,当读取到负号时需要将其标记为负数,等到下一个数字读取完毕后再将其转化为负数。
3. 当操作符栈为空或栈顶元素为左括号时,直接将操作符压入栈中,不再比较优先级。
4. 当表达式中出现除零错误时,只有在计算过程中才能判断,因此需要在计算时进行判断并输出错误信息。