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

news2024/11/15 15:57:59

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

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

二、需要注意的点:

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

表达式的输入: 用户需要通过命令行输入表达式,包括数字和运算符号,例如"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;
}

四、总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/439456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单CDN与融合CDN之间的对比:优缺点及注意事项

CDN是现代互联网服务的重要组成部分&#xff0c;它CDN可帮助内容提供者高速交付内容&#xff0c;不同的服务器部署在全球不同的数据中心&#xff0c;并在它们之间共享相同的网络路径。随着企业意识到CDN的重要性&#xff0c;越来越多的企业正在使用CDN作为内容分发工具。互联网…

完美解决丨RuntimeError: create_session() called before __init__().

错误&#xff1a; import sys sys.path.append(/home/pi/ssd-detect) import ssd_detect ssd_detect.detect(/home/pi/ssd-detect/test.jpg) 报错如下&#xff1a; Traceback (most recent call last): File "test.py", line 6, in <module ssd_detect.detect(/ho…

ArcGIS制作建设项目使用林地现状图

近年来&#xff0c;随着经济社会的快速发展&#xff0c;各地建设项目不断增多&#xff0c;占用征用林地项目的数量也呈逐年上升的趋势。根据《占用征用林地审核审批管理规范》规定&#xff0c;建设项目申请占用征用林地&#xff0c;应编制的项目使用林地可行性报告&#xff1b;…

Linux-升级CMake版本(Ubuntu18.4)

一、简介 在一些场景中&#xff0c;因为CMake版本过低而无法编译&#xff0c;此时就需要升级CMake的版本。 二、升级 卸载 先卸载旧的cmake sudo apt-get autoremove cmake 安装 切换文件夹 cd /usr/src 下载cmake包。需要哪个版本&#xff0c;可以自行修改版本号。 注&#…

中国人工智能公司CIMCAI集装箱识别云服务全球用户量领先核心科技领先,免费人工智能集装箱识别云服务,智能化港航中国人工智能公司

中国人工智能公司CIMCAI集装箱识别云服务全球用户量领先核心科技领先&#xff0c;免费人工智能集装箱识别云服务&#xff0c;智能化港航智慧港航.全球领先CIMCAI ENGINE集装箱AI检测云服务&#xff0c;集装箱号识别率99.98%&#xff0c;全球超4000企业用户使用&#xff0c;集装…

npm 包本地调试(详细流程:包本地路径、npm link 、yalc)

一、使用 包本地路径安装 package.json 中的包名叫 dzmtest&#xff08;这个才是重点&#xff09;&#xff0c;包的文件夹名 test。 获取到包的文件夹路径 执行安装命令&#xff0c;然后提示安装成功 $ npm install 包文件夹路径# 例如&#xff1a; $ npm install /Users/d…

【Linux】Linux第一个小程序-进度条

前言&#xff1a; 在之前的学习中&#xff0c;我们已经基本掌握了关于了 Linux 下的一些工具的使用&#xff0c;接下来我们运用之前学到的知识&#xff0c;我将带领大家写了一个关于 进度条 的小程序来练练手&#xff01;&#xff01;&#xff01; 本文目录 &#xff08;一&am…

密码模块非入侵式攻击及其缓解技术GMT0083-2020

密码模块非入侵式攻击&#xff0c;是一种攻击方式&#xff0c;在这种攻击中&#xff0c;攻击者不会直接访问受攻击者的密码模块。相反&#xff0c;攻击者会利用其他途径获得用户的凭证&#xff0c;然后使用这些凭证去访问密码模块。这种攻击通常使用钓鱼邮件、社交工程等技巧&a…

户外软件推荐与介绍——奥维和两步路

文章目录 &#xff08;一&#xff09;记录坐标的网站1、奥维互动地图注册2、记录坐标3、如何导出坐标点到ArcGIS4、导航5、记录轨迹6、下载离线地图 &#xff08;二&#xff09;记录轨迹的软件&#xff08;三&#xff09;离线地图的下载&#xff08;四&#xff09;如何使用3D地…

Chapter5-消息队列的核心机制

Broker 是 RocketMQ 的核心&#xff0c;大部分‘重量级”工作都是由 Broker 完成的&#xff0c;包括接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、&#xff0d;消息的持久化存储、消息的 HA 机制以及服务端过滤功能等。 5.1 消息存储和发送 分布式队列因为有高…

网络协议-TCP、IP协议和互联网协议群

目录 TCP/IP协议群简介&#xff08;互联网协议群&#xff09;&#xff08;Internet Protocol Suite&#xff09; 应用层&#xff08;Application&#xff09;(合并简化了展示层&#xff0c;会话层) 传输层&#xff08;Transport&#xff09; 网络层&#xff08;Internet&am…

射频功率放大器在铝板损伤量化表征中的应用

实验名称&#xff1a;基于异常指数的铝板损伤量化表征 研究方向&#xff1a;损伤量化 测试目的&#xff1a; 结构损伤检测与量化评估对于保障航空、航天、船舶、石油化工及兵器工业等领域的基础设施结构安全性具有重要意义&#xff0c;受到了广泛的关注。在现有的结构监测技术中…

微内核与宏内核

了解Linux发展史的同学都知道&#xff0c;关于linux吵架史的一段佳话&#xff0c;就是关于内核设计思想之争&#xff0c;这段故事在linus Tovalds的自传中也有提到。我们都知道linux操作系统由Linus Tovalds模仿minix操作系统开发的。 虽然Linux是受MINIX启发而发明&#xff0c…

Git——利用SSH密钥本地仓库上传远程GitHub库

文章目录 1、前言2、详细步骤2.1 创建密钥2.2 进入密钥文件并复制2.3 在GitHub上添加密钥2.4 回到本地仓库文件夹&#xff0c;连接GitHub并上传 3. 结语 1、前言 现在想要从本地设备将本地仓库上传到GitHub上需要用到SSH密钥&#xff0c;接下来讲解大致的步骤&#xff0c;本文默…

一本通 3.4.6 拓扑排序

1352&#xff1a;【例4-13】奖金 【题目描述】 由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出&#xff0c;Yali Company总经理Mr.Z心情好&#xff0c;决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。 于是Mr.Z下令召开m方会谈…

openEuler实验-基于openEuler的云景平台文件管理系统

一些常见的Linux命令 目录 前言 实验目的 实验内容 实验知识点 实验环境 实验分析 系统登录和电源管理 1&#xff09;使用login命令登录系统 2&#xff09;退出openEuler 3&#xff09;退出当前的shell 软件管理 1&#xff09;查询目录信息 2&#xff09;切换目录路…

基于Tensorflow搭建卷积神经网络CNN(服装分类)保姆及级教程

项目介绍 TensorFlow2.X 搭建卷积神经网络&#xff08;CNN&#xff09;&#xff0c;实现服装的分类识别。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠&#xff0c;然后经过全连接层&#xff0c;最后用softmax映射为每个类别的概率&#xff0c;概率最大的即为识…

25 - 回文串问题

文章目录 1. 回文子串法一&#xff1a;动态规划法二&#xff1a;双指针法 2. 最长回文子串方法一&#xff1a;动态规划法方法二&#xff1a;双指针法 3. 最长回文子序列 1. 回文子串 法一&#xff1a;动态规划 递推公式 当s[i] ! s[j]&#xff0c;那没啥好说的了&#xff0c;d…

三闯港交所,主打性价比的乡村基如何夺魁“中式快餐第一股”?

曾被中金公司称为“中国大消费最燃赛道”的中式餐饮&#xff0c;正在密集掀起IPO的风潮。去年5月和7月&#xff0c;老乡鸡和老娘舅分别向上交所提交招股书&#xff0c;绿茶餐厅、杨国福麻辣烫、捞王等企业也在推进上市计划。 国内第四大中式快餐集团&#xff0c;占据约0.6%市场…

python版pytorch模型转openvino及调用

一、openvino安装 参看官方文档https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/download.html 安装命令是根据上面的选择生成。这里安装了pytorch和onnx依赖。 二、pytorch模型转opnvino模型推理 import os import time import cv2 import nu…