【数据结构C++】表达式求值(多位数)课程设计


📚博客主页:Zhui_Yi_
🔍:上期回顾:图

❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️
🎇追当今朝天骄,忆顾往昔豪杰。
在这里插入图片描述

文章目录

  • 前言
    • 问题描述
    • 基 本 要 求
    • 实 现 提 示
  • 一、摘要以及引言
    • 摘要
    • 引言
  • 二、系统设计
  • 三、关键算法与实现
    • 1.运算符处理
    • 2.表达式求值流程
  • 四、程序实现
  • 五、具体代码
    • 1.定义结构以及初始化
    • 2.简单的链栈操作
      • 判空
      • 入栈
      • 出栈
      • 取栈顶元素
      • 判断运算符是否有效
      • 将运算符转换
      • 判断运算符优先级
      • 进行运算
      • 进行运算
      • 完整代码
  • 总结
  • 切记切记,我给出代码缺少对括号匹配的信息,但代码是能直接运行的,需要你们自己写出来。

前言

本期呢,给大家带来的课程设计,简单给大家说一哈要求:

问题描述

任 何 一 个 表 达 式 都 是 由 操 作 数 (operand)、 运 算 符 (operator)和 界 限 符
(delimiter)组 成 的 。 其 中 , 操 作 数 可 以 是 常 量 , 也 可 以 是 变 量 ; 运 算 符 可 以 是 算
术 运 算 符 、关 系 运 算 符 和 逻 位 算 符 ;界 限 符 是 左 、右 括 号 和 标 志 表 达 式 结 束 的 结 束 符。
在 本 课 程 设 计 中 ,仅 讨 论 简 单 算 术 表 达 式 的 求 值 问 题 , 约 定 表 达 式 中 只 包 含 加 、减 、 乘 、 除 4 种运算, 所 有 的 运 算 对 象 均 为 简 单 变 量 , 表 达 式 的 结 束 符 为 “ =”。
要 求以 字 符 序 列 的 形 式 从 终 端 输 入 语 法 正 确 、不 含 变 量 的 整 数 表 达 式 。 利 用 已 知 的 运 算 符 优 先 关 系 , 实 现 对 算 术 表 达 式 的 求 值 。

基 本 要 求

这 是 一 个 利 用 栈 结 构 完 成 的 程 序 。为 了 实 现 运 算 符 优 先 算 法 ,需 使 用 两 个 工 作 栈 ,一 个 称 为 运 算 符 栈 (OPTR), 用 来 寄 存 运 算 符 ; 另 一 个 称 为 操 作 数 栈 (OPND), 用 来
寄 存 操 作 数 或 运 算 结 果 。 基 本 要 求 如 下 : (1) 表 达 式 中 只 包 含 加 、 减 、 乘 、 除 4
种 运 算 , 应 按 优 先 级 进 行 运 算 。
(2) 表 达 式 中 不 包 含 变 量 。
(3) 操 作 数 应 为 整 数
(4) 操 作 数 应 包 含 1 位 数 , 2 位 数 , 3 位 数 等 不 同 数 据 。
(5) 初 始 状态: 操作数栈(OPND)为空栈,表达式结束符“ =” 为 运 算 符 栈 (OPTR)的 栈 底 元 素 。

实 现 提 示

假 设 算 术 表 达 式 Expression 内 可 以 含 有 常 量 (0~9)和 二 元 运 算 符(+, -, *, /)。 实
现 以 下 操 作 : (1) ReadExpre(E): 对 以字符序列的形式输入语法正确的 中 缀表 达 式 并 构 造 表 达 式 E。
(2) EValuation(): 对 算 术 表 达 式 E 求 值 。 (3) Compare(c1,c2): 比 较 运 算 符
优 先 级 。
(4) Operate(a,optr,b):根 据 运 算 符 optr 进 行 操 作 数 a 和 b 的 运算 。
(5) 栈 的 相 关 操 作 ( 必 须 自 己 实 现 , 不 可 使 用 现 成 的 模 板 类 )。

一、摘要以及引言

摘要

本文介绍了一个利用链栈数据结构实现的简单中缀表达式求值程序。该程序能够接收用户输入的数学表达式,支持加减乘除四则运算及括号,以等号“=”作为输入结束标志,计算表达式的值并输出结果。本文详细阐述了程序的设计思路、核心算法及实现细节,旨在为初学者提供一个学习链栈应用和表达式求值原理的实践案例。

引言

在计算机科学领域,表达式求值是一项基本而重要的任务,广泛应用于编译器设计、计算器开发等多个场景。其中,中缀表达式是最自然的数学表达形式,但直接计算中缀表达式较为复杂。本文采用栈这一数据结构,设计并实现了一个程序,能够高效地将中缀表达式转换为后缀表达式(逆波兰表示法),进而计算其值。

二、系统设计

  • 本系统主要由以下几个部分组成:
  • 链栈结构:定义了两个链栈,OPTD用于存储操作数,OPTR用于存储运算符。
    表达式解析与计算:程序首先读取用户输入的中缀表达式,然后根据运算符优先级和括号规则,将表达式转换为便于计算的形式,并最终求得结果。
    用户交互:提供友好界面,用户输入表达式,以等号结束,程序显示计算结果,并询问是否继续进行新的计算。

三、关键算法与实现

1.运算符处理

  • 运算符入栈规则:程序通过Precede函数判断新读入的运算符与栈顶运算符的优先级,优先级较低的运算符先出栈计算。
    括号处理:遇到左括号入栈,遇到右括号则弹出栈顶运算符直到遇到左括号,处理括号内表达式。
    等号处理:等号既是输入结束标志,也作为特殊运算符处理,确保表达式正确结束。

2.表达式求值流程

  1. 初始化:初始化两个链栈。
  2. 读取输入:逐字符读取用户输入的表达式。
  3. 字符处理:对每个字符判断是否为运算符、数字或结束符号,进行相应处理。
  4. 运算符优先级判定与操作数计算:使用栈结构辅助计算,遵循运算符优先级规则。
  5. 输出结果:计算完成后,输出表达式的计算结果。

四、程序实现

本程序使用C++语言实现,主要采用了结构体定义链栈,通过自定义的链栈操作函数实现了数据的入栈、出栈等操作。calculate函数为核心,负责解析和计算表达式。通过一系列条件判断和循环结构,实现了对中缀表达式的有效处理。此外,程序还包含用户交互环节,提高了用户体验。

五、具体代码

1.定义结构以及初始化

// 链栈节点结构
struct Node {double data;Node* next;
};// 链栈结构
struct LinkStack {Node* top;int size;
};// 初始化链栈
LinkStack* InitLinkStack() {LinkStack* stack = new LinkStack;stack->top = nullptr;stack->size = 0;return stack;
}

2.简单的链栈操作

判空

bool IsEmpty(LinkStack* stack) {return stack->top == nullptr;
}

入栈

// 入栈操作
void Push(LinkStack* stack, double value) {Node* node = new Node;node->data = value;node->next = stack->top;stack->top = node;stack->size++;
}

出栈

double Pop(LinkStack* stack) {if (IsEmpty(stack)) {throw runtime_error("栈是空的!");}double value = stack->top->data;Node* temp = stack->top;stack->top = stack->top->next;delete temp;stack->size--;return value;
}

取栈顶元素

// 获取栈顶元素
double GetTop(LinkStack* stack) {if (IsEmpty(stack)) {throw runtime_error("栈是空的!");}return stack->top->data;
}

判断运算符是否有效

运算符分为+、-、*、/、=,即:

bool In(char c) {if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '=')return true;return false;
}

将运算符转换

int intdata(char c) {switch (c) {case '+': return 0;case '-': return 1;case '*': return 2;case '/': return 3;case '(': return 4;case ')': return 5;case '=': return 6; default: break;}
}

判断运算符优先级

在这里插入图片描述
根据这张图片进行建立二维数组。

char Precede(char c1, char c2) {int a, b;char table[7][7] = {'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=','0','>','>','>','>','0','>','>','<','<','<','<','<','0','=',};a = intdata(c1); b = intdata(c2);return table[a][b];
}

进行运算

double operate(double a, char c, double b) {if (c == '+') return (a + b);else if (c == '-') return (a - b);else if (c == '*') return (a * b);else if (c == '/') {if (b == 0) return (flag = 1);else return (a / b);}
}

进行运算

double calculate() {char ch, tempc;double x, y, temp, count = 0;Push(OPTR, '='); cin >> ch;while (ch != '=' || GetTop(OPTR) != '=') { if (!In(ch)) {if (count != 0) {temp = GetTop(OPTD); Pop(OPTD);temp = (double)(temp * 10 + ch - '0');Push(OPTD, temp);cin >> ch;}else {temp = (double)(ch - '0');Push(OPTD, temp);count++;cin >> ch;}}else {count = 0;switch (Precede(GetTop(OPTR), ch)) {case '<':Push(OPTR, ch);cin >> ch;break;case '>':tempc = GetTop(OPTR); Pop(OPTR);y = GetTop(OPTD); Pop(OPTD);x = GetTop(OPTD); Pop(OPTD);Push(OPTD, operate(x, tempc, y));break;case '=':tempc = GetTop(OPTR); Pop(OPTR);cin >> ch;break;default:break;}}}return GetTop(OPTD);
}

完整代码

#include <iostream>
#include <string>using namespace std;// 链栈节点结构
struct Node {double data;Node* next;
};// 链栈结构
struct LinkStack {Node* top;int size;
};// 初始化链栈
LinkStack* InitLinkStack() {LinkStack* stack = new LinkStack;stack->top = nullptr;stack->size = 0;return stack;
}// 判断栈是否为空
bool IsEmpty(LinkStack* stack) {return stack->top == nullptr;
}// 入栈操作
void Push(LinkStack* stack, double value) {Node* node = new Node;node->data = value;node->next = stack->top;stack->top = node;stack->size++;
}// 出栈操作
double Pop(LinkStack* stack) {if (IsEmpty(stack)) {throw runtime_error("栈是空的!");}double value = stack->top->data;Node* temp = stack->top;stack->top = stack->top->next;delete temp;stack->size--;return value;
}// 获取栈顶元素
double GetTop(LinkStack* stack) {if (IsEmpty(stack)) {throw runtime_error("栈是空的!");}return stack->top->data;
}// 全局链栈
LinkStack* OPTD = InitLinkStack();
LinkStack* OPTR = InitLinkStack();
int flag = 0;// 判断字符是否为运算符
bool In(char c) {if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '=')return true;return false;
}// 将运算符转换为序号
int intdata(char c) {switch (c) {case '+': return 0;case '-': return 1;case '*': return 2;case '/': return 3;case '(': return 4;case ')': return 5;case '=': return 6; // 修改这里,添加'='的序号default: break;}
}// 判定运算符优先级
char Precede(char c1, char c2) {int a, b;char table[7][7] = {'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=','0','>','>','>','>','0','>','>','<','<','<','<','<','0','=',};a = intdata(c1); b = intdata(c2);return table[a][b];
}// 执行运算
double operate(double a, char c, double b) {if (c == '+') return (a + b);else if (c == '-') return (a - b);else if (c == '*') return (a * b);else if (c == '/') {if (b == 0) return (flag = 1);else return (a / b);}
}// 表达式求值
double calculate() {char ch, tempc;double x, y, temp, count = 0;Push(OPTR, '='); cin >> ch;while (ch != '=' || GetTop(OPTR) != '=') { if (!In(ch)) {if (count != 0) {temp = GetTop(OPTD); Pop(OPTD);temp = (double)(temp * 10 + ch - '0');Push(OPTD, temp);cin >> ch;}else {temp = (double)(ch - '0');Push(OPTD, temp);count++;cin >> ch;}}else {count = 0;switch (Precede(GetTop(OPTR), ch)) {case '<':Push(OPTR, ch);cin >> ch;break;case '>':tempc = GetTop(OPTR); Pop(OPTR);y = GetTop(OPTD); Pop(OPTD);x = GetTop(OPTD); Pop(OPTD);Push(OPTD, operate(x, tempc, y));break;case '=':tempc = GetTop(OPTR); Pop(OPTR);cin >> ch;break;default:break;}}}return GetTop(OPTD);
}// 菜单函数
void menu() {puts("\n=========================\n");puts("       表达式求值");puts("\n=========================\n");
}// 主函数
int main() {menu();double answer, trueValue = 1;while (trueValue) {cout << "\n请输入表达式,以等号(=)结束:"; answer = calculate();if (flag == 1) {cout << "分母不能为0哦!" << endl;flag = 0;}elsecout << "表达式的值为:" << answer << endl;cout << "按0可结束程序,继续请按1:";cin >> trueValue;}return 0;
}

在这里插入图片描述

总结

本文通过设计链栈数据结构和实现相应的算法,成功开发了一个能够处理中缀表达式的程序。该程序不仅能够正确计算表达式的值,还具备良好的用户交互体验,适合教学和初步编程实践。未来的工作可以考虑扩展程序功能,支持更多类型的运算符和更复杂的表达式结构。

切记切记,我给出代码缺少对括号匹配的信息,但代码是能直接运行的,需要你们自己写出来。

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

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

相关文章

【机器学习】第7章 集成学习(小重点,混之前章节出题但小题)

一、概念 1.集成学习&#xff0c;顾名思义&#xff0c;不是一个玩意&#xff0c;而是一堆玩意混合到一块。 &#xff08;1&#xff09;基本思想是先 生成一定数量基学习器&#xff0c;再采用集成策略 将这堆基学习器的预测结果组合起来&#xff0c;从而形成最终结论。 &#x…

pdf怎么压缩到2m以内或5m以内的方法

PDF作为一种广泛使用的文档格式&#xff0c;已经成为我们工作和生活中不可或缺的一部分。然而&#xff0c;有时候PDF文件内存会比较大&#xff0c;给我们的存储和传输带来了很大的不便。因此&#xff0c;学会压缩 PDF 文件是非常必要的。 打开"轻云处理pdf官网"&…

js语法---理解防抖原理和实现方法

什么是防抖&#xff08;节流&#xff09; 在实际的网页交互中&#xff0c;如果一个事件高频率的触发&#xff0c;这会占用很多内存资源&#xff0c;但是实际上又并不需要监听触发如此多次这个事件&#xff08;比如说&#xff0c;在抢有限数量的优惠券时&#xff0c;用户往往会提…

Scott Brinker:API对今天的Martech用户来说「非常重要」 ,但它们对即将到来的人工智能代理浪潮至关重要

API在Martech中非常重要 猜一猜空格应该填什么&#xff1a; _______之于AI代理就像数据之于AI模型 正如你可能从我的标题猜到的那样&#xff0c;答案是API。让我们讨论一下为什么…… 数据是人工智能模型的差异化 在过去的一年半里&#xff0c;人工智能疯狂的超级炒作周期…

Repetition Improves Language Model Embeddings论文阅读笔记

文章提出了一种提高decoder-only LLM的embedding能力的方法&#xff0c;叫echo embeddingslast-token pooling&#xff08;即直接选最后一个token作为句子的embedding&#xff09;和直接mean pooling都不如文章提出的echo embedding&#xff0c;做法是把句子重复两次&#xff0…

OpenGL Super Bible 7th - Drawing Our First Triangle(绘制第一个三角形)

简介 本文的原版为《OpenGL Super Bible 7th》,是同事给我的,翻译是原文+译文的形势。文章不属于机器直译,原因在于语言不存在一一对应的关系,我将尽可能的按照中国人看起来舒服的方式来翻译这些段子,如果段子让你感到身心愉悦,那还劳烦点个关注,追个更。如果我没有及时…

【论文阅读】-- Attribute-Aware RBFs:使用 RT Core 范围查询交互式可视化时间序列颗粒体积

Attribute-Aware RBFs: Interactive Visualization of Time Series Particle Volumes Using RT Core Range Queries 1 引言2 相关工作2.1 粒子体渲染2.2 RT核心方法 3 渲染彩色时间序列粒子体积3.1 场重构3.1.1 密度场 Φ3.1.2 属性字段 θ3.1.3 优化场重建 3.2 树结构构建与调…

算法题day45(补5.31日卡:动态规划05)

一、完全背包理论基础&#xff1a; 完全背包和01背包问题唯一不通过的地方就是&#xff0c;每种物品有无限件。 二、刷题&#xff1a; 1.卡码网 52. 携带研究材料&#xff08;第七期模拟笔试&#xff09; (kamacoder.com)(medium&#xff09; 解决: nv input().strip().sp…

如何在 Windows 中安装 Spire.PDF for Python

Spire.PDF for Python 是一款完全独立的 PDF 开发组件&#xff0c;用于在任何 Python 应用程序中读取、创建、编辑和转换 PDF 文件。本文将介绍如何在 Windows 中安装 Spire.PDF for Python。 最新python安装激活教程在下方&#xff1a; 步骤1 下载最新版的 Python 并将其安装…

MYSQL数据库安装

一.编译安装MySQL服务 1.安装环境依赖包 2.将安装mysql 所需软件包传到/opt目录下 mysql-boost-5.7.44.tar tar zxvf mysql-boost-5.7.44.tar.gz 3.配置软件模块 cd /opt/mysql-5.7.44/ cmake \ -DCMAKE_INSTALL_PREFIX/usr/local/mysql \ -DMYSQL_UNIX_ADDR/usr/local/mysq…

MyBatis中获取Mysql数据库插入记录的主键值

在MyBatis中&#xff0c;你可以使用多种方式获取插入记录的主键值。以下是常见的几种方法&#xff1a; 1. 使用 useGeneratedKeys 和 keyProperty 这是MyBatis提供的最直接的方法。在你的Mapper XML文件中&#xff0c;使用 useGeneratedKeys 和 keyProperty 来指定MyBatis在插…

ES8新特性:async函数

1、async函数 返回值为promise对象&#xff1b;promise对象的结果由async函数执行的返回值决定。 2、await 表达式 await 必须写在 async 函数里面&#xff1b;await 右侧的表达式一般为promise对象,返回该对象的结果&#xff0c;如果不是promise对象&#xff0c;就直接返回对…

【云手机】数据安全如何保障?

安全办公&#xff0c;信息安全&#xff0c;这是企业使用云手机的初衷和目的&#xff0c;云手机在数据保密&#xff0c;远程办公等功能上有巨大的优势&#xff0c;也为企业提供了支持 首先就是云手机能够实现数据的集中管理和加密存储。所有办公相关的数据都存储在云端的安全服务…

2024加密软件排行榜|最新企业常用加密软件推荐

安秉网盾加密软件&#xff1a; 专注于企业级的透明加密解决方案&#xff0c;确保公司内部文件在公司环境外无法被访问。 审批机制灵活&#xff0c;支持多种审批方式&#xff0c;方便管理。 广泛应用于多个行业&#xff0c;拥有丰富的企业环境适配经验。 适合对内部数据安全有严…

音乐管理系统 SpringBoot + vue

文章目录 1、简要介绍2、数据库设计3、解决的问题1、图片和音频的上传和存储2、分页功能 4、数据返回 也算是进行了半个学期&#xff0c;跟着老师讲的进行 后端使用SpringBoot 前端 vue layui jdk 18 项目地址&#xff1a;gitee 1、简要介绍 只有管理端&#xff0c;但是对用…

ORA-12560: TNS:协议适配器错误

项目场景&#xff1a; 由于最近一直没有连接oracle&#xff0c;然后之前windows也是正常可以启动oracle&#xff0c;正常连接。无论是SQL Developer还是SQL PLUS命令&#xff0c;都能正常连接和操作。 问题描述 这两天刚好用SQL Developer工具连接&#xff0c;然后报错&#…

[C#] opencvsharp对Mat数据进行序列化或者反序列化以及格式化输出

【简要介绍】 在OpenCVSharp中&#xff0c;FileStorage类用于将数据&#xff08;包括OpenCV的Mat类型数据&#xff09;序列化为XML或YAML格式的文件&#xff0c;以及从这些文件中反序列化数据。以下是关于FileStorage类用法的详细说明&#xff1a; 写入数据&#xff08;序列化…

React-Redux

什么是Redux&#xff1f; Redux是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia&#xff08;Vuex&#xff09;&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管理应用的状态 例子&#xff1a;不和任何框架绑定&#xff0c;不使用任何构…

图像处理与视觉感知复习--形态学图像处理

文章目录 计算图像膨胀和腐蚀计算开操作和闭操作击中或击不中变化 计算图像膨胀和腐蚀 定义&#xff1a; A c A^c Ac 表示集合A的补集几何的反射 有集合A中所有元素相对于原点的反射元素组成的集合称为集合A的反射&#xff0c;几位 A ^ \hat{A} A^ A ^ { w ∣ w − a , a …

SpringTask-Timer实现定时任务

1、Timer 实现定时任务 1.1、JDK1.3 开始推出定时任务实现工具。 1.2、API 执行代码 public static void main(String[] args) throws ParseException {Timer timer new Timer();String str"2024-06-10 23:24:00";Date date new SimpleDateFormat("yyyy-MM…