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



推荐阅读
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • 本文详细探讨了HTML表单中GET和POST请求的区别,包括它们的工作原理、数据传输方式、安全性及适用场景。同时,通过实例展示了如何在Servlet中处理这两种请求。 ... [详细]
  • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
  • 本文探讨了使用C#在SQL Server和Access数据库中批量插入多条数据的性能差异。通过具体代码示例,详细分析了两种数据库的执行效率,并提供了优化建议。 ... [详细]
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 本文探讨了在使用Selenium进行自动化测试时,由于webdriver对象实例化位置不同而导致浏览器闪退的问题,并提供了详细的代码示例和解决方案。 ... [详细]
  • 本文探讨了在C++中如何有效地清空输入缓冲区,确保程序只处理最近的输入并丢弃多余的输入。我们将介绍一种不阻塞的方法,并提供一个具体的实现方案。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • 本问题探讨了在特定条件下排列儿童队伍的方法数量。题目要求计算满足条件的队伍排列总数,并使用递推算法和大数处理技术来解决这一问题。 ... [详细]
  • 深入理解Lucene搜索机制
    本文旨在帮助读者全面掌握Lucene搜索的编写步骤、核心API及其应用。通过详细解析Lucene的基本查询和查询解析器的使用方法,结合架构图和代码示例,带领读者深入了解Lucene搜索的工作流程。 ... [详细]
  • 深入解析for与foreach遍历集合时的性能差异
    本文将详细探讨for循环和foreach(迭代器)在遍历集合时的性能差异,并通过实际代码示例和源码分析,帮助读者理解这两种遍历方式的不同之处。文章内容丰富且专业,旨在为编程爱好者提供有价值的参考。 ... [详细]
  • JavaScript 基础语法指南
    本文详细介绍了 JavaScript 的基础语法,包括变量、数据类型、运算符、语句和函数等内容,旨在为初学者提供全面的入门指导。 ... [详细]
  • 本文将探讨Java编程语言中对象和类的核心概念,帮助读者更好地理解和应用面向对象编程的思想。通过实际例子和代码演示,我们将揭示如何在Java中定义、创建和使用对象。 ... [详细]
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社区 版权所有