当前位置: 首页 > news >正文

运算表达式求值(递归下降分析法)


author: hjjdebug
date: 2026年 01月 12日 星期一 15:12:49 CST
descrip: 运算表达式求值(递归下降分析法)


运算是简单的,但分析是复杂的,需要应对各种用户的输入,并给出结果或错误提示!
怎么应对用户的灵活输入, 那就是3个分析函数. 并且是递归下降的.
所谓下降,就是一个套一个,越向下级别越低.(实际是优先级更高)
递归,则是自己直接或间接调用自己. 当然了,参数肯定要不一样了.

代码特点:
实现了完整的递归下降解析器,包含加减解析、乘除解析和因子解析三个解析函数 符合编译原理中的经典解析方法
支持浮点数操作
支持负数和正数符号处理
具备完善的错误处理机制,包括非法字符检测、括号匹配检查、除零错误等
支持连续计算和退出命令
包含详细的注释说明各个功能模块的作用

200行代码,就是逐级分析实现句法功能.

附录: 完整代码

$cat main.c#include<stdio.h>#include<stdlib.h>#include<ctype.h>//for isdigit#include<string.h>#include<math.h>//for fabs// 全局变量char*expression;intpos;inthasErr;//基本函数// 跳过空格voidskipSpaces(){while(expression[pos]==' '){pos++;}}// 检查是否为操作符intisOperator(charc){return(c=='+'||c=='-'||c=='*'||c=='/');}// 把分析进一步分割为分析加减法,分析乘除法,分析基本项// 它们构成递归下降分析. 上层只需要调用顶层即可.doubleparseAdd();doubleparseMultiple();doubleparseItem();// 解析因子(处理数字和括号)doubleparseItem(){if(hasErr)return0.0;skipSpaces();// 处理负号if(expression[pos]=='-'){pos++;skipSpaces();return-parseItem();}// 处理正号if(expression[pos]=='+'){pos++;returnparseItem();}// 处理括号if(expression[pos]=='('){pos++;doubleresult=parseAdd();if(hasErr)return0.0;skipSpaces();if(expression[pos]!=')'){printf("错误: 缺少右括号\n");hasErr=1;return0.0;}pos++;returnresult;}// 处理数字(包括浮点数)if(isdigit(expression[pos])||expression[pos]=='.'){doublenum=0.0;doubledecimalBase=0.1;// 处理整数部分while(isdigit(expression[pos])){num=num*10+(expression[pos]-'0');pos++;}// 处理小数部分if(expression[pos]=='.'){pos++;while(isdigit(expression[pos])){num+=(expression[pos]-'0')*decimalBase;decimalBase*=0.1;pos++;}}returnnum;}// 处理非法字符if(expression[pos]!='\0'&&!isOperator(expression[pos])&&expression[pos]!=')'){printf("错误: 非法字符 '%c'\n",expression[pos]);hasErr=1;return0.0;}printf("错误: 表达式格式错误\n");hasErr=1;return0.0;}// 解析项(处理乘法和除法)doubleparseMultiple(){if(hasErr)return0.0;doubleresult=parseItem();while(expression[pos]=='*'||expression[pos]=='/'){charop=expression[pos];pos++;skipSpaces();doubleright=parseItem();if(hasErr)return0.0;if(op=='*'){result*=right;}else{if(fabs(right)<1e-10){// 浮点数比较printf("错误: 除零错误\n");hasErr=1;return0.0;}result/=right;}}returnresult;}// 解析表达式(处理加法和减法)doubleparseAdd(){if(hasErr)return0.0;doubleresult=parseMultiple();while(expression[pos]=='+'||expression[pos]=='-'){charop=expression[pos];pos++;skipSpaces();doubleright=parseMultiple();if(hasErr)return0.0;if(op=='+'){result+=right;}else{result-=right;}}returnresult;}// 主函数intmain(){charinput[1000];printf("递归下降表达式求值程序(支持浮点数)\n");printf("支持 +, -, *, /, (), 负数, 浮点数\n");printf("输入 'quit' 退出程序\n\n");while(1){printf("请输入表达式: ");if(!fgets(input,sizeof(input),stdin)){break;}// 去除换行符input[strcspn(input,"\n")]=0;// 检查退出命令if(strcmp(input,"quit")==0){printf("程序退出\n");break;}// 初始化全局变量expression=input;pos=0;hasErr=0;// 检查空输入skipSpaces();if(expression[pos]=='\0'){printf("错误: 空表达式\n\n");continue;}// 解析表达式doubleresult=parseAdd();// 检查是否有多余的字符skipSpaces();if(expression[pos]!='\0'&&!hasErr){printf("错误: 表达式格式错误,多余字符 '%c'\n",expression[pos]);}elseif(!hasErr){printf("结果: %.6f\n",result);}printf("\n");}return0;}
http://www.jsqmd.com/news/234527/

相关文章:

  • 上下文图谱(Context Graphs):从0到1构建AI时代的决策系统,程序员必看收藏
  • 中文实体识别新利器|AI 智能实体侦测服务镜像上线
  • Java实习模拟面试之蚂蚁金服后端校招一面:深入考察日志、并发、事务与算法
  • 万能分类器+云端GPU:个人开发者的性价比之选
  • 万能分类器多模态应用:图文分类云端一键部署,3步搞定
  • 防坑指南:购买AI分类服务前必做的5项测试
  • 术语干预+上下文理解,HY-MT1.5让翻译更智能
  • 运算表达式求值c代码(用栈实现)
  • 图像分类新选择:万能分类器实测,云端GPU比本地快5倍
  • AI智能实体侦测服务核心优势解析|高精度NER+动态彩色高亮
  • 别只看不练!30+程序员2个月转行大模型,2w+offer经验全分享,收藏这篇就够了!
  • 万能分类器图像分类实战:云端GPU 10分钟出结果,3块钱玩整天
  • 如何高效部署多语言翻译模型?HY-MT1.5镜像快速上手
  • 避坑!AI分类器环境配置:为什么99%新手会失败
  • 大学生不要一边做一边怀疑
  • 视觉代理新体验|Qwen3-VL-WEBUI助力Dify平台实现GUI操作自动化
  • AI视觉新突破:MiDaS单目深度估计实战应用与性能评测
  • 高效多语言互译新选择|基于HY-MT1.5大模型镜像实战解析
  • AI分类竞赛夺冠秘籍:弹性GPU+万能分类器调优
  • AI分类模型解释性:万能分类器决策可视化云端工具
  • GoLand 2026年1月最新版 2025.3.1 安装、授权、使用说明
  • 串口转网口通信:基于C++与Qt库的实现之旅
  • 智能高亮+极速推理|AI智能实体侦测服务赋能信息抽取场景
  • 分类模型联邦学习:万能分类器分布式训练+GPU集群
  • 为什么无线充需要Qi认证?
  • Stable Diffusion+分类器联动教程:1小时1块玩转智能标注
  • 沐曦C500适配HY-MT1.5全过程|vLLM框架下高效推理实践
  • Windows OLE零点击RCE漏洞分析:CVE-2025-21298调查实战
  • 【WRF-VPRM WRF-GHG-Prepy工具】其五 背景场处理-初始/边界条件:CAMS-Inversion数据(函数解析)
  • airplay认证流程有哪些?