AI开发C语言应用按步走,表达式计算器calc的第三步,表达式求值器(带运算符优先级)
calc3 — 表达式求值器带运算符优先级1. 概述本次迭代将 calc2 的 tokenizer词法分析器升级为完整的表达式求值器实现了带运算符优先级的递归下降解析。功能变化项目calc1/calc2calc3输入(90-18)/315(90-18)/315输出逐行列出 token计算结果39优先级无仅线性扫描*/%优先于-括号仅识别括号内优先求值除法/取模仅识别运行时检查除零错误2. 变更清单文件操作说明parse.h编辑新增parse_peek()/parse_consume()APIparse.c编辑实现 lookahead 缓冲区增加has_lookahead状态eval.h新建声明eval_expr(input, result)eval.c新建递归下降求值器4 层语法函数~180 行main.c编辑改为调用eval_expr()输出结果Makefile编辑SRC加入eval.ctest目标改为三列校验退出码 输出值test.expr编辑增加第三列期望输出值3. 运算符优先级体系3.1 优先级层次优先级语法层运算符结合性1 (最低)expr-左结合2term*/%左结合3 (最高)unary一元-右结合—factor( )括号、数字字面量—3.2 文法定义expr → term (( | -) term)* term → unary ((* | / | %) unary)* unary → - unary | factor factor → NUMBER | ( expr ) | ERROR每个语法层函数消费对应的 token 并返回整数值通过函数调用层次隐式表达优先级staticintparse_expr(void)// 处理 -staticintparse_term(void)// 处理 * / %staticintparse_unary(void)// 处理一元 -staticintparse_factor(void)// 处理数字、括号4. 核心实现4.1 lookahead 缓冲区递归下降解析器需要预读peek下一个 token 来决定走哪个分支因此需要在 tokenizer 之上增加一层缓冲区。parse.h 新增 APITokenparse_peek(void);// 预读下一个 token不消费可多次调用Tokenparse_consume(void);// 消费并返回下一个 tokenparse.c 内部状态staticToken lookahead;// 缓冲区staticinthas_lookahead;// 1 已缓存parse_peek()第一次调用时会调用parse_next()将结果存入缓冲区后续调用直接返回缓冲区内容。parse_consume()清空缓冲区并返回内容下次读取时重新调用parse_next()。4.2 递归下降求值器eval.cparse_expr() ← 入口 ├─ parse_term() ← 处理 * / % │ ├─ parse_unary() ← 处理一元 - │ │ ├─ parse_factor() ← 处理数字、( ) │ │ │ ├─ NUMBER → 返回数值 │ │ │ ├─ (expr) → 递归 parse_expr() │ │ │ └─ ERROR → 报错 │ │ └─ -unary → 递归 parse_unary() 取负 │ └─ 循环处理 * / % └─ 循环处理 -关键代码expr 层staticintparse_expr(void){intleftparse_term();while(!eval_error){Token tparse_peek();if(t.typeTOKEN_PLUS){parse_consume();leftleftparse_term();}elseif(t.typeTOKEN_MINUS){parse_consume();leftleft-parse_term();}else{break;}}returnleft;}错误处理错误场景处理方式非法字符如factor中遇到TOKEN_ERROR输出列号并返回 1除零/模零term中运行时检查输出division by zero并返回 1不匹配的括号factor中(后未找到)时expect()失败多余 tokeneval_expr解析完后检查是否还有未消费的 token空输入eval_expr入口直接返回 14.3 main.c 入口staticintparse_and_eval(constchar*input){intresult;if(eval_expr(input,result)!0)return1;printf(%d\n,result);return0;}5. 测试套件升级5.1 test.expr 三列格式表达式 | 期望退出码 | 期望输出值#表达式退出码输出覆盖场景1(90-18)/315039基本表达式回归210%301取模3-530-2负号 加法43-50-2运算符后负号5(-3)0-3括号内负号6(-820)%-300混合 取模 负号73 508空格835*2013*优先于9(35)*2016括号覆盖优先级1010/2308/优先于1110%3*202%*同级左结合12351—非法字符13empty1—空输入5.2 Makefile test 目标更新为同时校验退出码和输出值while IFS| read -r expr expected expected_out; do \ # ... 去空格 ... actual_out$$($(TARGET) $$expr 2/dev/null); actual$$?; \ if [ $$actual $$expected ]; then \ if [ -z $$expected_out ] || [ $$actual_out $$expected_out ]; then \ printf PASS [%2d] %-22s → %s\n ...; \ fi; \ fi; \ done6. 目录结构更新后calc/ ├── Makefile # 构建脚本含 test 目标 ├── parse.h # tokenizer 头文件含 peek/consume API ├── parse.c # tokenizer 实现含 lookahead 缓冲区 ├── eval.h # 求值器头文件新增 ├── eval.c # 递归下降求值器实现新增 ├── main.c # 入口程序改为求值输出 ├── test.expr # 测试用例文件三列格式 ├── doc/ │ ├── calc1.md # 第一次构建tokenizer 基础 │ ├── calc2.md # 第二次构建取模、负号区分、测试套件 │ └── calc3.md # 本次构建表达式求值器 └── build/ ├── calc ├── parse.o ├── eval.o └── main.o7. 测试验证7.1 回归测试$maketestcalc — 测试套件PASS[1](90-18)/315 →39PASS[2]10%3 →1PASS[3]-53 →-2PASS[4]3-5 →-2PASS[5](-3)→-3PASS[6](-820)%-3 →0PASS[7]35→8PASS[8]35*2 →13PASS[9](35)*2 →16PASS[10]10/23 →8PASS[11]10%3*2 →2PASS[12]35 → error PASS[13]empty→ error13passed,0failed,13total7.2 优先级验证输入期望实际输出验证点35*23101313*优先于(35)*28*21616括号最高优先级10/235388/优先于10%3*211*2133%*同级左结合--5-(-5)55一元-右结合3/0errordivision by zero除零检查

相关新闻

AI学术截止日期管理:GitHub+Markdown驱动的社区化Deadline工具

AI学术截止日期管理:GitHub+Markdown驱动的社区化Deadline工具

1. 项目概述:一个被低估的AI从业者生存工具你有没有在凌晨三点盯着电脑屏幕,手指悬在键盘上,心里发慌——不是因为模型跑崩了,而是突然想起三天后就是NeurIPS的投稿截止日,而你的实验还没复现完?或者翻遍邮…

2026/7/20 10:41:12阅读更多 →
从零开始:用Path of Building 2打造你的PoE2完美角色

从零开始:用Path of Building 2打造你的PoE2完美角色

从零开始:用Path of Building 2打造你的PoE2完美角色 【免费下载链接】PathOfBuilding-PoE2 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding-PoE2 你是否在《流放之路2》中为角色构建感到困惑?面对复杂的天赋树、装备搭配和伤…

2026/7/20 10:41:12阅读更多 →
Bagging防抖原理:用自助采样降低模型预测波动

Bagging防抖原理:用自助采样降低模型预测波动

1. 项目概述:为什么“装袋法”不是在给模型打包快递,而是给预测结果加了一层防抖滤镜?“Ensemble Methods Explained in Plain English: Bagging”——这个标题里藏着一个被教科书反复包装、却常被初学者误读成“高级黑科技”的朴素思想。我带…

2026/7/20 10:41:12阅读更多 →
找家政不能只看价格:选择服务时,这些信息更重要

找家政不能只看价格:选择服务时,这些信息更重要

过去找家政服务,很多消费者习惯通过熟人介绍、社区信息、微信群或者电话联系。这种方式简单直接,但随着家庭服务需求越来越多,消费者也逐渐发现,家政服务并不是简单的“找个人上门”。一次完整的家政服务,通常涉及服务…

2026/7/21 5:02:37阅读更多 →
21M小模型碾压百倍大模型,卫星影像理解迎来新时代

21M小模型碾压百倍大模型,卫星影像理解迎来新时代

这项由剑桥大学、英伟达和dClimate Labs联合完成的研究,以预印本形式发布于2026年7月4日,论文编号为arXiv:2607.03949v1,有兴趣深入了解的读者可以通过该编号查询完整论文。地球正面临着一个数据悖论:我们从未像今天这样拥有如此海…

2026/7/21 5:02:37阅读更多 →
RevokeMsgPatcher:基于内存补丁技术的企业级即时通讯消息保护解决方案深度解析

RevokeMsgPatcher:基于内存补丁技术的企业级即时通讯消息保护解决方案深度解析

RevokeMsgPatcher:基于内存补丁技术的企业级即时通讯消息保护解决方案深度解析 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地…

2026/7/21 5:02:37阅读更多 →
C++实现校园导航系统:迪杰斯特拉算法与图数据结构实战

C++实现校园导航系统:迪杰斯特拉算法与图数据结构实战

1. 项目概述与核心价值最近在整理大学时期的项目,翻出了这个“校园导航系统”,一个基于C和迪杰斯特拉算法实现的课程设计。当时觉得就是个普通的算法应用,现在回头看,它其实是一个绝佳的、将数据结构、算法、面向对象编程和实际问…

2026/7/21 5:02:37阅读更多 →
英雄联盟换肤之旅:我与R3nzSkin的72小时奇妙冒险

英雄联盟换肤之旅:我与R3nzSkin的72小时奇妙冒险

英雄联盟换肤之旅:我与R3nzSkin的72小时奇妙冒险 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin 还记得那个周末的深夜吗?我盯着屏幕上那个已经玩了300场的英雄&am…

2026/7/21 5:02:37阅读更多 →
C++并行计算框架设计:从任务抽象、线程池到工作窃取与性能优化

C++并行计算框架设计:从任务抽象、线程池到工作窃取与性能优化

1. 项目概述:为什么我们需要一个自己的并行计算框架?在C开发领域,尤其是涉及高性能计算、实时数据处理或者大规模仿真时,多线程并行计算几乎是绕不开的话题。你可能用过std::thread,也调过std::async,甚至被…

2026/7/21 5:00:36阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/20 18:51:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/20 18:51:18阅读更多 →