热门标签 | 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



推荐阅读
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 本文介绍了在Linux环境下如何有效返回命令行状态、上一级目录及快速查找头文件和函数定义的方法。包括处理长时间运行命令、编辑器退出技巧、目录导航以及文件搜索策略。 ... [详细]
  • 1#include2#defineM1000103#defineRGregister4#defineinf0x3f3f3f3f5usingnamespacestd;6boolrev ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • 深入理解Flink的水印机制
    本文详细探讨了Apache Flink框架中的水印机制,这是一种用于处理数据流中时间不一致问题的重要工具。通过介绍水印的工作原理及其在实际应用中的实现方式,帮助读者更好地理解和利用这一功能。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文介绍如何手动实现一个字符串连接函数,该函数不依赖于C语言的标准字符串处理函数,如strcpy或strcat。函数原型为void concatenate(char *dest, char *src),其主要作用是将源字符串src追加到目标字符串dest的末尾。 ... [详细]
  • 本题要求计算一组正整数的最小公倍数(LCM)。输入包括多组测试数据,每组数据首先给出一个正整数n,随后是n个正整数。 ... [详细]
  • Logging all MySQL queries into the Slow Log
    MySQLoptionallylogsslowqueriesintotheSlowQueryLog–orjustSlowLog,asfriendscallit.However,Thereareseveralreasonstologallqueries.Thislistisnotexhaustive:Belowyoucanfindthevariablestochange,astheyshouldbewritteninth ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 使用QT构建基础串口辅助工具
    本文详细介绍了如何利用QT框架创建一个简易的串口助手应用程序,包括项目的建立、界面设计与编程实现、运行测试以及最终的应用程序打包。 ... [详细]
  • PHP面试题精选及答案解析
    本文精选了新浪PHP笔试题及最新的PHP面试题,并提供了详细的答案解析,帮助求职者更好地准备PHP相关的面试。 ... [详细]
  • 如何处理PHP缺少扩展的问题
    本文将详细介绍如何解决PHP环境中缺少扩展的问题,包括检查当前环境、修改配置文件以及验证修改是否生效的具体步骤,帮助开发者更好地管理和使用PHP扩展。 ... [详细]
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社区 版权所有