基于微信小程序的表达式计算器的设计与实现

2022-07-08 07:19赵素萍
电子技术与软件工程 2022年2期
关键词:运算符字符串数组

赵素萍

(晋中信息学院 山西省晋中市 030800)

本项目将字符串分割为数和运算符两个数组,从运算符的第一个数组元素开始,先进行乘除的运算,即从左到右,将所有的乘除运算计算完,再进行第二次循环,计算所有的加减。本文从此观点出发,设计并实现了计算器的表达式求值。不使用栈而是直接将对字符串进行操作,可实现表达式的实时计算。通过实验发现,该方法能大大提高计算的执行效率。

1 页面布局

本项目采用的是flex布局。Flex(Flexible Box)为”弹性布局”,用来为盒状模型内容的容器成员项提供最大的灵活性。具体使用方法为将容器的显示方式设置为flex,为容器成员分配其占比即可。

页面样式中较难的为flex布局,但只要掌握了基础知识,即找到对应的容器和项目,并为容器设置显示方式和显示方向;为项目设置各自的所占比例即可,写代码就会变的很容易。为了更好的理解代码,程序员必须充分了解并熟练掌握调试器的使用,最终运行时调试器中显示的wxml结构如图1所示。

根据图1可以看出,小程序进行渲染时,结构文件中的所有内容都会被包含到这样一对组件中,所有在该项目中,可以将page视为容器,显示屏与按钮为其成员,可灵活分配占比,本项目中采用的2:3。Page的样式设置为flex布局方式,flex方向设置为纵向布局;容器成员设置为1:1即可。参考代码如下:

图1:计算器结构

page{display:flex;flex-direction:column;}

.num{flex:2}

.btns{flex:3}

显示区域不需要采用flex布局,只需要采用绝对定位方式将其放置到合理的位置即可。即表达式和结果的样式设置为“display:absolute;”,并通过left、right、top、bottom的属性值设置,来决定最后要放的位置即可。

需要注意的是,若使用absolute绝对定位,要求包含该组件的容器不能为静态定位方式,不然是相对于整个页面的定位,即需要将num容器的布局方式设置为相对定位,即“display:relative;”。

按钮区域也使用了flex布局,其中按钮区域是容器,另使用4个view为其容器成员,这4个view为四行按钮。每一行都占25%。参考代码如下:

.btns{display:flex;flex-direction:column;}

.row{flex:25%}

每一行的view为容器,再使用3-4个view为容器成员,该view为我们最终要使用的按钮,将其占比统一设置为25%。若一行有3个按钮,则需要有一个按钮加长,达到合并单元格的效果,实现方法为在组件内通过行内样式实现。页面样式和行内样式都为其设置了相同属性的不同属性值时,即发生冲突时,由于行内样式的优先级最高,所以删除DEL按钮通过行内样式修改了他的宽度为50%。如图1第5行代码所示。

2 数字输入

2.1 输入字符太多

如果用户需要输入的字符串表达式太长时,会导致显示屏放不下这么多的内容,此时不再支持用户字符的输入,本项目中规定若表达式的长度大于25则不再支持继续输入,直接退出。求字符串长度直接使用系统为字符串定义好的length属性即可。需要用户自己使用循环函数来统计字符串的长度,可以很大程度的节省程序员的开发时间,提高开发效率。参考代码如下:

if (str.length > 25) return

函数内遇到return就会直接退出函数体,不会再执行剩余的代码,所以如果读者想结束函数的运行时,即可使用上述代码的方式退出,即满足一定的条件时退出。条件的判断使用if关键字来实现。

2.2 无效0的替换

表达式的操作:

当前输入的数字为0,字符串的最后一位也为0,则将0替换,即再输入多个0仍为0,否则替换为其他数字,即当用户输入00001时,字符串为1。若不判断最后一位为0,则1+2变成了12。若不判断当前输入的数是否为0,则100就没办法输入,因为所有的0都会被替换。若数字为0,这时就需要判断表达式的最后一位是否也为字符0,此时不为0则不需要替换,如0.1的输入不会被替换为1,仍然为0.1。

当前数的操作:

若当前数为0则替换,否则直接加在后面即可。微信小程序中页面结构可以采用数据绑定的方式将后台的值显示在页面中,同时也可以在后台修改其值,需要注意的是,不能通过赋值方式改变页面结构中数据绑定的值,必须通过setData函数来修改,而该函数的参数为json格式的对象类型,即setData({属性名1:属性值1,属性名2:属性值2.....})。

代码如下:

其中c为表达式的最后一个字符,substr函数为字符串的截取,其参数分别是起始位置和截取子串的长度,第3行代码为截取除最后一位的字符串并加上当前输入的字符后组成新的字符串,并将新的字符串赋值为表达式。举例说明,当前表达式为“1+0”,当用户输入2时,将表达式中的1+取出并和2连接,即“1+2”。通过此方法来增强代码的强壮性。否则直接将输入的字符连接到表达式后面即可。

最后,需要注意的是,为了实现实时计算的效果,增强用户的体验效果,用户每输入一个数时进行结果的计算,并通过数据绑定的方式将结果直接显示在屏幕上,不需要专门按等于号才能知道结果。由于计算运用在多个地方,所以将表达式计算的功能封装成函数,用到的时候调用即可。

3 表达式的计算

首先先将表达式分割为数字数组和运算符数组,采用split函数来实现。通过调试发现,表达式通过split函数分割后的数组中包含有很多的空字符数组元素。数字数组中只有第一个和最后一个数组元素时空字符串,只需要将其删除即可。删除数组元素的方式是采用splice方法来实现。而运算符数组中,中间元素也有很多的空字符串元素。所以需要循环判断运算符数组元素,并将其空字符元素全部删除。

通过split分割函数和splice删除数组元素的函数,即可得到正确的数组。举例说明,假设用户输入的表达式为“5+12×3÷4”,则数字数组为{5,12,3,4},运算符数组为{“+”,“×”,“÷”}。

得到正确的数组后,首先要解决的就是按照先乘除后加减,从左到右的运算法则进行计算。所以需要循环遍历运算符数组。具体操作如下:

(1)先从左到右依次找出乘除运算符的下标。找到一个乘号或除号后,返回下标i并转入(2);遍历完运算符数组后转入(3);

(2)根据下标找出两个运算数,即下标为i和i+1的运算数数组元素,运算并将运算结果存入下标为i的运算数数组,删除下标为i的运算符和下标为i+1的运算数。转入(1)继续寻找;

(3)同样的方法,从左到右遍历运算符数组进行加减运算。当运算符数组为空,转入(4);

(4)此时运算数数组只有一个数,即最后要求的结果。通过数据绑定的方式将其显示出来即可。

为了读者更清晰的了解计算机的运算过程,特将每一次运算后的数组元素都输出到控制台中,读者可看测试小节中的图5。

图5:console控制台实时监测运算过程

4 小数点的输入

小数点的操作大概分为3种情况,1没有;2一个;3多个。其中一个小数点时又分为3种情况:1只有小数部分没有整数部分,如用户直接输入‘.1’;2只有整数部分没有小数部分,如用户输入‘1.+2’。针对各种情况都需要有相应的处理来增强软件的强壮型。

4.1 直接输入.->0.

数字为0,用户直接输入".",则数字需要变为"0.",字符串表达式则需要直接与"0."链接。举例说明当用户输入"1+.2"时,用户输完"+"后,num变为"0",输入"."时,表达式变为"1+0.",num变为"0."。表达式的最后不能为0,否则会变成"00."。

为了实现上述功能,需要取出字符串表达式中的最后一个字符,具体代码如下:

4.2 小数部分不输入1.->1.0

当用户输入1.时,表示数据部分已经输入完成,下一个输入的为运算符,所以每次在输入运算符之前都需要判断字符串的最后一位是否为小数点,若成立则先将表达式的最后加一个0再加当前输入的运算符。否则会出错,如表达式为1.+2,则Numbers数 组[‘1’,‘’,‘2’],options数组[‘.+’]。效果如图,图2为表达式和计算结果,图3为console控制台输出的数组。很显然结果是错误的。

图2:表达式与计算结果

图3:console控制台调试结果

将表达式改为1.0+2后,Numbers数组[‘1.0’,‘2’],options数组[‘+’],实现加0的具体代码如下:

4.3 同一个数输入多个点 0.1..2.3->0.123

数字中如果已经有点,则用户再加点就不被允许了,直接退出函数。需要循环遍历当前正在输入的数中是否含有小数点,使用str.indexOf('.')函数实现。若有点该函数会返回.的index索引值,即0...n-1中的一个数。若没有点则会返回-1,具体代码如下:

4.4 正常输入

直接在num变量后面与表达式的后面加点即可

有小数点的字符串分割操作需要再进行numbers数组与options数组的整合。如3.6,经过‘d’分割后,numbers数组为[3,6],options数组为[‘.’],此时需要numbers数组变为[3.6],即修改3为3.6,删除6;options数组的点这一项删除。

5 运算符的输入

若用户同时输入多个运算符,则需要将之前的运算符删除,并用新的运算符代替。举例说明,当用户同时输入1+++---***///2时,屏幕上只显示1/2,中间的运算符全部被最后一个运算符替换。目前的系统还存在一定的不足,升级方向为可以实现负数的运算,如3*-5。具体代码如下:

if (c == "+" || c == '-' || c == '÷' || c == '×')

{this.setData({express: str.substr(0, str.length - 1) + op}) }

其中c为表达式的最后一个字符。str.substr为字符串的截取,str.length为求字符串的长度。op为当前输入的运算符字符。

6 删除操作

每次删除完一个字符前,都需要判断表达式是否为空,若为空则直接实现清屏结果,若不为空则计算表达式并显示新的结果。这里主要介绍删除后不为空的情况:

删除最后一个字符后,若数字数组最后一项为空则删除,若输入2+3*4会计算出正确结果,当删除4后,数字数组为[‘2’,‘3’,‘’],运算符为[‘+’,‘×’],根据运算符的优先级,先计算‘3’ב’得0,后2+0=2,“2+3*”结果并不是5,而是2,所以需要将最后一个空字符串删除,只计算2+3即可。

if (numbers[numbers.length - 1]== '') numbers.splice(-1, 1)//删除最后一个空字符串

经过上述操作后,numbers数组与options数组的长度相等,只需要删除options数组的最后一个数组元素即可。具体代码如下:

if (numbers.length == options.length) options.splice(-1, 1)

经过上述操作后,即可完成删除操作,继续进行字符串表达式的运算。由于运算操作在用户输入运算数时也会执行,所以该项目中使用模块化编程的方法,将运算操作封装成函数,需要使用的时候直接调用即可,减少了代码的冗余性,增强了代码可读性,同时也便于后期的测试与维护。

7 测试与维护

为了增加计算器的正确性和强壮性,充分利用家人、朋友,以及微信朋友圈、抖音等通信工具广泛征集测试结果,计算器运行页面如图4所示。为了更好的观察表达式分割后的数组内容,再每次运算时,都将数组内容在控制台输出。控制台的输出效果如图5所示。

图4:计算器运行

为了让读者更好的体验该小程序的运行效果,同时针对小程序中存在的不足,也欢迎读者提出您的宝贵意见。读者可以使用微信扫一扫功能运行计算器小程序。二维码如图6所示。

图6:计算器小程序的二维码

8 结束语

由于本学期所带课程即为微信小程序的开发,所以讲到测试章节的时候,将该项目与课堂内容结合。让学生找错,并将调试的内容作为课堂内容讲解。调试的技能在编程中占了举足轻重的作用,不会调试的程序员是不存在的,几乎没有哪个软件项目是能一次性测试通过的。

在不断的测试、调试的过程中,不仅让学生掌握了测试的知识点,同时也完善了计算器软件的功能。如0的处理,小数点的处理,删除操作,清屏操作,数学运算符到计算机算术运算符的转变等。

猜你喜欢
运算符字符串数组
JAVA稀疏矩阵算法
老祖传授基本运算符
JAVA玩转数学之二维数组排序
用手机插头的思路学习布尔运算符
Excel数组公式在林业多条件求和中的应用
寻找勾股数组的历程
一种新的基于对称性的字符串相似性处理算法
依据字符串匹配的中文分词模型研究
表达式求值及符号推导
一种针对Java中字符串的内存管理方案