本文用Javaswing来实现一个简单计算器,主要内容为图形用户界面GUI的实现以及运算表达式核心算法的设计编写。

程序运行环境为Windows10 ,编译环境为MyEclipse 。

一、具体功能:

1、:输入,输出

 输入:允许输入带有括号的完整计算式(例 8*(4-95)+5÷2*e-pi)输出:输出Double类型的结果输出:整个运算表达式并保存于历史记录中

2、:功能

 基本的加,减,乘,除,四则运算平方运算开方运算求余运算

最终界面如下图:

除了常规的数字按钮和运算符,还有两个常数e,pi(π),清空键AC,括号运算符(),平方(x^x)和开方(sqrt)运算符,输入显示框以及历史记录文本框,文本框的垂直滚动条和水平滚动条。

二、主要思想:

1:中缀表达式转为后缀表达式

准备:

①后缀表达式队列:postQueue,用于存储逆波兰表达式(其实不用队列排序直接输出也行)
②操作符栈:opStack,对用户输入的操作符进行处理,用于存储运算符

算法思想:

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

示意图:

2、计算后缀表达式

准备:

需要用到一个结果栈Res_Stack :用于存放计算的中间过程的值和最终结果

算法思想:

1、从左开始向右遍历后缀表达式的元素。
2、如果取到的元素是操作数,直接入栈Res_Stack,如果是运算符,从栈中弹出2个数进行运算,然后把运算结果入栈
3、当遍历完后缀表达式时,计算结果就保存在栈里了。

示意图:

三、结果测试

分析:

1、可实现基本四则运算及平方、开方、求余运算。
2、运算表达式可显示于输入界面并保存于历史记录栏
3、输入界面和历史记录栏皆可实现不断字自动换行功能以及滚动条功能
4、不足之处:进行平方和开方运算时其保存在历史记录中的表达式会出现两个等号及两个结果。

四、完整源代码(每行代码已附有详细注释)

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;import javax.swing.*;//Calculator类,继承JFrame框架,实现事件监听器接口
public class Calculator extends JFrame implements ActionListener {private final String[] KEYS = { "7", "8", "9", "AC", "4", "5", "6", "-", "1", "2", "3", "+", "0", "e", "pi", "/", "sqrt","%", "x*x", "*", "(", ")", ".", "=" };private JButton keys[] = new JButton[KEYS.length];private JTextArea resultText = new JTextArea("0.0");// 文本域组件TextArea可容纳多行文本;文本框内容初始值设为0.0private JTextArea History = new JTextArea();// 历史记录文本框初始值设为空private JPanel jp2=new JPanel();private JScrollPane gdt1=new JScrollPane(resultText);//给输入显示屏文本域新建一个垂直滚动滑条private JScrollPane gdt2=new JScrollPane(History);//给历史记录文本域新建一个垂直滚动滑条// private JScrollPane gdt3=new JScrollPane(History);//给历史记录文本域新建一个水平滚动滑条private JLabel label = new JLabel("历史记录");private String b = "";// 构造方法public Calculator() {super("Caculator");//“超”关键字,表示调用父类的构造函数,resultText.setBounds(20, 18, 255, 115);// 设置文本框大小resultText.setAlignmentX(RIGHT_ALIGNMENT);// 文本框内容右对齐resultText.setEditable(false);// 文本框不允许修改结果History.setBounds(290, 40, 250,370);// 设置文本框大小History.setAlignmentX(LEFT_ALIGNMENT);// 文本框内容右对齐History.setEditable(false);// 文本框不允许修改结果label.setBounds(300, 15, 100, 20);//设置标签位置及大小jp2.setBounds(290,40,250,370);//设置面板窗口位置及大小jp2.setLayout(new GridLayout());JPanel jp1 = new JPanel();jp1.setBounds(20,18,255,115);//设置面板窗口位置及大小jp1.setLayout(new GridLayout());resultText.setLineWrap(true);// 激活自动换行功能resultText.setWrapStyleWord(true);// 激活断行不断字功能resultText.setSelectedTextColor(Color.RED);History.setLineWrap(true);//自动换行History.setWrapStyleWord(true);History.setSelectedTextColor(Color.blue);gdt1.setViewportView(resultText);//使滚动条显示出来gdt2.setViewportView(History);gdt1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);//设置让垂直滚动条一直显示gdt2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);//设置让垂直滚动条一直显示gdt2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);//设置让水平滚动条一直显示jp1.add(gdt1);//将滚动条添加入面板窗口中jp2.add(gdt2);this.add(jp1);//将面板添加到总窗体中this.add(jp2);//将面板添加到总窗体中this.setLayout(null);this.add(label);// 新建“历史记录”标签//this.add(resultText);// 新建文本框,该语句会添加进去一个新的JTextArea导致带有滚动条的文本无法显示或者发生覆盖//this.add(History);// 新建历史记录文本框,该语句会添加进去一个新的JTextArea导致带有滚动条的文本无法显示// 放置按钮int x = 20, y = 150;for (int i = 0; i < KEYS.length; i++){keys[i] = new JButton();keys[i].setText(KEYS[i]);keys[i].setBounds(x, y, 60, 40);if (x < 215) {x += 65;} else {x = 20;y += 45;}this.add(keys[i]);}for (int i = 0; i < KEYS.length; i++)// 每个按钮都注册事件监听器{keys[i].addActionListener(this);}this.setResizable(false);this.setBounds(500, 200, 567, 480);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}// 事件处理public void actionPerformed(ActionEvent e){//History.setText(b);//使输入的表达式显示在历史记录文本框中String label=e.getActionCommand();//获得事件源的标签if(Objects.equals(label, "="))//{resultText.setText(this.b);History.setText(History.getText()+resultText.getText());if(label.equals("="))//调用计算方法,得出最终结果{String[] s =houzhui(this.b);String result=Result(s);this.b=result+"";//更新文本框,当前结果在字符串b中,并未删除,下一次输入接着此结果以实现连续运算resultText.setText(this.b);History.setText(History.getText()+"="+resultText.getText()+"\n");}}else if(Objects.equals(label, "AC"))//清空按钮,消除显示屏文本框前面所有的输入和结果{this.b="";resultText.setText("0");//更新文本域的显示,显示初始值;}else if(Objects.equals(label, "sqrt")){String n=kfys(this.b);resultText.setText("sqrt"+"("+this.b+")"+"="+n);//使运算表达式显示在输入界面History.setText(History.getText()+"sqrt"+"("+this.b+")"+"=");//获取输入界面的运算表达式并使其显示在历史记录文本框this.b=n;}else if(Objects.equals(label, "x*x")){String m=pfys(this.b);resultText.setText(this.b+"^2"+"="+m);//使运算表达式显示在输入界面History.setText(History.getText()+this.b+"^2"+"=");//获取输入界面的运算表达式并使其显示在历史记录文本框this.b=m;}else if(Objects.equals(label, "e") || Objects.equals(label, "pi")){if(label.equals("e")){String m=String.valueOf(2.71828);//将e的值以字符串的形式传给mthis.b=this.b+m;//保留显示m之前输入的运算符或数字字符继续下一步运算resultText.setText(this.b);// History.setText(History.getText()+this.b);}if(label.equals("pi")){String m=String.valueOf(3.14159265);this.b=this.b+m;resultText.setText(this.b);// History.setText(History.getText()+this.b);}}else{this.b=this.b+label;resultText.setText(this.b);// History.setText(History.getText()+this.b);}//History.setText(History.getText()+this.b);//使输入的表达式显示在历史记录文本框中}//将中缀表达式转换为后缀表达式private String[] houzhui(String str) {String s = "";// 用于承接多位数的字符串char[] opStack = new char[100];// 静态栈,对用户输入的操作符进行处理,用于存储运算符String[] postQueue = new String[100];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串int top = -1, j = 0;// 静态指针top,控制变量jfor (int i = 0; i < str.length(); i++)// 遍历中缀表达式// indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符;{if ("0123456789.".indexOf(str.charAt(i)) >= 0) // 遇到数字字符的情况直接入队{s = "";// 作为承接字符,每次开始时都要清空for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {s = s + str.charAt(i);//比如,中缀表达式:234+4*2,我们扫描这个字符串的时候,s的作用相当于用来存储长度为3个字符的操作数:234}i--;postQueue[j] = s;// 数字字符直接加入后缀表达式j++;}else if ("(".indexOf(str.charAt(i)) >= 0) {// 遇到左括号top++;opStack[top] = str.charAt(i);// 左括号入栈}else if (")".indexOf(str.charAt(i)) >= 0) {// 遇到右括号for (;;)// 栈顶元素循环出栈,直到遇到左括号为止{if (opStack[top] != '(') {// 栈顶元素不是左括号postQueue[j] = opStack[top] + "";// 栈顶元素出栈j++;top--;} else { // 找到栈顶元素是左括号top--;// 删除栈顶左括号break;// 循环结束}}}else if ("*%/+-".indexOf(str.charAt(i)) >= 0)// 遇到运算符{if (top == -1){// 若栈为空则直接入栈top++;opStack[top] = str.charAt(i);}else if ("*%/".indexOf(opStack[top]) >= 0){// 当栈顶元素为高优先级运算符时,让栈顶元素出栈进入后缀表达式后,当前运算符再入栈postQueue[j] = opStack[top] + "";j++;opStack[top] = str.charAt(i);}else {top++;opStack[top] = str.charAt(i);// 当前元素入栈}}}while (top != -1) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式postQueue[j] = opStack[top] + "";j++;top--;}return postQueue;}//开方运算方法public String kfys(String str) {String result = "";double a = Double.parseDouble(str), b = 0;b = Math.sqrt(a);result = String.valueOf(b);//将运算结果转换为string类型并赋给string类型的变量resultreturn result;}//平方运算方法public String pfys(String str) {String result = "";double a = Double.parseDouble(str), b = 0;b = Math.pow(a, 2);result = String.valueOf(b);return result;}// 计算后缀表达式,并返回最终结果public String Result(String[] str) {String[] Result = new String[100];// 顺序存储的栈,数据类型为字符串int Top = -1;// 静态指针Topfor (int i = 0; str[i] != null; i++) {if ("+-*%/".indexOf(str[i]) < 0) {  //遇到数字,直接入栈Top++;Result[Top] = str[i];}if ("+-*%/".indexOf(str[i]) >= 0)// 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶{double x, y, n;x = Double.parseDouble(Result[Top]);// 顺序出栈两个数字字符串,并转换为double类型Top--;y = Double.parseDouble(Result[Top]);Top--;if ("*".indexOf(str[i]) >= 0) {n = y * x;Top++;Result[Top] = String.valueOf(n);// 将运算结果重新入栈}if ("/".indexOf(str[i]) >= 0){if (x == 0)// 被除数不允许为0{String s = "error!";return s;} else {n = y / x;Top++;Result[Top] = String.valueOf(n);// 将运算结果重新入栈}}if ("%".indexOf(str[i]) >= 0){if (x == 0)// 被除数不允许为0{String s = "error!";return s;} else {n = y % x;Top++;Result[Top] = String.valueOf(n);// 将运算结果重新入栈}}if ("-".indexOf(str[i]) >= 0) {n = y - x;Top++;Result[Top] = String.valueOf(n);// 将运算结果重新入栈}if ("+".indexOf(str[i]) >= 0) {n = y + x;Top++;Result[Top] = String.valueOf(n);// 将运算结果重新入栈}}}return Result[Top];// 返回最终结果}// 主函数public static void main(String[] args) {Calculator a = new Calculator();}
}

另附:

这是最初尚未修改的源代码,贴在这里备份,方便大家随时修改找bug。

https://blog.csdn.net/weixin_50301255/article/details/121889662

欢迎大家批评指正,分享问题解决方案。

Java编写简单计算器--实现篇相关推荐

  1. java编写简单计算器_编写java程序简单计算器

    展开全部 主要涉及的知识点: 类的e69da5e887aa3231313335323631343130323136353331333365653863写法, 以及方法的调用 .建议多做练习. 如果有看 ...

  2. matlab-GUI编写简单计算器

    GUI编写简单计算器*加减乘除,以及部分特殊符号,其实原理特别简单: 语法结构包括实现原理很多大佬都有详细的说明了,这里就不赘述了,简单的入门计算器. 掌握好几个简单的语法就好: 1)获取:变量名=g ...

  3. java编写某计算器控制台程序_用java程序编写一个计算器

    点击查看用java程序编写一个计算器具体信息 答:给你一个参考,希望不要被百度吞了当晚餐 import java.awt.BorderLayout; import java.awt.GridLayou ...

  4. java编写某计算器控制台程序_计算器 - 进阶的憨狗 - 博客园

    源起 最近在看程杰著作的<大话设计模式>,全书以小菜和大鸟对话的形势,由浅入深的讲解程序的设计思想,影射出一个个设计模式.我之前虽然也使用过一些设计模式,但没有系统的学习.整理.总结,现从 ...

  5. 用Java编写简单的扑克牌游戏

    昨天我帮助一位朋友解决了这个问题,今天我即兴想写一篇详细的关于用Java编写扑克牌游戏的文章. 当然我这里只是实现一些简单的功能. 关于扑克牌游戏的特征,想必大家都有所接触过,有扑克牌,玩扑克牌游戏的 ...

  6. 用JAVA编写简单呼叫器餐厅,使用Java编写Palm OS程序的解决方案之一

    现在,使用Java语言为 Palm OS编写程序的领域还没有完全统一,并且也有许多程度上的差异,目前,市面上有好几种不同的可用的应用程序接口,每种应用程序接口都给出了一个到当前的Palm OS应用程序 ...

  7. java编写简易计算器_java实现简易计算器功能

    本文为大家分享了java实现简易计算器功能,具体内容如下 题目: 编写一个模拟计算器的程序.在面板中添加一个文本框(显示按键及运算结果). 10个数字按钮(0~9).4个运算按钮(加.减.乘.除).一 ...

  8. (C语言)静态栈编写简单计算器(感悟与详细解析)

    C语言数据结构静态栈--计算器的实现 下面我来详细的解释一下我编写的计算器代码.... 有必要先说明一下的是,此代码中含有两个栈:数据栈和算符栈: 数据栈:存放double型数字: 算符栈:存放cha ...

  9. 利用Java编写简单的猜拳游戏

    猜拳游戏要求用Java编写一个人机对战并判断输赢,记录输赢情况. 其中,1代表石头,2代表剪刀,3代表布,110表示结束游戏. 思路:首先定义输入函数,并提示用户输入猜拳数值,定义一个随机数代表电脑数 ...

最新文章

  1. BIOS不识别linux,linux – 在BIOS中启用VT但KVM无法检测到
  2. 怎么改掉科学计数法_马拉松猝死频发为哪般——听听冠军们怎么说
  3. CVPR 2018 SA-Siam:《A Twofold Siamese Network for Real-Time Object Tracking》论文笔记
  4. aws架构_如何使用AWS构建可扩展架构
  5. mongodb数据库导出备份
  6. 论文浅尝 | 基于时序知识图谱的问答
  7. 求无向图中某顶点的度 (有注释)
  8. 1.7_heap_sort_堆的向下调整堆排序
  9. 数据库优化的几种方法
  10. node repl环境
  11. 数值分析(1)-绪论:误差
  12. VC与VS的版本对应关系,VC到底是什么?为啥总提示缺少VC
  13. js分割字符串的方法
  14. layui修改头像功能
  15. 大一计算机网络技术实训总结,大一计算机网络技术实训报告精选
  16. 力扣707设计链表(单链表,JavaScript)
  17. 【附源码】Python计算机毕业设计软件学院社团管理系统
  18. 微信小程序医院门诊体检预约信息管理系统SSM-JAVA【数据库设计、论文、源码、开题报告】
  19. 手把手转行|小步试错,逐步迭代
  20. matlab批量修改文件内容并转换文件格式

热门文章

  1. 什么是HTTP Referer?
  2. 创业者都在纠结和困惑些啥?
  3. 图数据,有向图,给定起点和终点,返回所有可能到达的路径,java.
  4. 部标监控平台指令开发
  5. jquery点击缓慢滚动到页面顶部
  6. 梅森素数(mason)
  7. Python设计模式之原型模式(4)
  8. python上机编程报告_20182213 实验一《Python程序设计》实验报告
  9. 手持终端在仓库盘点中的优势
  10. 响应式pbootcms模板网站建设类网站