C++学习之交互式表达式求值的详细讲解和简单代码示例

文章介绍了如何用C++编写一个简单的交互式表达式求值程序,包括用户输入检查、表达式解析、运算符优先级处理和计算过程。程序通过栈来处理运算符和数字,支持四则运算,但不处理复杂表达式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、怎么理解交互式表达式求值:

交互式求表达式值是指通过命令行交互的方式,接收用户输入的数值和运算符号,然后计算出其表达式的值并返回给用户。这种方式可以方便地进行简单的计算和查错,也可以用于程序设计中一系列复杂的计算。
在这里插入图片描述

二、需要注意的点:

实现交互式求表达式的值需要考虑以下几点:

表达式的输入: 用户需要通过命令行输入表达式,包括数字和运算符号,例如"2+3*4"。在输入时需要对输入进行检查,排除可能的错误。

表达式的解析: 将输入的字符串转换为可以计算的形式,例如将"2+3*4"转化为"2+12",并且保证运算的正确性。

计算表达式的值: 根据解析好的表达式,按照优先级依次进行计算,最终得到表达式的值。在计算过程中需要注意运算符的优先级和左右结合性。

三、详细实现过程:

下面以C++代码为例,展示一个简单的交互式求表达式的值程序的实现:

首先,我们需要定义一个函数来判断一个字符是否是运算符。可以采用简单暴力的方法,比如在代码中写出所有可能的运算符。这种方法虽然有点麻烦,但是可以保证正确性。以下是一个示例实现:

bool is_operator(char c) {
    switch (c) {
        case '+':
        case '-':
        case '*':
        case '/':
            return true;
        default:
            return false;
    }
}

接下来,定义一个函数来判断两个运算符的优先级。我们可以将每个运算符赋予一个权重值,然后比较它们的权重值大小即可。以下是一个示例实现:

int get_priority(char op) {
    switch (op) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return -1;  // 如果不是运算符,则返回-1
    }
}

bool has_higher_priority(char op1, char op2) {
    int p1 = get_priority(op1);
    int p2 = get_priority(op2);
    return p1 >= p2;  // 注意这里的大于等于号,表示左结合性
}

接着,定义一个函数来计算两个数的结果。根据输入的运算符,选用相应的计算方法即可。以下是一个示例实现:

double calculate(double num1, double num2, char op) {
    switch (op) {
        case '+':
            return num1 + num2;
        case '-':
            return num1 - num2;
        case '*':
            return num1 * num2;
        case '/':
            return num1 / num2;
        default:
            return 0;  // 如果不是运算符,则返回0
    }
}

接下来,定义一个函数来解析表达式。该函数将输入的字符串转换为一个包含数字和运算符的vector容器,方便后续计算。在解析表达式时,需要注意操作数可能有多位数,所以需要进行合并。以下是一个示例实现:

vector<string> parse_expression(string expression) {
    vector<string> tokens;
    int i = 0;
    while (i < expression.length()) {
        char c = expression[i];
        if (is_operator(c)) {  // 如果是运算符,则直接加入vector中
            string token(1, c);
            tokens.push_back(token);
            i++;
        } else if (isdigit(c)) {  // 如果是数字,则将其合并
            string number("");
            while (i < expression.length() && isdigit(expression[i])) {
                number += expression[i];
                i++;
            }
            tokens.push_back(number);
        } else {  // 其他情况视为非法字符,忽略掉
            i++;
        }
    }
    return tokens;
}

最后,我们可以定义一个函数,按照优先级依次计算表达式的结果。该函数使用两个栈来实现:一个用于存储数字,一个用于存储运算符。当遇到一个运算符时,先判断其优先级是否大于等于栈顶的运算符,如果是,则将该运算符入栈;否则,将栈顶的操作符弹出,并计算栈顶的两个数字的结果,然后将结果入栈。如果是一个括号,则需要进行相应的处理。计算完成后,最终栈中仅剩下一个数字值,即为表达式的结果。以下是一个示例实现:

double evaluate_expression(string expression) {
    vector<string> tokens = parse_expression(expression);
    stack<double> numbers;
    stack<char> operators;

    for (int i = 0; i < tokens.size(); i++) {
        string token = tokens[i];
        if (token == "(") {  // 括号特殊处理
            operators.push(token[0]);
        } else if (token == ")") {
            while (!operators.empty() && operators.top() != '(') {
                char op = operators.top();
                operators.pop();
                double num2 = numbers.top();
                numbers.pop();
                double num1 = numbers.top();
                numbers.pop();
                numbers.push(calculate(num1, num2, op));
            }
            operators.pop();  // 将左括号弹出
        } else if (is_operator(token[0])) {  // 运算符处理
            while (!operators.empty() &&
                   has_higher_priority(operators.top(), token[0])) {
                char op = operators.top();
                operators.pop();
                double num2 = numbers.top();
                numbers.pop();
                double num1 = numbers.top();
                numbers.pop();
                numbers.push(calculate(num1, num2, op));
            }
            operators.push(token[0]);
        } else {  // 数字处理
            numbers.push(stod(token));
        }
    }

    while (!operators.empty()) {  // 处理剩余的运算符
		char op = operators.top();
		operators.pop();
		double num2 = numbers.top();
		numbers.pop();
		double num1 = numbers.top();
		numbers.pop();
		numbers.push(calculate(num1, num2, op));
	}

	return numbers.top();
}

在这里插入图片描述

最后,我们可以把上述函数组合成一个完整的程序,实现交互式求表达式的值。以下是一个示例实现:

#include <iostream>
#include <stack>
#include <vector>

using namespace std;

bool is_operator(char c) {
    switch (c) {
        case '+':
        case '-':
        case '*':
        case '/':
            return true;
        default:
            return false;
    }
}

int get_priority(char op) {
    switch (op) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return -1;  // 如果不是运算符,则返回-1
    }
}

bool has_higher_priority(char op1, char op2) {
    int p1 = get_priority(op1);
    int p2 = get_priority(op2);
    return p1 >= p2;  // 注意这里的大于等于号,表示左结合性
}

double calculate(double num1, double num2, char op) {
    switch (op) {
        case '+':
            return num1 + num2;
        case '-':
            return num1 - num2;
        case '*':
            return num1 * num2;
        case '/':
            return num1 / num2;
        default:
            return 0;  // 如果不是运算符,则返回0
    }
}

vector<string> parse_expression(string expression) {
    vector<string> tokens;
    int i = 0;
    while (i < expression.length()) {
        char c = expression[i];
        if (is_operator(c)) {  // 如果是运算符,则直接加入vector中
            string token(1, c);
            tokens.push_back(token);
            i++;
        } else if (isdigit(c)) {  // 如果是数字,则将其合并
            string number("");
            while (i < expression.length() && isdigit(expression[i])) {
                number += expression[i];
                i++;
            }
            tokens.push_back(number);
        } else {  // 其他情况视为非法字符,忽略掉
            i++;
        }
    }
    return tokens;
}

double evaluate_expression(string expression) {
    vector<string> tokens = parse_expression(expression);
    stack<double> numbers;
    stack<char> operators;

    for (int i = 0; i < tokens.size(); i++) {
        string token = tokens[i];
        if (token == "(") {  // 括号特殊处理
            operators.push(token[0]);
        } else if (token == ")") {
            while (!operators.empty() && operators.top() != '(') {
                char op = operators.top();
                operators.pop();
                double num2 = numbers.top();
                numbers.pop();
                double num1 = numbers.top();
                numbers.pop();
                numbers.push(calculate(num1, num2, op));
            }
            operators.pop();  // 将左括号弹出
        } else if (is_operator(token[0])) {  // 运算符处理
            while (!operators.empty() &&
                   has_higher_priority(operators.top(), token[0])) {
                char op = operators.top();
                operators.pop();
                double num2 = numbers.top();
                numbers.pop();
                double num1 = numbers.top();
                numbers.pop();
                numbers.push(calculate(num1, num2, op));
            }
            operators.push(token[0]);
        } else {  // 数字处理
            numbers.push(stod(token));
        }
    }

    while (!operators.empty()) {  // 处理剩余的运算符
        char op = operators.top();
        operators.pop();
        double num2 = numbers.top();
        numbers.pop();
        double num1 = numbers.top();
        numbers.pop();
        numbers.push(calculate(num1, num2, op));
    }

    return numbers.top();
}

int main() {
    string expression;
    cout << "请输入表达式(仅支持整数和四则运算):" << endl;
    getline(cin, expression);

    double result = evaluate_expression(expression);
    cout << "计算结果为:" << result << endl;

    return 0;
}

四、总结

通过上面的代码,我们可以实现基本的交互式求表达式的值功能。但需要注意,该程序仅支持整数和四则运算,如果要支持更复杂的表达式,需要进行一定的修改。
希望对看到的小伙伴有帮助。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逃逸的卡路里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值