C++实现算式字符串的输入,输出算式的值
在 C++ 中实现算式字符串的输入和计算功能可以涉及多个步骤,包括解析字符串、处理运算符和运算数,以及计算最终的结果。以下是详细的步骤和示例代码,帮助你实现这一功能:
1. 解析算式字符串
为了计算算式的值,你需要首先解析字符串中的运算符和运算数。一般来说,可以使用两种方法:递归下降解析和 Shunting-yard 算法。这里我们使用 Shunting-yard 算法将表达式转换为后缀表达式,然后计算其值。
2. 实现步骤
2.1 定义运算符优先级
运算符优先级和结合性是计算算式的关键。定义优先级和结合性:
cpp#include <unordered_map>
#include <cctype>
#include <string>
std::unordered_map<char, int> precedence = {
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}
};
2.2 将中缀表达式转换为后缀表达式
使用 Shunting-yard 算法将中缀表达式转换为后缀表达式:
cpp#include <stack>
#include <vector>
#include <sstream>
#include <cctype>
#include <iostream>
// 将中缀表达式转换为后缀表达式
std::vector<std::string> infixToPostfix(const std::string& expression) {
std::stack<char> operators;
std::vector<std::string> output;
std::stringstream number;
for (char ch : expression) {
if (std::isdigit(ch)) {
number << ch;
} else {
if (!number.str().empty()) {
output.push_back(number.str());
number.str("");
}
if (ch == '(') {
operators.push(ch);
} else if (ch == ')') {
while (!operators.empty() && operators.top() != '(') {
output.push_back(std::string(1, operators.top()));
operators.pop();
}
operators.pop(); // pop the '('
} else if (precedence.find(ch) != precedence.end()) {
while (!operators.empty() && precedence[operators.top()] >= precedence[ch]) {
output.push_back(std::string(1, operators.top()));
operators.pop();
}
operators.push(ch);
}
}
}
if (!number.str().empty()) {
output.push_back(number.str());
}
while (!operators.empty()) {
output.push_back(std::string(1, operators.top()));
operators.pop();
}
return output;
}
2.3 计算后缀表达式的值
使用栈来计算后缀表达式的值:
cpp#include <stack>
#include <string>
#include <vector>
#include <stdexcept>
#include <iostream>
// 计算后缀表达式的值
double evaluatePostfix(const std::vector<std::string>& postfix) {
std::stack<double> values;
for (const std::string& token : postfix) {
if (std::isdigit(token[0])) {
values.push(std::stod(token));
} else {
double right = values.top(); values.pop();
double left = values.top(); values.pop();
switch (token[0]) {
case '+': values.push(left + right); break;
case '-': values.push(left - right); break;
case '*': values.push(left * right); break;
case '/':
if (right == 0) throw std::runtime_error("Division by zero");
values.push(left / right); break;
default: throw std::runtime_error("Unknown operator");
}
}
}
return values.top();
}
2.4 主函数示例
将以上部分结合起来,创建一个主函数来处理输入和输出:
cppint main() {
std::string expression;
std::cout << "Enter an expression: ";
std::getline(std::cin, expression);
// 去除空格
expression.erase(remove(expression.begin(), expression.end(), ' '), expression.end());
try {
std::vector<std::string> postfix = infixToPostfix(expression);
double result = evaluatePostfix(postfix);
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
总结
- 定义运算符优先级:设定不同运算符的优先级和结合性。
- 中缀转后缀:使用 Shunting-yard 算法将中缀表达式转换为后缀表达式。
- 计算后缀表达式:使用栈计算后缀表达式的值。
- 处理输入输出:读取用户输入的算式,进行转换和计算,然后输出结果。
通过以上步骤,你可以实现一个简单的算式计算器,能够处理基本的数学运算。