第6章四则运算计算器
本章介绍的项目是大家十分熟悉的计算器,通过该项目的实践,我们将学习状态图的一些基本知识、C# 中方法的概念和应用以及键盘事件的运用,同时,训练编写一个略微复杂的Windows应用程序的设计思路。
为了使读者能够循序渐进地学习此类项目的设计,我们根据难度的不同,分为三个项目分别实现,首先完成项目一:整数的四则运算计算器,然后在此基础上完善,实现项目二:实数四则运算计算器,最后添加记忆功能,完成项目三:带记功能的实数四则运算计算器。
6.1 项目一:整数四则运算计算器设计
6.1.1 工作目标
终极目标:完成一个整数四则运算的计算器,界面如图6.1所示:
图6.1 整数四则运算计算器
促成目标:
1.完成整数四则运算计算器整体设计——状态机分析;
2.完成整数四则运算模块设计——流程分析;
3.完成整数四则运算计算器的程序界面设计及属性设置;
4.完成整数四则运算器的程序编码;
5.对整数四则运算计算器进行必要的运行测试,如有错误进行调试修改。
6.1.2 工作任务
工作任务一:构建计算器的状态图;
工作任务二:设计程序模块的流程图;
工作任务三:设计界面完成窗体及控件的属性设置;
工作任务四:编写程序代码;
工作任务五:测试软件,对错误进行调试修改。
6.1.3 工作任务一:构建计算器的状态图
1、知识准备——状态图
状态图(Statechart Diagram)是描述一个实体基于事件反应的动态行为,显示了该实体如何根据当前所处的状态对不同的事件做出反应的。状态图用于显示状态机(它指定对象所在的状态序列)、使对象达到这些状态的事件和条件、以及达到这些状态时所发生的操作。状态机由状态组成,各状态由转移链接在一起。状态是对象执行某项活动或等待某个事件时的条件。转移是两个状态之间的关系,它由某个事件触发,然后执行特定的操作或评估并导致特定的结束状态。图6.2描绘了状态机的各种元素。
图6.2 状态机的各种元素
一个简单的编辑器可被视为有限的状态机,其状态为Empty(空)、Waiting for a command(等待命令)和Waiting for text(等待文本)。事件Load file(装载文件)、Insert text(插入文本)、Insert character(插入字符)和Save and quit(保存并退出)导致了状态机中的转移。下面的图6.3描绘了编辑器的状态机。
图6.3 编辑器的状态机
状态机最多地用于建立对象在其生命期内的行为模型。当对象具有依赖于状态的行为时,尤其需要使用状态机。可能具有状态机的对象包括:类、子系统、用例、接口(以声明实现该接口的对象必须满足的状态)和协议(以声明实现该协议的对象必须满足的状态)。并非所有对象都需要有状态机。如果对象的行为很简单,只是存储或检索数据,那么该对
象的行为就与状态无关,它的状态机也没有多少用处。
2、整数四则运算计算器的状态图设计
仔细分析计算器的状态变化,可以发现,计算器整体上有四个状态组成:接受第1个操作数、接受第2个操作数、输出计算机结果和出错。而接受第1或第2个操作数的状态中又包含了接受数字的状态和接受+、-、×、/、=五种运算符状态两种情况,把这些状态表达成状态图,如图6.4到6.6所示。
图6.4 整数四则运算计算器的顶层状态图
以上状态图描述了这样一个可循环的过程:首先系统进入输入第一个操作数的状态,如果此时继续输入数字,则系统保持当前状态,直到输入运算符,接收第一个操作数的状态结束,进入下一个状态——接收第二个操作数,这一状态也一直保持到输入一个运算符时结束,这时,运算符不一定是“=”号,也可以是+、-、×、/中的一个,无论是哪一个运算符,程序都先计算出结果并显示。接下去,如果用户输入+、-、×、/中的一个运算符,则把前一次运算的结果作为第一个操作数,开始下一轮计算;如果用户输入数字,则将前一次运算的结果丢弃,开始新一轮的计算。输入或运算中出现溢出或其它错误,则系统进入“ERROR”状态。以上描述的是顶层的状态图,它还需要进行一些细化,主要是在接收第一个或第二个操作数的过程中接收的是操作数中的第一个数字还是第一个以后的数字,程序的处理会有所不同,因为如果是第一个数字,直接显示就行,但如果是第一个以后的数字,则应该跟在前面的数字后面显示,所以还应该把上图中接收操作数的两个状态进一步分解。
图6.5 初始/接受第一个操作数的分解子状态图
图6.6 接受第二个操作数的分解子状态图
状态图很清楚地说明了计算器的状态以及触发状态改变的事件,结合本章学习的方法的相关知识,编写计算器程序有了一个比较清楚的思路:首先可以编写一个方法InitMembers(),对计算器的状态进行初始化,另外编写两个方法Numbers_Click()和Operators_Click():前者用来处理接收到数字时计算器所做的工作,后者用来处理接收到运算符时,程序应当做出的正确反映,而具体接到的是哪一个数字或运算符可以考虑采用按钮的单击事件,通过参数传递给上述的两个方法。
此外,通过状态图还可以分析出当输入第1个操作数时,必须判断一下输入的是一个数字还有第1个以后的数字,所以程序中需要定义一个bool类型的变量bNumBegins,其初值为true,当输入一个数字之后就将它置为false,直到计算出结果后再置为true,准备进行下一轮的计算。
这里,有一点必须特别给予说明,由于该计算器的功能是比较简单的,所以暂时不考输入操作数是负数和情况。
6.1.4工作任务二:设计程序模块的流程图
1.知识准备——方法
方法(method)又常称为函数(function),是实现可以由对象或类执行的计算或操作。一般而言,可以把一个程序中多次用到的某个任务,如常用的计算定义为方法,以便反复调用。在前面的章节中曾经应用过的MessageBox类的Show、Math的Pow都是方法,方法是类的成员。
1)实例方法和静态方法
C#的方法有实例方法和静态方法之分。所谓的实例方法是指通过对象名调用的方法,也是本章应用到的方法。静态方法与类关联,而不是与对象关联,定义静态方法时要使用static关键字,访问静态方法时要使用类名,而不是对象名。
2)方法定义的格式
实例方法定义的格式化为:
修饰符返回类型方法名(形参列表)
{
声明和语句
}
静态方法定义的格式为:
修饰符static 返回类型方法名(形参列表)
{
声明和语句
}
其中“返回类型”指定该方法返回的值的类型。如果方法无返回值,则返回类型为void;“方法名”是一个有效的标识符;“形参列表”中的“形参”是“形式参数”的简称,“形参列表”是一个可选项,指定方法的参数,如果有多个参数,可以用逗号分隔,每个参数与声明变量的方法一样,都是指定数据类型和参数名。即使没有参数,括号也不能省略。
方法返回类型如果不是 void,则方法可以使用 return 关键字来返回值,如果语句中return 关键字的后面是与返回类型匹配的值,则该语句将该值返回给方法调用方。return 关键字还会停止方法的执行。如果返回类型为 void,则可使用没有值的 return 语句来停止方法的执行。如果没有 return 关键字,方法执行到代码块末尾时即会停止。具有非 void 返回类型的方法才能使用 return 关键字返回值。
2.整数四则运算计算器的程序流程图
程序思路的大体框架基本清楚后,我们可以来构建计算器及其主要方法的流程图,以便根据流程图写出程序代码。程序总流程图如图6.7所示。
图6.7 整数计算器程序总流程图
图6.8 Numbers_Click()方法的流程图
图6.9 Operators_Click()方法的流程图
上述Operators_Click()方法的流程图在理解上会比较困难。首先我们要考虑清楚,当
新一轮计算开始时,第一次输入一个运算符(+、-、×、/中的一个),程序是不能进行计算的,因为此时只有一个操作数,只有当输入第二个操作数之后,第二次输入一个运算符(+、-、×、/或者=),才能进行四则运算,所以在Operators_Click()方法中对运算符的处理应当推迟一步,也就是说,本次输入的运算符应该保存起来(流程图中保存在cOperator中),而程序当前处理的是前一次输入的运算符,之后把运算的结果存入第一个操作数,以便开始新一轮的计算。
这里还有一个小问题,既然对运算符的处理是推迟一步进行的,那么在程序初始化的时候,应给运算符赋一个初值,作为第一个运算符的前一个运算符,那么初值应当是什么呢?试想,程序最开始时,用户输入一个操作数和一个运算符(+、-、×、/中的一个),由于此时不进行加、减、乘、除的四则计算,程序所做的工作只是保存运算符,并将输入的数放入存放第一操作数的变量中,所以初值不能是+、-、×、/中的一个,而只能是“=”。
6.1.5工作任务三:设计界面完成窗体及控件的属性设置
首先创建一个Windows应用程序,命名为Cacle1,在窗体上添加一个文本框控件和15个按钮控件,设计程序界面如图6.10所示,
图6.10 程序界面设计
窗体、控件及相关属性如表6.1所示。
表6.1 控件属性表
6.1.6工作任务四:编写程序代码
在编写代码之前我们再来考虑一个问题,我们开发的这个计算器,用鼠标点单击各按钮时,触发了按钮的Click事件,通过编写按钮的单击事件我们可以实现数字或运算符的输入,但是为了提高输入的速度,许多人喜欢使用键盘进行操作,那么我们的计算器可不可以用键盘来操作呢,答案是肯定的,但我们需要为编写增加相关的键盘事件。
1.知识准备——键盘事件
当用户按键盘键时,Windows 窗体提供两个事件,而当用户松开键盘键时,Windows 窗体提供一个事件。
1)KeyDown 事件发生一次;
2)KeyPress事件,当用户按住同一个键时,该事件可以发生多次;
3)当用户松开键时,KeyUp 事件发生一次。
我们用下表对三个事件进行说明:
表6.2 键盘事件说明
Windows 窗体将键盘输入标识为由按位 Keys 枚举表示的虚拟键代码。使用 Keys 枚举,可以综合一系列按键以生成单个值。可通过处理 KeyDown 或 KeyUp 事件来检测大多数物理按键操作。如果通过组合按键得到一个字符,则可以通过处理 KeyPress 事件来检测该字符。
Keys枚举类包含用于处理键盘输入的常数。键由键值标识,键值是由键代码和一组修饰符共同组成的一个整数值。键值的左边四个数字包含键代码(与 Windows 虚拟键代码一样)。键值的右边四个数字包含 SHIFT、CONTROL 和 ALT 键的修饰符位。这里我们举例小部分Keys成员,供大家参考,如表6.3所示:
表6.3 Keys枚举类部分成员
在本项目中,我们采用文本框的key_Down事件,接收来自数字键盘的事件,其它的键盘事件有兴趣的读者可以自己添加。
2.编写程序代码
对照以上流程分析,编写程序代码如下:
// 一个整数四则运算的计算器
using System;
using System.Drawing;
using System.Collections;
using https://www.doczj.com/doc/2b19112160.html,ponentModel;
using System.Windows.Forms;
using System.Data;
namespace Calce1
{
public class Form1 : System.Windows.Forms.Form
{
// 存储前一个操作数
protected long iNum1;
// 存储运算符
protected char cOperator;
// 是否开始输入一个新的数字
protected bool bNumBegins;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button8;
private System.Windows.Forms.Button button9;
private System.Windows.Forms.Button btnAdd;
private System.Windows.Forms.Button btnSubstract;
private System.Windows.Forms.Button btnMultiply;
private System.Windows.Forms.Button btnDivide;
private System.Windows.Forms.Button btnEquals;
protected System.Windows.Forms.TextBox txtOutput;
private System.Windows.Forms.Button button0;
private https://www.doczj.com/doc/2b19112160.html,ponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
InitMembers();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
// 初始化相关变量
private void InitMembers()
{
iNum1 = 0;
cOperator = '=';
bNumBegins = true;
}
// 当用户按下0 - 9 这10个键时的情况
private void Numbers_Click(long i)
{
if(txtOutput.Text == "Error")
{
txtOutput.Text = "0";
}
try
{
// 取得输入
long iCurrent = long.Parse(txtOutput.Text);
if(bNumBegins)
{
iCurrent = i;
bNumBegins = false;
}
else
{
// 要求检查运算溢出的情况
checked{iCurrent = (iCurrent * 10) + i;}
}
txtOutput.Text = iCurrent.ToString();
}
catch
{
// 捕捉异常不处理,这样如果用户输入的数字超过界限,
// 程序中显示的数字会保持不变
}
}
// 当用户按下5个运算符时的情况
private void Operators_Click(char op)
{
//char op = ((Button)sender).Text[0];
long iCurrent;
try
{
iCurrent = long.Parse(txtOutput.Text);
}
catch
{
txtOutput.Text = "Error";
InitMembers();
return;
}
// 计算结果
long iResult;
try
{
switch(cOperator)
{
case '+':
checked{iResult = iNum1 + iCurrent;}
break;
case '-':
checked{iResult = iNum1 - iCurrent;}
break;
case '*':
checked{iResult = iNum1 * iCurrent;}
break;
case '/':
checked{iResult = iNum1 / iCurrent;}
break;
default:
iResult = iCurrent;
break;
}
}
catch
{
// 如果在计算中发生溢出,则显示"Error"
// 并重置整个状态
txtOutput.Text = "Error";
InitMembers();
return;
}
// 输出结果,并把当前的结果保存起来txtOutput.Text = iResult.ToString();
iNum1 = iResult;
//准备接受下一个操作数
bNumBegins = true;
// 保存符号
cOperator = op;
}
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e) {
Numbers_Click(1);
}
private void button2_Click(object sender, System.EventArgs e) {
Numbers_Click(2);
}
private void button3_Click(object sender, System.EventArgs e) {
Numbers_Click(3);
}
private void button4_Click(object sender, System.EventArgs e) {
Numbers_Click(4);
}
private void button5_Click(object sender, System.EventArgs e) {
Numbers_Click(5);
}
private void button6_Click(object sender, System.EventArgs e) {
Numbers_Click(6);
}
private void button7_Click(object sender, System.EventArgs e)
{
Numbers_Click(7);
}
private void button8_Click(object sender, System.EventArgs e)
{
Numbers_Click(8);
}
private void button9_Click(object sender, System.EventArgs e)
{
Numbers_Click(9);
}
private void button0_Click(object sender, System.EventArgs e)
{
Numbers_Click(0);
}
private void btnAdd_Click(object sender, System.EventArgs e)
{
Operators_Click('+');
}
private void btnSubstract_Click(object sender, System.EventArgs e)
{
Operators_Click('-');
}
private void btnMultiply_Click(object sender, System.EventArgs e)
{
Operators_Click('*');
}
private void btnDivide_Click(object sender, System.EventArgs e)
{
Operators_Click('/');
}
private void btnEquals_Click(object sender, System.EventArgs e)
{
Operators_Click('=');
}
//添加键盘事件代码,实现数字键盘的操作
private void txtOutput_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) {
目录 第一章引言 (3) 1.1 简述简易计算器 (3) 1.2 本设计主要任务 (3) 1.3 系统主要功能 (4) 第二章系统主要硬件电路设计 (4) 2.1 系统的硬件构成及功能 (4) 2.2 键盘电路设计 (5) 2.3 显示电路设计 (6) 第三章系统软件设计 (7) 3.1 计算器的软件规划 (7) 3.2 键盘扫描的程序设计 (7) 3.3 显示模块的程序设计 (8) 3.4 主程序的设计 (9) 3.5 软件的可靠性设计 (9) 第四章调试 (9) 第五章结束语 (10) 参考文献 (11) 附录源程序 (11)
第一章引言 1.1 简述简易计算器 近几年单片机技术的发展很快,其中电子产品的更新速度迅猛。计算器是日常生活中比较的常见的电子产品之一。如何才能使计算器技术更加的成熟,充分利用已有的软件和硬件条件,设计出更出色的计算器呢? 本设计是以AT89S52单片机为核心的计算器模拟系统设计,输入采用4×6矩阵键盘,可以进行加、减、乘、除9位带符号数字运算,并在LCD1602上显示操作过程。 科技的进步告别了以前复杂的模拟电路,一块几厘米平方的单片机可以省去很多繁琐的电路。现在应用较广泛的是科学计算器,与我们日常所用的简单计算器有较大差别,除了能进行加减乘除,科学计算器还可以进行正数的四则运算和乘方、开方运算,具有指数、对数、三角函数、反三角函数及存储等计算功能。计算器的未来是小型化和轻便化,现在市面上出现的使用太阳能电池的计算器, 使用ASIC设计的计算器,如使用纯软件实现的计算器等,未来的智能化计算器将是我们的发展方向,更希望成为应用广泛的计算工具。 1.2 本设计主要任务 以下是初步设定的矩阵键盘简易计算器的功能: 1.扩展4*6键盘,其中10个数字,5个功能键,1个清零 2.强化对于电路的焊接 3.使用五位数码管接口电路 4. 完成十进制的四则运算(加、减、乘、除); 5. 实现结果低于五位的连续运算; 6. 使用keil 软件编写程序,使用汇编语言; 7. 最后用ptoteus模拟仿真; 8.学会对电路的调试
简单的四则运算计算器程序
注:1、报告内的项目或内容设置,可根据实际情况加以调整和补充。 2、教师批改学生实验报告时间应在学生提交实验报告时间后10日内。
附件:程序源代码 // sizheyunsuan.cpp : Defines the entry point for the console application. #include
吉首大学课程设计 课程设计名称:简单的计算器 专业班级: 10 网络工程 学生姓名:胡申城唐茂林赖佳 学号:20104045049 20104045006 201040450 指导教师:鲁荣波老师 课程序设计时间:2011.12.18-2011.12.25
目录 一内容 (1) 二.设计要求 (2) 三.计算器的算法 (2) 四..流程图 (5) 五.源程序 (7) 六.执行结果 (8) 七.课程设计总结 (3) 八.参考书目 (3)
一、内容 编写一个功能基本完善的计算器程序,支持四则运算、乘方开方、指数对数等运算,支持带括号的表达式。 二、设计要求 1) 程序采用字符界面 2) 显示功能菜单,用户指定键即可进入相应功能 3) 每次计算完成后输出一个提示符,要计算的数字或表达式由用户在提示后面输入 4) 用户输入完按回车立即显示计算结果 三、计算器的算法 我们现在用的计算器多是一个数一个运算符的输入输出的。一个比较具有现实意义的计算器,应该具有如下功能: 1.能够实现整数的四则运算:如:1+6-9*4+4/3 2.能够实现小数的四则运算:如:0.2+7-4 这样的计算器基本可以使用在我们生活中。如果我们按照栈的使用来描述一下表达式的进栈出栈问题: 表达式例如:1+9*4/4-5。 假设有栈D和数组S;S中放运算数,D栈放入运算符,优先级高的现运算,四则运算中,*和/优先级最高。 第一步:扫描到‘1’,是运算数,放入S; 第二步:扫描到‘+‘进入D
第三步:扫描到9;进S 第四步:扫描‘*’,因为乘比加优先级高,所以9出栈实现:9*4,把结果入S, 第五步:扫描到/,同样计算S的栈顶元素出栈,实现36/4,把结果如S 第六步:扫描到—,进入D栈; 第七步:扫描到‘5’,进S 第八步:扫描到‘\0’,为结束符;把S栈顶元素栈S1,D顶元素出栈,然后S栈顶元素在出栈,实现减操作,接着S栈顶元素出栈,实现加操作。 具体进出栈如图: Next 为下一个字符或数字,run表示运行,空为不操作S[] D S[] D S[] D S[] D S[] D S[] top t top 9 top 36 top 4 - -1 top base 1 + 1 + 1 + 1 + 1 + 0 top top next + 9 * 4 / 4 - 5 = run 9*4 36/4 4-5 -1+1 表1-1 运算数运算符进栈、出栈
DBUF EQU 30H TEMP EQU 40H YJ EQU 50H ;结果存放 YJ1 EQU 51H ;中间结果存放GONG EQU 52H ;功能键存放 ORG 00H START: MOV R3,#0 ;初始化显示为空MOV GONG,#0 MOV 30H,#10H MOV 31H,#10H MOV 32H,#10H MOV 33H,#10H MOV 34H,#10H MLOOP: CALL DISP ;PAN调显示子程序WAIT: CALL TESTKEY ; 判断有无按键JZ WAIT CALL GETKEY ;读键 INC R3 ;按键个数 CJNE A,#0,NEXT1 ; 判断就是否数字键 LJMP E1 ; 转数字键处理NEXT1: CJNE A,#1,NEXT2 LJMP E1 NEXT2: CJNE A,#2,NEXT3 LJMP E1 NEXT3: CJNE A,#3,NEXT4 LJMP E1 NEXT4: CJNE A,#4,NEXT5 LJMP E1 NEXT5: CJNE A,#5,NEXT6 LJMP E1 NEXT6: CJNE A,#6,NEXT7 LJMP E1 NEXT7: CJNE A,#7,NEXT8 LJMP E1 NEXT8: CJNE A,#8,NEXT9 LJMP E1 NEXT9: CJNE A,#9,NEXT10 LJMP E1 NEXT10: CJNE A,#10,NEXT11 ;判断就是否功能键LJMP E2 ;转功能键处理NEXT11: CJNE A,#11,NEXT12 LJMP E2 NEXT12: CJNE A,#12, NEXT13 LJMP E2
基于单片机实现的四则运算计算器 姓名 学号: 班级: 专业名称:测控技术与仪器 指导教师: 东北大学 2016年1月
课程设计(论文)任务书课程设计(论文)题目:基于单片机实现的四则运算计算器 基本内容和设计要求: 1、主机的矩阵键盘输入数和运算符号,从机显示运算结果。 2、主从单片机串行通信系统,并在LCD上显示运算内容及结果。 3、计算结果超过十位数字则显示错误。 4、运算除法时,结果只取整数,不是四舍五入。 5、有清零功能。
目录 课程设计(论文)任务书................................................................................................ i i 摘要 (1) 第1章绪论 (2) 1.1计算器简介 (2) 1.2设计主要内容 (2) 第2章系统硬件设计 (4) 2.1硬件组成 (4) 2.2输入模块 (4) 2.3输出模块 (5) 2.4运算模块 (5) 第3章系统软件设计 (7) 3.1 主程序 (7) 3.1.1主程序框图及初始化 (7) 3.1.2LCD程序框图及初始化 (8) 3.1.3键盘程序框图及初始化 (9) 3.1.4运算程序框图 (10) 第4章调试测试与实验分析 (11) 4.1 计算器调试 (11) 参考文献 (12) 心得体会 (13) 附录硬件原理图及PCB图 (14) 附录程序清单 (15) 附录实物照片 (28)
摘要 单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域,电子、科技、通信、汽车、工业等。本设计是基于89C52RC单片机来进行的四则运算计算器系统设计,可以完成计算器的键盘输入,进行加、减、乘、除的基本四则运算,并在LCD1602液晶显示屏上显示相应的结果。本电路采用89C52RC单片机为主要控制电路,利用4*4矩阵键盘作为计算器以及运算符的输入。显示采用字符LCD静态显示。软件用C语言编程,并用开发板进行演示。 关键词:计算器,89C52RC单片机,LCD,矩阵键盘
HTML5+JavaScript: