1、 项目概述

1.1 项目目标和主要内容

  1. 实现一个计算器软件。
  2. 能通过设计的按钮控件输入并实现算术表达式,表达式在文本框中显示,运算结果输出显示;保存和浏览历史运算记录;
  3. 能够检验算术表达式的合法性;
  4. 能够实现混合运算的求解,算术表达式中包括加、减、乘、除、括号等运算符;
  5. 要求交互界面友好,程序健壮。
    简述本项目实现的主要内容和目标,使用的开发平台,采用的主要工具。
    1.2 项目的主要功能
  6. 检验算术表达式的合法性;
  7. 能够实现混合运算的求解,算术表达式中包括加、减、乘、除、括号等运算符;
  8. 运算结果输出显示;
  9. 保存和浏览历史运算记录。

2、 项目设计
2.1 项目总体框架
设计思想:
使用QT进行图形化开发设计。UI中的控件和具体的槽函数或 Lamda表达式进行绑定。在本项目中与用户交互的按钮控件主要分为三类, 一类是触发后在可编辑文本框的末尾 添加一个字符,例如数字和操作符; 一类是触发后在可编辑文本框的末尾减少一个字符,例如Backspace键; 一类是触发后清除可编辑文本框,例如Clear键。

系统框架图:

层次逻辑图:

2.2 系统详细设计
【1】 模块划分图及描述
逻辑设计部分主要又包括两个部分:一是保证输入正确的表达式。二是计算正确的表达式。
(1)保证输入正确的表达式。这里既包括输入数字和运算符,也包括正确输入他们的关系。
其中,前者,主要是利用按钮的信号和槽,即按下一个数字,将会触发一个槽,在这个槽中输入这个数字。具体的,在本程序中为了程序的简洁化,中间又加了一个公共的信号,这样按下任意一个数字都会触发同样的信号SendNum(int num)。这个信号有一个参数,就是对应的数字值。同理,符号也是一样。
(2)、计算正确输入的表达式:本程序采用的过程是先把中序表达式转化为后续表达式,然后利用后续表达式进行计算。其中的原理网上很多,在此就不赘述了。

【2】 类关系图及描述

QCalculatorUI Class里面封装了GUI图形界面设计,QCalculatorDec Class里面封装了运算函数,将中缀表达式转换为后缀表达式,分3个函数具体来实现。
【3】 程序流程图及描述

【4】 存储结构、内存分配
后缀表达式求解,需要用到一个结果栈Res_Stack :用于存放计算的中间过程的值和最终结果。 上述内容也可以按照函数或模块划分分别设计。
2.3 关键算法分析
算法 1:QQueue Split(const QString& exp);
【1】 算法功能
分离前缀。
【2】 算法基本思想
通过遍历字符串,每扫描到数字,就把它放到队列里面。
【3】 算法空间、时间复杂度分析
时间复杂度O(n),空间复杂度O(n)。

QQueue<QString> QCalculatorDec::Split(const QString& exp)          //分离前缀
{QQueue<QString> ret;QString num="";for(int i=0;i<exp.length();i++){if( (exp[i]=='.') || ( (exp[i]>='0') && (exp[i]<='9') ))    //判断小数点和数字{num += exp[i];}else if(exp[i]== '(' || exp[i]== ')' || exp[i]== '*' || exp[i]== '/'  ){if(!num.isEmpty())              //1*1{ret.enqueue(num);        //将数字入队列num.clear();}ret.enqueue(exp[i]);}else if(exp[i]== '+' || exp[i]== '-')           // + - 需要特殊处理{if(i==0)       //表达式开头,说明是正负号{num+= exp[i];}//i>0else if(exp[i-1]=='(' || exp[i-1]=='+' || exp[i-1]=='-' || exp[i-1]=='*' || exp[i-1]=='/'){num+= exp[i];}else        //否则是加减运算符{if(!num.isEmpty()){ret.enqueue(num);        //将数字入队列num.clear();}ret.enqueue(exp[i]);}}}if(!num.isEmpty())         //遍历完成,判断是否还有数字{ret.enqueue(num);num.clear();}return ret;
}

算法 2:QCalculatorDec::Transfer(QQueue& exp)
【1】 算法功能
将中缀队列转换为后缀队列。
【2】 算法基本思想
从左向右依次读取算术表达式的元素X,分以下情况进行不同的处理: (1)如果X是操作数,直接入队 (2)如果X是运算符,再分以下情况: a)如果栈为空,直接入栈。 b)如果X==”(“,直接入栈。 c)如果X==”)“,则将栈里的元素逐个出栈,并入队到后缀表达式队列中,直到第一个配对的”(”出栈。(注:“(”和“)”都不入队) d)如果是其他操作符(+ - * /),则和栈顶元素进行比较优先级。 如果栈顶元素的优先级大于等于X,则出栈并把栈中弹出的元素入队,直到栈顶元素的优先级小于X或者栈为空。弹出完这些元素后,才将遇到的操作符压入到栈中。 (3)最后将栈中剩余的操作符全部入队。
【3】 算法空间、时间复杂度分析
时间复杂度O(n),空间复杂度O(n)。

QQueue<QString> QCalculatorDec::Transfer(QQueue<QString>& exp)     //将中缀队列转换为后缀队列
{QStack<QString> stack;QQueue<QString> ret;bool num_ok;QString symbol;while(!exp.isEmpty()){symbol = exp.dequeue();   //出队列symbol.toDouble(&num_ok);if(num_ok==true)          //数字{stack.push(symbol);}else if(symbol=="+"||symbol=="-"){while(!stack.isEmpty() &&(stack.top()!="(")){ret.enqueue(stack.pop());     //取出栈顶运算符并入队列}stack.push(symbol);}else if(symbol=="*"||symbol=="/"){while(!stack.isEmpty() && (stack.top()!="(") && (stack.top()!="+") && (stack.top()!="-")){ret.enqueue(stack.pop());     //取出栈顶运算符并入队列}stack.push(symbol);}else if(symbol == "("){stack.push(symbol);}else if(symbol ==")"){while(!stack.isEmpty() && (stack.top()!="(")){ret.enqueue(stack.pop());     //取出栈顶运算符并入队列}if(stack.top()=="(")stack.pop();}}while(!stack.isEmpty()&& (stack.top()!="("))         //遍历完成,判断栈里是否为空{ret.enqueue(stack.pop());     //取出栈顶运算符并入队列}return ret;
}

2.4 其他
在实现计算器的运算函数时,多处使用了STL中的栈和队列,极大的提高了代码的编写效率。后缀表达式求解,需要用到一个结果栈Res_Stack,用于存放计算的中间过程的值和最终结果。
输入的时候主要有一下要考虑的:

  1. 浮点数的正确输入。(如 :“0.3…2”就不合法)
  2. 左右括号要匹配。( 如:“3+)))”) 肯定有问题)
  3. 左括号前面是运算符或者左括号,后面是数字或者左括号;右括号前面是数字或者右括号,右括号后面是运算符或者右括号。(如:“((33+)、(8+2)3”等输入不正确 )
  4. 本程序每次输入运算符或者右括号时提交数字。

3、 程序运行结果分析

界面显示用户当前输入的界面,每当输入新输入的数据与该界面已经显示的数据不同时将重置显示。
参与运算的数据(即操作数)可以为整数或实数,运算符(即操作符)为+、-、、/(加、减、乘、除)等二元操作符,包括圆括号;如 :56+10-25=15,6+(5-4/2)*3=15

4、 总结
4.1 项目的难点和关键点
计算器的难点和关键点主要还是中缀表达式转换为后缀表达式和后缀表达式值的计算。然后处理括号,括号的优先级是最高,也是里面最难处理的。
事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。Qt 程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。

4.2 项目的评价
老师提出的需求基本上实现了,但是我的程序界面不够美观。因为第一次做项目,时间上还是很紧的,实现完基本功能后就马不停蹄地去进行下一个项目了。 写完这个项目之后,自己从头在总结一翻,你会发现自己真的收获了很多,以前看不懂的代码,现在在看会豁然开朗。我觉得老师说的很对,总结真的很重要,之前我没总结,只靠回想的话,我真的能记住的很少很少,我觉得这个项目过段时间在总结一次的话,就可以真正理解整个项目的实现流程,自己下次做在类似的项目就会得心应手,不会不知道怎麽下手了,几个小时的总结写完了,觉得自己写的很充实,理解的也更清楚了,以后也要经常做这样的总结,我相信自己慢慢的就会成长起来的。加油把,继续努力。

4.3 心得体会
编码是软件开发过程中最基本、最底层的技艺,然而也是最重要的技艺。任何一个领域的专家都需要花费大量的时间来进行基本技艺的锻炼,木匠需要花费大量的时间来锻炼他们对各种工具的掌握,厨师则需要练习刀工和火候。程序员也是一样的,对我们来说,语言的各种特性必须要了然于胸。而对软件的管理也需要从代码做起。
软件的开发过程就象是一部精密的机器,任何一个环节的变化,都会对其它的环节产生影响。把软件过程按照瀑布的形式进行划分是一种分解的处理思路,但同时我们还应该看到不同活动之间的相互影响。软件开发中的生命周期模型也是一个层次模型,从业务建模一直到软件实现,需要跨越数个层次,同样会出现执行不力的情况,例如,代码设计偏离需求、偏离设计的情况比比皆是。

5、 参考文献
《Qt 5.9 C++开发指南》作者:王维波
《Qt 5 开发及实例》作者:陆文周
《QtCreator快速入门》作者:霍亚飞

实验1:支持算术表达式求解的计算器相关推荐

  1. 数据结构:项目三、算术表达式求解

    一.问题描述及基本要求 [问题描述] 设计一个简单的算术表达式计算器. [基本要求]  实现标准整数类型的四则运算表达式的求值(包含括号,可多层嵌入). [测试数据] (30+2*70)/3-12*3 ...

  2. 数据结构课程设计之项目三---算术表达式求解

    目录 问题描述 基本要求 问题分析 逻辑设计 物理设计 存储结构 其他模块功能核心函数伪代码 总结 问题描述 设计一个简单的算术表达式计算器. 基本要求 实现标准非负整数类型的四则运算中缀表达式的求值 ...

  3. 算术表达式求解背景_1.8 C++算术运算符与表达式

    点击上方"C语言入门到精通",选择置顶 第一时间关注程序猿身边的故事 作者 闫小林 白天搬砖,晚上做梦.我有故事,你有酒么? 基本的算术运算符 在上一节大概介绍了算术运算符有哪些, ...

  4. 数据结构课程设计---赛事统计,校园导航,算术表达式

    文章目录 目录 项目一:计算机设计大赛赛事统计 一.内容与相关要求: 二.问题分析和任务定义: 三.数据结构的选择和概要设计; 3.1 数据结构的选择 3.2 概要设计 3.2.1 功能函数的设计 四 ...

  5. C++——算术表达式的求值(数据结构课程设计)

    数据结构课程设计--算术表达式的求值 1.实验目的 1.在课程设计中提高学生的动手能力和编程能力; 2.在课程设计中提高数据结构中理论知识(栈和二叉树等知识)的应用. 3.在课程设计中提高自己对各个方 ...

  6. html算术计算,js实现计算器 提供算术表达式求值

    //html 计算器 @import "calculator.css"; //CSS /* CSS Document */ body { /*   padding-right:40 ...

  7. 如何利用计算机求函数解析式,数据结构表达式求值(计算器)实验报告(共10篇).doc...

    数据结构表达式求值(计算器)实验报告(共10篇) 数据结构表达式求值(计算器)实验报告(共10篇) 数据结构课程设计_实验报告(一)表达式求值(计算器) 数据结构课程设计 实验报告 起止时间:2015 ...

  8. 【数据结构】栈的应用-算术表达式求值#数据结构实验任务书

    实验题目:栈的应用-算术表达式求值 正文 实验环境: Visual C++ 2010 实验目的: 1.掌握栈的定义及实现: 2.掌握利用栈求解算术表达式的方法. 实验内容: 通过修改完善教材中的算法3 ...

  9. 字符串算术表达式求值-简单计算器实现(栈)-数据结构和算法(Java)

    1 字符串算术表达式分类 字符串算术表达式分为前缀表达式.中缀表达式和后缀表达式.其中前缀表达式又称波兰表达式,后缀表达式基于前缀表达式,又称逆波兰表达式.下面给出百度百科关于几种表达式的定义: 前缀 ...

最新文章

  1. Python学习笔记1 Python基础
  2. pyqt designer connect无响应_如何用PyQt编写桌面程序,创建并打开播放列表?
  3. 某40岁程序员找工作,因技术老旧被拒绝,竟泪洒当场!
  4. python能绘制统计图吗-使用Python绘制图表大全总结
  5. 【机器学习】最近邻算法KNN原理、流程框图、代码实现及优缺点
  6. JVM内存管理------杂谈(借此也论一论obj=null)
  7. 小便利——免密钥简单写法
  8. 使用Spring Security 3.1保护RESTful Web服务,第3部分
  9. Atitit.每周计划日程表 流程表v3
  10. java找不到数据库的表_GreenDao:no such table 找不到表的终极解决方案!
  11. nasa和linux的关系,跟美国NASA毅力号登陆火星的Linux是一个无图形的纯命令行系统...
  12. oracle安装最后一步完成了就消失了_Oracle安装过程中遇到的一些问题及解决方案...
  13. 我在南方的艳阳里大雪纷飞
  14. 吴恩达机器学习ex4 Neural Networks Learning (python)
  15. c语言_kbhit函数怎么用,kbhit再c语言中怎么用请教
  16. Apple Pencil有没有必要买?Apple Pencil平替哪款好?
  17. java equest 作用_Eclipse使用总结
  18. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1060:均值
  19. 世界上最远的距离_泰戈尔
  20. 计算机归零按键,上电复位和按键复位区别

热门文章

  1. (转载)Python 代码格式化工具 Black-Python
  2. GNSS/INS组合导航(三):GPS全球定位系统
  3. 计算机专业英语的时态特点,英语时态表的学习与整理
  4. 食物API接口免费开放-APP数据接口
  5. APP url scheme
  6. linux 内核高拍仪,高拍仪开发控件 | Dynamsoft Camera SDK
  7. 使用keil下载芯唐固件报错
  8. Flutter学习笔记之生成随机数
  9. Picasso图片下载缓存库的使用心得
  10. ArcBlock ⑩ 月报 | ABT 节点承载运行所有 ArcBlock 产品与服务