实验一 课程设计之算术计算器

本文介绍了使用Java和Swing实现的四则运算计算器,包括中缀表达式转后缀表达式的算法和计算器界面设计。计算器具备错误检查和用户友好界面,能够处理算术混合表达式。
摘要由CSDN通过智能技术生成

软件实习项目一 —— Java实现能进行四则运算的简易计算器

一、实验任务

(1)设计一个简易的计算器,使其实现对四则算数混合运算表达式求值。

(2)为调试好的简易计算器设计操作界面

二、实验准备

(1)具体编程语言:Java

(2)确定所用图形界面:Java Swing

(3)算法思想:中缀表达式转换为后缀表达式,进行单栈运算,推入算术表达式中的数,遇到算数操作符时进行运算,将其中间结果推入另一个栈中临时存储。将两次邻近的中间结果互相进行运算得出新的中间结果。以此重复循环,得出最终答案,输出在计算器的文本框里。

三、设计思路

(1)输入以及运算的实现

要实现完整计算式的输入并运算,就得用到计算后级表达式的算法,和将中缀表达式转换为后缀表达式的算法(后缀表达式队列(post Queue):用于存储逆波兰表达式,不用队列排序直接输出也可)

算法1:中缀表达式转后缀表达式
因为计算式要在计算器的文本编辑框中显示,所以计算式用字符串记录(定义为字符串)
规则:从左向右遍历中缀表达式
① 遇到数字字符,直接加入后缀表达式
② 遇到高优先级运算符,若栈为空直接入栈,若栈不为空,则将当前运算符与栈顶元素比较
比较1(栈顶元素也为高优先级运算符):栈顶元素出栈加入后缀表达式,当前运算符入栈.这样的操作使得栈中不会出现连续的高优先级运算符
比较2(栈顶元素为"(左括号):将当前元素入栈
比较3(栈顶元素为低优先级运算符):将当前元素入栈
③ 遇到“(”左括号,将左括号入栈
④ 遇到“)”右括号,将栈顶元素顺序出栈,直到栈顶元素为左括号,此时州去栈顶的左括号
⑤ 遇到低优先级运算符,若栈为空直接入栈,若栈不为空,则将当前运算符与栈顶元素比
比较1(栈顶元素也为低优先级运算符):栈顶元素出栈加入后缀表达式,当前运算符入栈。这样的操作使得栈中不会出现连续的低优先级运算符
比较2(栈顶元素为(左括号):将当前运算符入栈
比较3(栈顶元素为高优先级运算符):栈顶元素出栈加入后缀表达式,当前运算符入

算法2:计算后缀表达式
计算启缀表达式依然借助栈来实现
运算规则:遍历后缀表达式
① 遇到数字字符,直接入栈
② 遇到运算符,顺序出栈两个元素(数字),进行运算,将运算结果入栈
循环以上步骤最终栈中剩下的那个数字为最终答案

(2)用户在使用计算器进行算术表达式的输入时,计算器需要判断所输入的表达式是否符合运算规则,如遇到括号不完整、小数点重复等问题,计算器报错,提示用户输入正确的算术表达式,以帮助用户达到更好的使用体验

(3)计算器的基本功能设置完成后设计简易计算器的界面,以辅助用户完成基本的运算操作,得出结果

四、功能实现

计算器启动界面

package calculator;

public class StartMyCalculator {
   
    public static void main(String[] args) {
   
        // 启动计算器图形界面窗口
        new MyCalculator();
    }
}

计算机工作界面,并为按钮注册监听器

public class MyCalculator implements ActionListener {
   
    // 定义主窗口并命名
    private final JFrame jf = new JFrame("Simple Calculator");
    // 定义文本框
    private final JTextField jt = new JTextField("Click the button to enter the expression");
    // 定义按钮
    private JButton but_0, but_1, but_2, but_3, but_4, but_5, but_6, but_7, but_8, but_9,but_H,
            but_add, but_sub, but_mul, but_div, but_lt, but_rt, but_org, but_equ, but_C, but_Del;
    // 初始化表达式
    private String input = "";
    //建立一个数组,用于存放历史记录
    String[] History = new String[10];
    //记录按下查看历史记录按钮H的次数
    int count_H = 0;
    //记录按下等于号=的次数
    int count_equ = 0;

    MyCalculator() {
   
        // 设置各按钮的信息
        setButton();
        // 设置文本框信息
        setTextField();
        //设置主窗口信息
        setThis();
        // 添加各组件
        addBut();
    }

    // 设置按钮信息的方法
    private void setButton() {
   
        but_0 = new JButton("0");
        but_0.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_0.setMargin(new Insets(0, 0, 0, 0));
        but_1 = new JButton("1");
        but_1.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_1.setMargin(new Insets(0, 0, 0, 0));
        but_2 = new JButton("2");
        but_2.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_2.setMargin(new Insets(0, 0, 0, 0));
        but_3 = new JButton("3");
        but_3.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_3.setMargin(new Insets(0, 0, 0, 0));
        but_4 = new JButton("4");
        but_4.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_4.setMargin(new Insets(0, 0, 0, 0));
        but_5 = new JButton("5");
        but_5.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_5.setMargin(new Insets(0, 0, 0, 0));
        but_6 = new JButton("6");
        but_6.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_6.setMargin(new Insets(0, 0, 0, 0));
        but_7 = new JButton("7");
        but_7.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_7.setMargin(new Insets(0, 0, 0, 0));
        but_8 = new JButton("8");
        but_8.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_8.setMargin(new Insets(0, 0, 0, 0));
        but_9 = new JButton("9");
        but_9.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_9.setMargin(new Insets(0, 0, 0, 0));
        but_add = new JButton("+");
        but_add.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_add.setMargin(new Insets(0, 0, 0, 0));
        but_sub = new JButton("-");
        but_sub.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_sub.setMargin(new Insets(0, 0, 0, 0));
        but_mul = new JButton("*");
        but_mul.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_mul.setMargin(new Insets(0, 0, 0, 0));
        but_div = new JButton("/");
        but_div.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_div.setMargin(new Insets(0, 0, 0, 0));
        but_lt = new JButton("(");
        but_lt.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_lt.setMargin(new Insets(0, 0, 0, 0));
        but_rt = new JButton(")");
        but_rt.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_rt.setMargin(new Insets(0, 0, 0, 0));
        but_Del = new JButton("Del");
        but_Del.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_Del.setMargin(new Insets(0, 0, 0, 0));
        but_C = new JButton("C");
        but_C.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_C.setMargin(new Insets(0, 0, 0, 0));
        but_equ = new JButton("=");
        but_equ.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_equ.setMargin(new Insets(0, 0, 0, 0));
        but_org = new JButton(".");
        but_org.setFont(new Font("Miriam Fixed", Font.BOLD, 18));
        but_org.setMargin(new Insets(0, 0, 0, 0));
        but_H = new JButton("H");
        but_H.setFont(new Font("Miriam Fixed",Font.BOLD,18));
        but_H.setMargin(new Insets(0,0,0,0));
    }

    // 设置文本框信息方法
    private void setTextField() {
   
        jt.setEditable(false);
        jt.setFont(new Font("Miriam Fixed", Font.PLAIN, 18));
    }

    // 定义主窗口的方法
    private void setThis() {
   
        // 窗口大小
        jf.setSize(500, 335)
课程程设计,简易议计算器实验已经成功目录 1、引言……………………………………………………………………………………………… 2 1.1 计算器意义………………………………………………………………………………2 1.2 电子计算器的特殊键 …………………………………………………………………2 2 、单片机概述.……………………………………………………………………………………2 3 、芯片简介 ………………………………………………………………………………………3 3.1 MSC-51芯片简介…………………………………………………………………………3 4 、相关知识 ………………………………………………………………………………………6 4.1数码管显示…………………………………………………………………………………6 4.2矩阵按键 …………………………………………………………………………………6 5 、计算器硬件电路设 …………………………………………………………………………7 6 、计算器程序设计………………………………………………………………………………7 6.1存储单元分配………………………………………………………………………………7 6.2 主程序设计…………………………………………………………………………………7 6.3 数码管显示数据转换子程序CONV ……………………………………………………7 6.4 数码管动态显示子程序………………………………………………………………… 7 7 、系统硬件设计……………………………………………………………………………………7 7.1 系统总框图如下……………………………………………………………………………8 7.2 计算器硬件线路图…………………………………………………………………………8 7.3 系统工作原理 ………………………………………………………………………………9 8、汇编语言程序源代码……………………………………………………………………………10 9 、结语………………………………………………………………………………………………17 10、设计实物图……………………………………………………………………………18 摘要 近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。 本任务是个简易的两位数的四则运算,程序都是根据教材内和网络中的程序参考编写而成,在功能上还并不完善,限制也较多。本任务重在设计构思与团队合作,使得我们用专业知识、专业技能分析和解决问题全面系统的锻炼。 关键词: 单片机 计算器 范围 加减乘除 1 引言 1.1 计算器的历史 说起计算器,值得我们骄傲的是,最早的计算工具诞生在中国。中国古代最早采用的一种计算工具叫筹策,又被叫做算筹。这种算筹多用竹子制成,也有用木头,兽骨充当材料的。约二百七十枚一束,放在布袋里可随身携带。直到今天仍在使用的珠算盘,是中国古代计算工具领域中的另一项发明,明代时的珠算盘已经与现代的珠算盘几乎相同。17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的"纳皮尔算筹",英国牧师奥却德发明了圆柱型对数计算尺,这种计算尺不仅能做加减乘除、乘方、开方运算,甚至可以计算三角函数,指数函数和对数函数,这些计算工具不仅带动了计算器的发展,也为现代计算器发展奠定了良好的基础,成为现代社会应用广泛的计算工具。 1.2 电子计算器的特殊键 在使用电子计算器进行四则运算的时候,一般要用到数字键,四则运算键和清除数据键。除了这些按键,还有一些特殊键,可以使计算更加简便迅速。 2 单片机概述 单片机微型计算机是微型计算机的一个重要分支,也是颇具生命力的机种。单片机微型计算机简称单片机,特别适用于控制领域,故又称为微控制器。 通常,单片机由单块集成电路芯片构成,内部包含有计算机的基本功能部件:中央处理器、存储器和I/O接口电路等。因此,单片机只需要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。 单片机经过1、2、3、3代的发展,目前单片机正朝着高性能和多品种方向发展,它们的CPU功能在增强,内部资源在增多,引角的多功能化,以及低电压底功耗。 3 芯片简介 3.1 MSC-51芯片简介 MCS-51单片机内部结构 AT89C51是与MCS-51系列单片机兼容的典型产品,我们以这一代表性的机型进行系统的讲解。 AT89C51单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明: •中央处理器: 中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。 •数据存储器(RAM) AT89C51内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。 图1 •程序存储器(ROM): AT89C51共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。 •定时/计数器(ROM): AT89C51有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。 •并行输入输出(I/O)口: AT89C51共有4组8位I/O口(P0、 P1、P2或P3),用于对外部数据的传输。 •全双工串行口: AT89C51内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。 •中断系统: AT89C51具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。 •时钟电路: AT89C51内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但AT89C51单片机需外置振荡电容。 单片机的结构有两种类型,一种是程序存储器和数据存储器分开的形式,即哈佛(Harvard)结构,另一种是采用通用计算机广泛使用的程序存储器与数据存储器合二为一的结构,即普林斯顿(Princeton)结构。INTEL的MCS-51系列单片机采用的是哈佛结构的形式,而后续产品16位的MCS-96系列单片机则采用普林斯顿结构。 下图是MCS-51系列单片机的内部结构示意图2。 图2 MCS-51的引脚说明: MCS-51系列单片机中的8031、AT89C51及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明: MCS-51的引脚说明: MCS-51系列单片机中的8031、AT89C51及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:如图3 图3 Pin9:RESET/Vpd复位信号复用脚,当AT89C51通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位。初始化后,程序计数器PC指向0000H,P0-P3输出口全部为高电平,堆栈指针写入07H,其它专用寄存器被清“0”。RESET由高电平下降为低电平后,系统即从0000H地址开始执行程序。然而,初始复位不改变RAM(包括工作寄存器R0-R7)的状态,AT89C51的初始态。 AT89C51的复位方式可以是自动复位,也可以是手动复位,见下图4。此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。 图4 •Pin30:ALE/ 当访问外部程序器时,ALE(地址锁存)的输出用于锁存地址的低位字节。而访问内部程序存储器时,ALE端将有一个1/6时钟频率的正脉冲信号,这个信号可以用于识别单片机是否工作,也可以当作一个时钟向外输出。更有一个特点,当访问外部程序存储器,ALE会跳过一个脉冲。 如果单片机是EPROM,在编程其间, 将用于输入编程脉冲。 •Pin29: 当访问外部程序存储器时,此脚输出负脉冲选通信号,PC的16位地址数据将出现在P0和P2口上,外部程序存储器则把指令数据放到P0口上,由CPU读入并执行。 •Pin31:EA/Vpp程序存储器的内外部选通线,8051和8751单片机,内置有4kB的程序存储器,当EA为高电平并且程序地址小于4kB时,读取内部程序存储器指令数据,而超过4kB地址则读取外部指令数据。如EA为低电平,则不管地址大小,一律读取外部程序存储器指令。显然,对内部无程序存储器的8031,EA端必须接地。 在编程时,EA/Vpp脚还需加上21V的编程电压。 4 相关知识 4.1数码管显示 在本任务中用4位数码管显示当前数值的千,百,十,个,由于数码管个数多,如采用静态显示方式,则占用单片机的I/O口线太多,如果用定时器/计数器的串行移位寄存器工作方式及外接串入并出移位寄存器74LS164的方式,则电路复杂。所以,在数码管个数较多时,常采用动态显示方式。 如图1-1所示为单片机应用系统中的一种数码管动态显示电路图,4位数码管的相同段并联在一起,由一个8位I/O(P1口)输出字形码控制显示某一字形,每个数码管的公共端由另外一个I/O口(P0口)输出的字位码控制,即数码管显示的字形是由单片机I/O口输出的字形码确定,而哪个数码管点亮是由单片机I/O口输出的字位码确定的。4个数码管分时轮流循环点亮,在同一时刻只有1个数码管点亮,但由于数码管具有余辉特性及人眼具有视觉暂留特性,所以适当地选取循环扫描频率,看上去所有数码管是同时点亮的,察觉不出闪烁现象。动态显示方式所接数码管不能太多,否则会因每个数码管所分配的实际导通时间太少,使得数码管的亮度不足。在本任务中,为了简便,字形码和字位码都没由加驱动电路,在实际应用中应加驱动电路。数码管有共阴极和共阳极两种,对于共阳数码管,字形驱动输出0有效,字位驱动输出1有效;而对于共阴数码管则相反,即:字形驱动输出1有效,字位驱动输出0有效。 4.2矩阵按键 键盘是单片机系统中最常用的人机对话输入设备,用户通过键盘向单片机输入数据或指令。键盘控制程序需完成的任务有:监测是否有键按下,有键按下时,在无硬件去抖的动电路时,应用软件延时方法消除按键抖动影响;当有多个键同时按下时,只处理一个按键,不管一次按键持续多长时间,仅执行一次按键功能程序。 矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,思路:先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。但是,在程序的写法上,采用了最简单的方法,使得程序效率最高。本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。 本键盘扫描程序的优点在于:不用专门的按键延时程序,提高了CPU效率,也不用中断来扫描键盘,节省了硬件资源。另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。 本键盘扫描子程序名叫key,每次要扫描时用lcall key调用即可。 5 计算器硬件电路设计 AT89C51单片机的P2口作键盘口,其中P2.4-P2.7为键盘扫描输出线,P2.0-P2.3为键盘扫描输入线。键盘由4*4共16个按键组成,10个数字键(由0-9组成)5个运算符号(加减乘除等于)组成,1个清除键(作用相当于整体复位)。4个数码管用于显示当前数值的千,百,十,个,采用动态显示方式,P1口接4个数码管的七段,P0口分别接4个数码管的公共端,P1口输出数码管的字形码,P0口输出数码管的字位码。 6 计算器程序设计 6.1存储单元分配 30H单元:数值个位显示单元;31H单元:数值十位显示单元;32H单元:数值百位显示单元;33H单元:数值千位显示单元;23H单元:第一操作数存储单元;24H单元:第二操作数存储单元;25H单元:键值暂存单元;27H单元:清除键状态;34H-37H单元:结果数据转换暂存单元;38H-39H单元:结果高低8位暂存单元;R5单元:操作数计数单元;R4单元:操作数数值位数计数单元;R3单元:运算符号存储单元。 6.2 主程序设计 主程序进行程序中用到的一些存储单元的初始化,数值显示和4*4键盘扫描。首先,进行存储单元初始化,给数码管显示单元30H-33H赋予“0000”字形数据,将数值计数单元,存储单元,23H-25H,34H-37H,38H,39H,3AH,3BH,3CH,赋予初值零。之后,调用键盘扫描子程序,和数码管显示数据转换程序,数码管动态显示子程序。主程序不断进行键盘扫描,数码管显示数据转换子程序和动态显示子程序。 6.3 数码管显示数据转换子程序CONV 由于数值单元存放的是二进制数,而用户熟悉的是十进制数,所以应将数值单元中的二进制转换为十进制数,即BCD码。要通过数码管显示出当前数值,还必须将BCD码进一步转换为七段码,转换的最终结果数据存放于显示缓冲区30H-33H单元中,其中30H单元存放数值的个位七段码,31H单元存放数值的十位七段码,32H单元存放数值的百位七段码,33H单元存放数值的千位七段码。 6.4 数码管动态显示子程序 本任务由P1口输出字形码,P0口输出字位码。先将存放于30H单元的数值个位七段码由P1口输出,同时P0口输出使数值个位显示数码管点亮的字位码。由于采用的是共阳数码管,所以只有该位数码管对应的P0.0为1,其他位P0.1-P0.3位0,点亮延时10MS。然后P1口输出数值十位七段码,P0.1位1,数值十位数码管点亮,延时10MS。接着P1口输出数值百位七段码,P0.2为1,数值百位数码管点亮,延时10MS。最后P1口输出数值千位七段码,P0.3为1,数值千位数码管点亮,延时10MS。 7 系统硬件设计 选用设备AT89C51单片机一片,选用设备:AT89C51单片机一片,17个键盘,4位共阳极的七段数码管一个,连线若干,电容3个,电阻5个,晶振1个。 7.1 系统总框图如下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值