热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

算术表达式分析与解析技术初探

本文初步探讨了算术表达式的分析与解析技术,针对作者在职业转型过程中发现自身算法基础薄弱的问题,决定在接下来的三个月内,系统地学习和掌握常用数据结构与算法,以提升个人技术能力。研究内容不仅涵盖了基本的算术表达式解析方法,还深入讨论了其在实际应用中的优化策略,为相关领域的进一步研究奠定了基础。

  首先说明我算法不好,跳槽的时候发现自己的基础薄弱而且不成体系,所以这段时间(大约3个月)我将用全部可以利用的时间把常用的数据结构、算法、C++对象模型、STL、泛型编程、设计模式整理一遍,然后梳理一下思路,做到对C++基础知识体系“巨细匪遗,秩序井然”。这个目标并没有看上去那么难,可以一试。首先要攻克的是常用的数据结构和算法,这样可以结合STL容器和算法一起学习。等整理完成后就列一个表,现在暂时没有详细的计划,先列一个粗略的计划:

  

/* 基本结构:顺序表、链表、栈、队列、哈希表、平衡二叉树、红黑树、哈夫曼树、堆、B-树、结构应用:动态数组、循环队列、内存池、基本算法:二分查找、快排、基数排序、堆排序、归并排序、希尔排序、算法思想:回溯法、贪心法、分治法、动态规划、随机算法算法应用:算术表达式解析、迷宫寻路、N皇后、综合应用:脚本解释器(脚本与宿主程序交互、分支语句解析、循环语句解析、函数调用)、内存数据库(哈希索引、键值映射、增删改查、排序)*/

 

  上面这些就够忙的了,如果有好的思想则继续补充。

  用vim写了一上午,搞定了一个公式计算器,使用一个操作栈和一个数据栈,思路如下:

/* 1.格式化:对输入格式化处理为无空格字符串2.有效性检查:每个字符的合法性、括号匹配、运算符前后必须有操作数3.入栈扫描:字符为数字则视为有符号浮点数连续读入,然后push到数字栈;字符为操作符则判断上一个操作符的优先级,决定出栈计算或push到操作栈;4.出栈计算:操作符出栈直到遇到 ( 或栈空,操作数出栈计算,结果push回栈5.重复3、4直到表达式结束 */

 

下面是C++代码:

1 #include
2 #include<string.h>
3 #include
4 #include
5 #include
6 #include
7 using namespace std;
8
9 stack<double> nust;
10 stack<char> chst;
11 void trimspace(char*& exp)
12 {
13 if(exp&#61;&#61;NULL)return;
14 while(isblank(*exp)) exp&#43;&#43;;
15 char* p&#61;exp&#43;strlen(exp)-1;
16 while(isblank(*p))p--;
17 *(p&#43;1)&#61;&#39;\0&#39;;
18 }
19
20 bool checkvalid(char* exp)
21 {
22 char validchar[]&#61;{
23 &#39;(&#39;,&#39;)&#39;,&#39;&#43;&#39;,&#39;-&#39;,&#39;*&#39;,&#39;/&#39;,&#39;%&#39;,&#39;^&#39;,&#39;.&#39;
24 };
25 int unmatch&#61;0;
26 while(*exp!&#61;&#39;\0&#39;)
27 {
28 bool valid&#61;false;
29 for(unsigned int i&#61;0;i<sizeof(validchar);&#43;&#43;i)
30 {
31 if(*exp&#61;&#61;validchar[i])
32 {
33 valid&#61;true;
34 if(*exp&#61;&#61;&#39;(&#39;)
35 unmatch&#43;&#43;;
36 else if(*exp&#61;&#61;&#39;)&#39;)
37 unmatch--;
38 else if(!isdigit(*(exp&#43;1))&&&#39;(&#39;!&#61;*(exp&#43;1))
39 {
40 cout<<"[8]error expression: "<<*exp<<" needs option number"<<endl;
41 return false;
42 }
43 break;
44 }
45 }
46 if(!valid && !isdigit(*exp)){
47 return false;
48 }
49 exp&#43;&#43;;
50 }
51 if(unmatch!&#61;0)
52 {
53 cout<<"find unmatched ()"<<endl;
54 return false;
55 }
56 return true;
57 }
58
59 bool readfloat(char* p,int *diglen)
60 {
61 *diglen&#61;0;
62 if(p&#61;&#61;NULL)return false;
63 char num[32]&#61;{0};
64 int cnt&#61;0;
65 int dot&#61;0;
66 if(*p&#61;&#61;&#39;-&#39;){
67 p&#43;&#43;;
68 if(p&&!isdigit(*p)){
69 cout<<"[5]error expression"<<endl;
70 return false;
71 }
72 num[cnt&#43;&#43;]&#61;&#39;-&#39;;
73 }
74 while(*p!&#61;&#39;\0&#39;)
75 {
76 if(isdigit(*p))
77 num[cnt&#43;&#43;]&#61;*p;
78 else if(*p&#61;&#61;&#39;.&#39;)
79 {
80 dot&#43;&#43;;
81 if(dot>1){
82 cout<<"[6]error expression"<<endl;
83 return false;
84 }
85 num[cnt&#43;&#43;]&#61;&#39;.&#39;;
86 }
87 else
88 {
89 break;
90 }
91 p&#43;&#43;;
92 }
93 *diglen&#61;cnt;
94 double dval &#61; atof(num);
95 nust.push(dval);
96 cout<<"push "<endl;
97 return true;
98 }
99
100 /*
101 * ( has 0 priority
102 * &#43; - have 1 priority
103 * * / have 2 priority
104 * % ^ have 3 priority
105 *
106 */
107
108 int getlastpriority()
109 {
110 if(chst.empty())return 0;
111 char op&#61;chst.top();
112 switch(op)
113 {
114 case &#39;(&#39;:
115 return 0;
116 case &#39;&#43;&#39;:
117 case &#39;-&#39;:
118 return 1;
119 case &#39;*&#39;:
120 case &#39;/&#39;:
121 case &#39;%&#39;:
122 return 2;
123 case &#39;^&#39;:
124 return 3;
125 default:
126 return 0;
127 }
128 }
129
130 bool calc()
131 {
132 while(!chst.empty())
133 {
134 char op&#61;chst.top();
135 chst.pop();
136 if(op&#61;&#61;&#39;(&#39;) break;
137 if(nust.size()<2)
138 {
139 cout<<"[2]expression error number stack size&#61;"<endl;
140 return false;
141 }
142 double r&#61;nust.top();
143 nust.pop();
144 double l&#61;nust.top();
145 nust.pop();
146 switch(op)
147 {
148 case &#39;&#43;&#39;:
149 cout<<"push "<endl;
150 nust.push(l&#43;r); break;
151 case &#39;-&#39;:
152 cout<<"push "<endl;
153 nust.push(l-r); break;
154 case &#39;*&#39;:
155 cout<<"push "<endl;
156 nust.push(l*r); break;
157 case &#39;/&#39;:
158 cout<<"push "<endl;
159 nust.push(l/r); break;
160 case &#39;%&#39;:
161 cout<<"push "<<(int)l%(int)r<<endl;
162 nust.push((int)l%(int)r); break;
163 case &#39;^&#39;:
164 cout<<"push "<endl;
165 nust.push(pow(l,r)); break;
166 default:
167 break;
168 }
169 }
170 return true;
171 }
172
173
174 /*push option when last option&#39;s priority less than the current one*/
175 bool scan(char* exp)
176 {
177 int length&#61;strlen(exp);
178 for(int i&#61;0;ii)
179 {
180 if(isdigit(exp[i])){
181 int len;
182 bool ret&#61;readfloat(exp&#43;i,&len);
183 if(!ret){
184 return false;
185 }
186 i&#43;&#61;len;
187 }
188 if(i>&#61;length)
189 break;
190 switch(exp[i])
191 {
192 case &#39;(&#39;:
193 chst.push(&#39;(&#39;);
194 break;
195 case &#39;)&#39;:
196 calc();
197 break;
198 case &#39;&#43;&#39;:
199 if(getlastpriority()>&#61;1)
200 {
201 calc();
202 }
203 chst.push(&#39;&#43;&#39;);
204 cout<<"push &#43;"<<endl;
205 break;
206 case &#39;-&#39;:
207 if(i&#61;&#61;0||exp[i-1]&#61;&#61;&#39;(&#39;)
208 {
209 if(exp[i&#43;1]&#61;&#61;&#39;(&#39;){
210 nust.push(0);
211 chst.push(&#39;-&#39;);
212 cout<<"push 0"<<endl;
213 cout<<"push -"<<endl;
214 break;
215 }
216 int diglen;
217 bool ret&#61;readfloat(exp&#43;i,&diglen);
218 if(!ret){
219 cout<<"read float falied line:"<<__LINE__<<endl;
220 return false;
221 }
222 i&#43;&#61;diglen-1;
223 break;
224 }else{
225 if(getlastpriority()>&#61;1)
226 calc();
227 chst.push(&#39;-&#39;);
228 cout<<"push -"<<endl;
229 break;
230 }
231 case &#39;*&#39;:
232 if(getlastpriority()>&#61;2)
233 calc();
234 chst.push(&#39;*&#39;);
235 cout<<"push *"<<endl;
236 break;
237 case &#39;/&#39;:
238 if(getlastpriority()>&#61;2)
239 calc();
240 chst.push(&#39;/&#39;);
241 cout<<"push /"<<endl;
242 break;
243 case &#39;%&#39;:
244 if(getlastpriority()>&#61;2)
245 {
246 }else
247 calc();
248 chst.push(&#39;%&#39;);
249 cout<<"push %"<<endl;
250 break;
251 case &#39;^&#39;:
252 if(getlastpriority()>&#61;3)
253 calc();
254 chst.push(&#39;^&#39;);
255 cout<<"push ^"<<endl;
256 break;
257 default:
258 cout<<"[1]error expression"<<endl;
259 break;
260 }
261 }
262 return true;
263 }
264 int main(int argc,char* argv[])
265 {
266 if(argc!&#61;2){
267 cout<<"usage:calc express"<<endl;
268 }
269 char* exp&#61;argv[1];
270 trimspace(exp);
271 bool suc&#61;false;
272 suc&#61;checkvalid(exp);
273 if(!suc)return 1;
274 suc&#61;scan(exp);
275 if(!suc){
276 cout<<"scan failed"<<endl;
277 return 1;
278 }
279 suc&#61;calc();
280 if(!suc){
281 cout<<"calc failed"<<endl;
282 return 1;
283 }
284 if(nust.size()!&#61;1)
285 {
286 cout<<"[3]error expression number stack size&#61;"<endl;
287 return 1;
288 }
289 double rst&#61;nust.top();
290 nust.pop();
291 cout<endl;
292 return 0;
293 }

View Code

  后来看了一下数据结构里的方法&#xff0c;先把中缀表达式转成后缀表达式&#xff0c;然后遍历表达式&#xff0c;将数字入栈&#xff0c;直接运算即可。省去了操作栈&#xff0c;需要一个辅助数组保存操作符&#xff0c;看上去数字需要用一个占位符代替。不过时间复杂度上是一样的。

 

转:https://www.cnblogs.com/jwk000/archive/2013/05/30/3108793.html



推荐阅读
  • Oracle程序包基础入门:了解核心概念与基本结构
    本文旨在为初学者介绍 Oracle 程序包的基础知识,涵盖其核心概念和基本结构。通过详细解析程序包的组成元素,如过程、函数和变量,帮助读者理解如何在实际应用中有效使用 Oracle 程序包。此外,文章还提供了实例代码,以便读者更好地掌握这些关键概念。 ... [详细]
  • 内网渗透技术详解:PTH、PTT与PTK在域控环境中的应用及猫盘内网穿透配置
    本文深入探讨了内网渗透技术,特别是PTH、PTT与PTK在域控环境中的应用,并详细介绍了猫盘内网穿透的配置方法。通过这些技术,安全研究人员可以更有效地进行内网渗透测试,解决常见的渗透测试难题。此外,文章还提供了实用的配置示例和操作步骤,帮助读者更好地理解和应用这些技术。 ... [详细]
  • Nginx入门指南:从零开始掌握基础配置与优化技巧
    Nginx入门指南:从零开始掌握基础配置与优化技巧 ... [详细]
  • 前言: 网上搭建k8s的文章很多,但很多都无法按其说明在阿里云ecs服务器成功搭建,所以我就花了些时间基于自己成功搭建k8s的步骤写了个操作手册,希望对想搭建k8s环境的盆友有所帮 ... [详细]
  • 在JSP页面中调用客户端本地应用程序(例如 `C:\netterm.exe`)时,可以通过使用 `Runtime.getRuntime().exec("c:\\netterm.exe")` 实现。然而,这种方法仅在服务器端有效,若要实现在客户端执行本地程序,需要采用其他技术手段,如Java Applet或ActiveX控件,以确保安全性和兼容性。 ... [详细]
  • 本文旨在构建一个JavaScript函数,用于对用户输入的电子邮件地址和密码进行有效性验证。该函数将确保输入符合标准格式,并检查密码强度,以提升用户账户的安全性。通过集成正则表达式和条件判断语句,该方法能够有效防止常见的输入错误,同时提供即时反馈,改善用户体验。 ... [详细]
  • 适用于 SSR/WASM 的 ZXing Blazor 扫码组件,高效集成与优化
    本项目基于 ZXing 封装了适用于 SSR 和 WASM 的 Blazor 扫码组件,能够高效地集成到 Blazor 应用中,并支持通过手机或桌面电脑的摄像头进行扫码操作。该组件库不仅简化了开发流程,还提供了高性能的扫码体验。项目地址:[链接] ... [详细]
  • Spring 中获取 Request 的多种方式及其线程安全性的深入解析
    本文深入探讨了在Spring MVC框架下获取HTTP请求对象的多种方法,详细分析了每种方法的实现原理及其线程安全性,为开发者提供了全面的技术参考。 ... [详细]
  • AngularJS uirouter模块下的状态管理机制深入解析
    本文深入探讨了 AngularJS 中 ui-router 模块的状态管理机制。通过详细分析状态配置、状态转换和嵌套状态等核心概念,结合实际案例,帮助开发者更好地理解和应用这一强大工具,提升单页面应用的开发效率和用户体验。 ... [详细]
  • Python初学者入门指南:从基础到实践的全面学习路径本文为Python初学者提供了一条从基础到实践的全面学习路径。特别介绍了Python字典(Dictionary)中的`items()`方法,该方法用于返回字典中所有键值对的视图对象,便于在循环和其他操作中使用。通过实例讲解,帮助读者更好地理解和应用这一重要功能。 ... [详细]
  • 在 Asp.net 应用中,动态加载 DropDownList 控件的数据源是一项常见需求。本文探讨了如何高效地从数据库中获取数据,并实时更新下拉列表,确保用户界面始终与后台数据保持同步。通过使用 ADO.NET 和 LINQ to SQL 技术,开发者可以轻松实现这一功能,同时提高应用的性能和用户体验。文中还提供了代码示例和最佳实践,帮助开发者解决常见的数据绑定问题。 ... [详细]
  • 本文介绍了如何利用摄像头捕捉图像,并将捕获的图像数据保存为文件。通过详细的代码示例,展示了摄像头调用的具体实现方法,适用于多种应用场景,如安全监控、图像处理等。 ... [详细]
  • 【高效构建全面的iOS直播应用】(美颜功能深度解析)
    本文深入探讨了如何高效构建全面的iOS直播应用,特别聚焦于美颜功能的技术实现。通过详细解析美颜算法和优化策略,帮助开发者快速掌握关键技术和实现方法,提升用户体验。适合对直播应用开发感兴趣的开发者阅读。 ... [详细]
  • OpenCV 2.4.9 源码解析:级联分类器的错误率与尺寸分析 ... [详细]
  • 在 CentOS 7 上部署和配置 RabbitMQ 消息队列系统时,首先需要安装 Erlang,因为 RabbitMQ 是基于 Erlang 语言开发的。具体步骤包括:安装必要的依赖项,下载 Erlang 源码包(可能需要一些时间,请耐心等待),解压源码包,解决可能出现的错误,验证安装是否成功,并将 Erlang 添加到环境变量中。接下来,下载 RabbitMQ 的 tar.xz 压缩包,并进行解压和安装。确保每一步都按顺序执行,以保证系统的稳定性和可靠性。 ... [详细]
author-avatar
L宝树
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有