JAVA实现简单计算器实验过程
实验目的
(1)进行图形界面设计,掌握JFrame类、JPanel类、5种布局管理器、文本框、标签以及按钮的使用方法;
(2)实现计算器的基本功能,即加减乘除四则运算以及清除结果,退格等功能;
(3)实现计算器的历史记录功能。
实验前的内容预习与准备
JavaGUI编程;鼠标和键盘的事件处理,Java图形界面编程。
1. 需求及功能分析
本文的内容为制作一个简单的计算器程序的过程以及涉及相关算法的介绍,能计算数的加、减、乘、除功能,并在JAVA语言环境下完成所有功能特点。本次案例的功能较为简单,主要包括整形数字的计算和顺序表达式计算,其中顺序表达式计算,其中顺序表达式计算逻辑处理比较复杂。计算器基本界面上的控件主要包括“+、-、*、/、.、=、AC(清除功能)、历史记录、()、1、2、3、4、5、6、7、8、9、0”这几个最基本的选项按钮。
整个系统的功能结构图如下图所示:
2.系统功能分析
该系统支持计算器的最简单的加、减、乘、除功能以及相对复杂的四则运算,支持小数,包括清除按钮,退格按钮和历史记录功能。
3. 计算器的界面设置过程
首先是窗体的布置,窗体中可以放三个或者两个JPanel面板,用于放相关操作按钮和结果显示。
文本框的创建以及清空键、历史记录键的创建,可以设置一个函数history用于存储历史记录,并设置可显示几条记录。
添加操作符
JAVA中称为事件监听器,定义一个存储表达式,并将所有的操作按钮除了“=”外按下时,都将其添加到这个存储数组中,添加时,在其后添加空格。等到按下等号时,就可以将结果显示到屏幕上。
Java中关于Swing的按钮学习代码如下:
public class JPanelTest extends JFrame {//创建一个JPtest类继承JFrame实现窗体创建功能
public JPanelTest() {
// 默认打开的x、y坐标位置和打开之后的窗口大小
this.setBounds(30, 20, 500, 400);
// close按钮的操作
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 获取容器对象并设置布局方式为2行2列,行间距为20,列间距为10
Container ctainer = this.getContentPane();
ctainer.setLayout(new GridLayout(2, 2, 20, 10));
// 创建三个面板对象并设值布局方式
JPanel p1 = new JPanel(new GridLayout(2, 1, 10, 10));// 网格布局方式2行1列,行间距为10,列间距为10
JPanel p2 = new JPanel(new GridLayout(1, 2, 10, 10));// 网格布局方式1行2列,行间距为10,列间距为10
JPanel p3 = new JPanel(new BorderLayout());// 边界布局方式
// 分别设置面板的边框,类型为带标题的边框
p1.setBorder(BorderFactory.createTitledBorder("面板1"));
p2.setBorder(BorderFactory.createTitledBorder("面板2"));
p3.setBorder(BorderFactory.createTitledBorder("面板3"));
// 给面板添加内容
p1.add(new Button("a"));
p1.add(new Button("b"));
p1.add(new Button("c"));
4.计算器算法实现过程
建立栈用于存放数据
使用for循环,过程如下:
+:直接将下面一位入栈;
-:取负后入栈
×:将栈顶元素出栈,与循环中的第i+1位元素进行乘运算后使结果入栈;
÷:将栈顶元素出栈,将进行除运算的结果入栈,最后将栈中的所有数字相加,并把结果转换成字符串形式返回。
四则运算转换成后缀表达式的算法思想:
开始扫描:从左到右遍历算术表达式,遇到数字时,加入后缀表达式,遇到运算符时,分为以下三种情况:(1).如果为"(",将其压入栈中;(2).如果为")",则依次把栈中的运算符加入后缀表达式,直到出现"(";(3).除括号之外的其他运算符,按照运算符的优先级,直接入栈,否则从栈顶开始,依次弹出处理的运算符优先级高和优先级相等的运算符,直到一个比他优先级低的遇到了一个左括号为止。本文中使用TheCalculator类实现主要算法(其中包括字符串数组TheArray(String data)、中缀表达式转后缀表达式方法Res_Stack()、判断是否为数值的方法TheNum(str num)、运算比较优先级的方法ToCampare()和最终表达式进行栈计算的方法ToCalculator()。
5.具体实现步骤
第一步:实现图形界面化,添加计算器的Button和用于显示输入数字、输出结果的JTextField等。
public Caculator(){
Container c = getContentPane(); //定义一个顶级容器c
setLayout(new GridLayout(3,1));//新建网格布局管理器,3行1列
JTextField text= new JTextField("0",40);//构造一个用指定文本和列初始化的新文本框--text
text.setHorizontalAlignment(JTextField.RIGHT);//设置水平对齐方式:居右对齐,添加菜单按钮
JButton menu0 = new JButton("0");
JButton menu1 = new JButton("1");
JButton menu2 = new JButton("2");
JButton menu3 = new JButton("3");
JButton menu4 = new JButton("4");
JButton menu5 = new JButton("5");
JButton menu6 = new JButton("6");
JButton menu7 = new JButton("7");
JButton menu8 = new JButton("8");
JButton menu9 = new JButton("9");
JButton point = new JButton(".");
JButton equ = new JButton("=");
JButton jia= new JButton("+");
JButton jian= new JButton("-");
JButton cheng= new JButton("*");
JButton chu= new JButton("/");
JButton tui= new JButton("退格");
JButton qing = new JButton("清零");
JButton Lkuo=new JButton("(");
JButton Rkuo=new JButton(")");
JPanel text1= new JPanel(); //新建JPanel面板--text1
text1.setLayout(new GridLayout(4,5,5,5));//新建网格布局管理器(行数,列数,组件间的水平垂直间距)
第二步:给按钮和文本框添加鼠标监听事件。
text1.add(menu7);
text1.add(menu8);
text1.add(menu9);
text1.add(jiang);
text1.add(sqr);
text1.add(menu4);
text1.add(menu5);
text1.add(menu6);
text1.add(jian);
text1.add(menu1);
text1.add(menu2);
text1.add(menu3);
text1.add(cheng);
text1.add(qing);
text1.add(menu0);
text1.add(point);
text1.add(equ);
text1.add(chu);
text1.add(tui);
text1.add(Lkuo);
text1.add(Rkuo);
c.add(text);//将文本框text添加到顶级容器c中
c.add(text1);//将JPanel面板text1添加到顶级容器c中
setSize(450,350);
setTitle("我的计算器");
setVisible(true);
setResizable(false);//窗体大小由程序员决定,用户不能自由改变大小
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
第三步:输入的表达式使用中缀转后缀的方法
//中缀表达式转后缀
@SuppressWarnings("unchecked")
public static String[] Res_Stack(String[] textArray) {//中缀表达式转后缀表达式的方法
int k=0;
Stack stack = new Stack();//创建一个新的栈
for(int i=0;i<textArray.length-1;i++) {
if(textArray[i]!=null) {
System.out.println("Res_Stack中缀:"+textArray[i]);
int priority = ToCampare(textArray[i]); //2x(3+2)
if(isNum(textArray[i])) {//读取到数字
textArr2[k++] = textArray[i];
}
else {
if(!stack.empty()) {
if(textArray[i].equals("(")) {
stack.push(textArray[i]);
continue;
}
else if(textArray[i].equals(")")){ System.out.println(String.valueOf(stack.peek())); while
(!String.valueOf(stack.peek()).equals("(")) {
textArr2[k++] = String.valueOf(stack.pop());
}
stack.pop();
continue;
}
else if(priority>ToCampare(String.valueOf(stack.peek()))) {//优先级大于栈顶
stack.push(textArray[i]);//存入栈中
continue;
第四步:实现加减乘除的计算功能的主要算法
public static double ToCalculator(String Ctext) {//实现加减乘除的计算功能的主要方法
int numkey = 0;
int strkey = 0;
String[] strArr = ToCalculator()(toArr(Ctext));//设置一个数组存储表达式
Stack<String> stack = new Stack<String>();//创建一个新的栈
double sum = 0;
try {
for(int i=0;i<strArr.length-1;i++) {//进行入栈处理
numkey = 0;//初始化数值
strkey = 0;//初始化运算符
if(strArr[i]==null) {//判断栈中的内容
while(!stack.isEmpty()) {
String top = stack.pop();//栈中内容不为空则进行栈顶操作
if(isNum(top)) {
sum = Double.parseDouble(top);//数值在栈顶则进行赋值
}
}
break;
System.out.println("ToCacultor-后缀:"+strArr[i]);
if(stack.empty()) {
stack.push(strArr[i]);
}else {
for (String x : stack) {
if(isNum(x)) {
numkey++;
}else {
strkey++;
}
}
if(isNum(strArr[i])) {//判断输入的表达式是否为数值
if(numkey==1&&strkey==1) {
String str = stack.pop();//进行栈顶操作
double num3 = Double.parseDouble(stack.pop());//其中一个数值入栈
double s2 = Double.parseDouble(strArr[i]);将s2取出栈
double sum2 = 0;
switch (str) {
case "+":
sum2 = num3 + s2;
break;
case "-":
sum2 = num3 - s2;
break;
case "x":
sum2 = num3 * s2;
break;
case "/":
sum2 = num3 / s2;
break;
}
stack.push(String.valueOf(sum2));
}else {
stack.push(String.valueOf(strArr[i]));
}
}
else {
if(numkey>=2) {
double num1 = Double.parseDouble(stack.pop());
double num2 = Double.parseDouble(stack.pop());
double s = 0;
switch (strArr[i]) {
case "+":
s = num2 + num1;
break;
case "-":
s = num2 - num1;
break;
case "x":
s = num2 * num1;
break;
case "/":
s = num2 / num1;
break;
}
stack.push(String.valueOf(s));
}
else {
stack.push(String.valueOf(strArr[i]));
}
}
}
}
}catch (Exception e) {
System.err.println("计算出错!请重启~");
}
System.out.println("计算结果:"+sum);
return sum;
}
对计算器的部分容错处理
case "."://前面只能是数字
if(sum==1) {
doInit();
break;
}
if(g == 1&&point == 0) {
textA = textA + Ename;
point = 1;//标记.
textField.setText(textA);
cnum = 0;
g = 3;
}
break;
case "("://不能输入:(,),.,数字
if(sum==1) {
doInit();
}
if(g == 0 || g == 2) {//空 运算符
textA = textA + Ename;
left++;
// Right = 0;
textField.setText(textA);
g = 4;
}
System.out.println("cleft:"+left);
break;
case ")"://不能输入:(,.,运算符,空
if(sum==1) {
doInit();
break;
}
再对输入的表达式的运算符进行优先级比较
//运算符优先级比较 str1>str2 返回true
public static int ToCampare(String str1) {
int key = -1;
switch (str1) {
case "(":
key = 1;
break;
case ")":
key = 0;
break;
case "+":
case "-":
key = 2;
break;
case "x":
case "/":
key = 3;
break;
}
return key;
}
最后,代码调试正确后,运行结果功能进行加减乘除四则运算。
总结
通过本实验让我对JFrame类、JPanel类、5种布局管理器、文本框、标签及按钮的使用方法有了进一步的了解,还有学会了中缀转后缀的处理方式和使用。同时在实验过程中有一些不足之处,但是通过不断的学习之后有了更深刻的了解,收获满满。