提示:MFC实现计算器系列,后一篇均在前一篇基础上改进
前面写计算器写了4个,基本上点都差不多了,现在主要是查漏补缺。。。(主要是重整思路。。。参考microsoft计算器,找到以下问题:
1.一次输入一个数字过长问题:控制数据输入,一次数据输入只能在30个字符以内
2.删除过程中,删除最后一个字符后自动清零,而不是多按一次删除才清零:控制一下
3.表达式前置0问题 + 长按0问题:数据前面00000010,应该控制成为10,不允许前导多个无效0
4.删除过程中,删除小数点后不能写入小数点:
5.一次等号运算结束后,如果继续按符号则利用运算结果继续运算,如果按数字键则清零重开:
6.删除运算符后,又可以继续写小数点造成一个数据可以多个小数点:
7.输出控制(运算出整数,则输出结果是整数,是小数则输出小数,若位数控制在30以内全部显示,若以外则显示30位,若数据过大过小则显示位科学计数法,)---- 解决不了。。。
8.能够计算科学计数法表示的数(虽然无法输入,但是可以从计算结果中得到):主要在Tool类控制
9.代码冗余(查资料,多个宏响应同一个事件(好像是说的这句话,不重要,反正可以百度出来,多个按钮响应同一个事件)(放链接 --- MFC中,多个Button响应同一个事件))
接下来当然是解决问题了。。。。。
首先解决代码冗余问题,直接重开一个项目好吧。。。。
9.代码冗余:
做出界面,除了那个用来显示输出的Static Text按照之前的添加变量,其他的18个按钮都暂且不添加事件处理程序,(根本就是不添加。。。)(因为这次得手动添加了),,,,但是ID号还是要改的,这18个按钮ID分别标记为IDC_BUTTON1 -- IDC_BUTTON18,最好按顺序来,别怪没提醒,然后参照上面放的链接,写代码,最后在switch中写case,分别响应点击18个按钮后该做什么工作;ON_CONTROL_RANGE使用IDC_BUTTON1 -- IDC_BUTTON18这18个连续的ID号,不然为什么要你注意!然后都响应OnButtonClicked,去OnButtonClicked里面再去辨别具体是哪一个ID;
Dlg.h中加: void OnButtonClicked(UINT uId); // 函数名可变,记得和下面一起变
Dlg.cpp中加: ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON1, IDC_BUTTON18, OnButtonClicked);
void CJSQ0719Dlg::OnButtonClicked(UINT uId)
{
switch (uId) // uId就是button的资源号,就知道是哪个触发的
{
case IDC_BUTTON1:OnButtonData('1');
break; // 举个例子,OnButtonData('1');用来把字符1添加到表达式中,理解为点击了ID为IDC_BUTTON1的按钮,然后调用了函数OnButtonData('1');
}
}
-------------------- 问题解决!
8.能够计算科学计数法表示的数:主要在Tool类控制
问题简单,主要是格式固定e+或者e-,在Tool的函数中,控制一下就好了,
6.删除运算符后,又可以继续写小数点:
在删除那里控制一下,先判断删除的字符是数字还是符号,如果是符号则不能再加小数点了,修改那个用来标记能否添加小数点的标志就好了
2.删除过程中,删除最后一个字符后自动清零:
在删除哪里控制一下,当表达式字符已经删完了,就直接清零,重开就好了,
5.一次等号运算结束后,如果继续按符号则利用运算结果继续运算,如果按数字键则清零重开:
增加了一个标志,用来记录是否是重新开始运算,还是利用上次结果开始运算(只有按下等号后再次按下运算符才利用上次结果继续计算,如果按下的是数字字符,则直接清零,重开),问题解决
4.删除过程中,删除小数点后不能写入小数点:
一定程度上,这里和6出现了抵触,但是这里有一个巧妙地解决方案,删除非数字字符时,不是对标记的字段单纯的赋值true或者false,这样46总会干掉一个,这里可以取反,只需要和标记字段之前的状态相反就可以,
假设现在删掉的是运算符,那么没删之前肯定是可以加小数点的,删掉后,取反,不能加小数点;
假设现在删掉的是小数点,那么没删之前肯定不能加小数点,删掉后,取反,可以加小数点;
问题解决(解决个鬼 -- 才发现,如果是这种89*,删除一个*号之后,显然是可以加小数点的。。。。但是你设置的不能加。。。
3.表达式前置0问题 + 长按0问题:
没什么特别方案,无非是在输入0的时候做检查罢了;
// 当表达式为空时,输入0无效,不接受, #0,不接受
// 当表达式前一字符为0,且前二字符为运算符,输入0无效,不接受 #***(op)00 ,不接受
// 当表达式前一字符为0,且前二字符为运算符,输入1-9数据,进行数据更换 #***(op)0(1-9) ,更换,去掉前置0
1.一次输入一个数字过长问题:
在输入数字的时候做检查,检查当前这个数据串是否超过30,然后判断接不接受,解决
再就是把一些重复代码写成函数了,至此算是告一段落了,还剩下两个问题:
1.数据输出:计算出什么格式数据就输出 什么格式数据,(PS:我连如何判断double的小数位位数都没做到。。。。。。
2.第四点删除中的那个问题,应该还是可以解决的 ,太懒了。。。。。

2022-08-11:第四点好像是我的锅,因为这样删除太恶心了,去Microsoft试了一下,它根本就不支持删除运算符,它只能删除数字。。。。。。就是在删除过程,不允许删除运算符,那显然4中提到的问题根本不存在。。。。那。。问题解决!
此外它那个设计不错,分两行,一行存已经输入不允许改动的表达式,一行用来输入数据(我将其称之为 ,数据行,和 表达式行,),键入一个运算符的时候才把数据行和这个输入的运算符一起加入到表达式中,好处:这相当大的程度上简化了之前我们控制运算符输入、控制除号后数据非零等操作,然后删除的时候也就只能删除这个数据行的内容;同时,当它键入一个运算符的时候都会计算一下当前表达式的值,然后显示在数据行之中,这也是值得实现的功能,然后当再次输入数据时,这个当前表达式的计算结果就消失了,把数据行给数据输入用。确实不错,这个设计模式,人与人之间还是有差别的。。。。

这里是完整代码肯定会给链接的,有机会来处理结束了。。。(完整代码无了,电脑重置)
2022-11-23:关于一直没有解决的数据输出问题,理想情况是如果小数位数有限,就全部输出,否则以科学计数法输出;目标:(假设小数位7位)小数位数长过7位用科学计数法,小于7位全部输出;一种解决思路:直接利用%g转成字符串,判断字符串长度,然后再根据位数判定使用哪一种输出格式;(未模拟,仅听到的解决方案,感觉不错)
关于这里出现的很多问题:比如第九点多个宏响应同一个事件,这些都是对MFC中的宏很陌生,不知其用途,如果看完了侯捷的深入浅出MFC会好很多。
2022-08-10(0719。。。。)
浙公网安备 33010602011771号