目录
科学计算器(0)—课程简介
第1关:完成所有的摸底题目!
科学计算器(1)—将String类型转化为List
第1关:将String转化为List封装的中缀表达式
科学计算器(2)—检测中缀表达式是否合法
第1关:降低代码冗余—字符串相等判定
第2关:降低代码冗余—判断一个字符串是否为数字
第3关:判断中缀表达式是否合法
科学计算器(3)—合法中缀转换为后缀表达式
第1关:将中缀表达式转换为后缀表达式
科学计算器(4)—从后缀表达式获取表达式的计算结果
第1关:后缀表达式计算结果
科学计算器(5)—合并为一个calculate类
第1关:整合类测试
科学计算器(6)—初始化页面
第1关:新建一个计算器Frame
第2关:在JPanel里添加组件—JButton与JTextFiled
第3关:美化你的计算器
科学计算器(7)—添加监听器
第1关:为组件添加各类监听器
科学计算器(终)—完成逻辑交互
第1关:计算器实现
CalculatorFrame(计算器界面类)
Calculate(计算逻辑类)
科学计算器(0)—课程简介
第1关:完成所有的摸底题目!
- 1、
请在下列选项中选择入栈顺序 3 2 1 5 4 6 的不可能出栈顺序 D A、 3 2 1 5 4 6 B、 1 2 3 4 5 6 C、 1 2 3 5 6 4 D、 1 2 3 6 5 4 - 2、
Java中如何对一个List数组进行遍历?以下哪个选项是错误的?C A、 for(int i = 0 ; i < list.size(); i ++){} B、 for(String string:list){} C、 Iterator iterator = list.iterator(); while (iterator != null){} D、 Iterator iterator = list.iterator(); while (iterator.hasNext()){} - 3、
以下哪一个是计算式((1+2)!+5×(6−3))÷2
正确的后缀表达式?A A、 [1, 2, +, !, 5, 6, 3, -, ×, +, 2, ÷] B、 [1, 2, +, !, 5, 6, 3, ×, -, +, 2, ÷] C、 [1, 2, !, +, 5, 6, 3, ×, -, +, 2, ÷] D、 [1, 2, +, !, 5, 6, 3, ×, -, 2, +, ÷] - 4、
在计算后缀表达式的结果算法中,如果目前当前栈的内容为3.25 2.66 + 2.66
,目前表达式遍历的字符为!
,那么接下来操作为?C A、 !是操作符,直接入栈 B、 计算2.66!的结果,压入栈中 C、 报错 D、 不做处理 - 5、
在Java中常用于图形化界面(GUI)编程的类库是?A A、 import javax.swing.*; B、 import java.awt.*; C、 import java.awt.event.ActionEvent; D、 import java.awt.event.ActionListener; - 6、
设置监听器时需要new的对象和重写的函数分别是?B A、 addActionListener actionEvent B、 addActionListener actionPerformed C、 actionPerformed addActionListener D、 actionEvent addActionListener - 7、
在Swing编程中,如果我们目前获得了结果要将其实时显现在JtextFiled文本框中,应该使用以下哪个方法?A A setText() B、 setFont() C、 setEditable() D、 setBorder()
科学计算器(1)—将String类型转化为List
第1关:将String转化为List封装的中缀表达式
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class TestMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
/**********************************begin******************************/
List<String> list = new ArrayList<>();
// 初始化一个封装String的List,List只能对object进行封装,不能是char
for(int i = 0 ; i < str.length() ; i ++){
char strTemp = str.charAt(i);
// 对于String可以使用charAt实现字符的定位
if("(+-×÷^!cst)".indexOf(strTemp) >= 0){
// 判断当前这个字符是不是运算符
list.add(strTemp + "");
// list封装的是String,所以需要加上一个空字符串转换为String
}else if("1234567890".indexOf(strTemp) >= 0){
// 判断是不是数字
String str1 = strTemp + "";
while(i + 1 < str.length() && "1234567980.".indexOf(str.charAt(i + 1)) >= 0){
// 在数字后如果也是数字表示是一个数,但同时也可以是小数点。0.53这样的数字作为一个对象加入
str1 += str.charAt(i + 1);
i++;
}
// 将获得的字符串添加到list
list.add(str1);
}
}
System.out.println(list);
// List封装有重载toString,可以直接输出
/***********************************end*******************************/
}
}
科学计算器(2)—检测中缀表达式是否合法
第1关:降低代码冗余—字符串相等判定
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class TestMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
/**********************************begin******************************/
//通过if语句判断是否相等
if(string.equals("+") || string.equals("-") ||string.equals("×") ||string.equals("÷") ||string.equals("^")
||string.equals("t") ||string.equals("c") ||string.equals("s") || string.equals("!")){
System.out.println("true");
}else {
System.out.println("false");
}
// 简单写法,Java.util.String封装一个contains函数,可以判断一个字符串是否包括另一个字符串
// System.out.println("+-×÷^!tsc".contains(string));
/***********************************end*******************************/
}
}
第2关:降低代码冗余—判断一个字符串是否为数字
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class TestMain1 {
public static void main(String[] args) {
/**********************************begin******************************/
// 获取输入字符串
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
//当一个字符串包含某一个字符时indexof会返回匹配的第一个字符位置
if("0123456789".indexOf(string.charAt(0)) >= 0){
System.out.println("true");
}else{
System.out.println("false");
}
/***********************************end*******************************/
}
}
第3关:判断中缀表达式是否合法
import java.util.List;
public class TestMain2 {
/**********************************begin******************************/
public boolean wrongExpression(List<String> list){
int temp = 0;
if(list.size() == 0){ // 没有输入
temp = 1;
}else if(list.size() == 1){ // 只有一个输入并且输入的是不合法的运算符
if(list.get(0).equals("(") || list.get(0).equals(")") || isOperator(list.get(0)) || list.get(0).equals("t")
|| list.get(0).equals("c") || list.get(0).equals("s")){
temp = 2;
}
}else{ // 输入多于一个字符,用for进行循环
for(int i = 0 ; i < list.size() ; i ++){
String str = list.get(i);
int isNumber = 0;
if(! "+-×÷^!sct()".contains(str)){
// 当str不是运算符时,如果不能转化为double说明数据格式有问题
try {
Double.parseDouble(str);
isNumber = 1;
}catch (NumberFormatException e){
temp = 3;
}
}
// 数字后面不可以再接数字
if(isNumber == 1 && i < str.length() - 1 && ! "+-×÷^!sct()".contains(list.get(i + 1))){
temp = 4;
}
int cnt = 0;
for(int j = 0 ; j < str.length() ; j ++){
// 处理小数点
if(str.charAt(j) == '.'){
cnt ++;
}
}
if(cnt == 1 && (str.indexOf('.') == 0 || str.indexOf(".") == str.length()- 1)){
System.out.println(str.indexOf('.') + " " + list.size() + " " + str);
// 只有一个小数点但是位于字符末尾,这情况parse无法检测
temp = 5;
}
if(i == 0 && !("sct1234567890(".indexOf(str.charAt(0)) >= 0)){
//第一个字符不是数字等
temp = 6;
}
if("+-×÷^".contains(str) && ((i - 1 >= 0 && !("1234567890)".indexOf(list.get(i - 1).charAt(0)) >= 0))
|| (i + 1 < list.size() && !("1234567890(".indexOf(list.get(i + 1).charAt(0)) >= 0)))){
//+-×÷^前后必须是数字
temp = 7;
}
if(str.equals("!") && !(i == list.size() - 1 || "+-×÷^)".indexOf(list.get(i + 1).charAt(0)) >= 0)){
// !后面必须是运算符或者是最后一个
temp = 8;
}
if(str.equals("(") && (i == list.size() - 1 || !("0123465789sct()".indexOf(list.get(i + 1).charAt(0)) >= 0))){
// 对于左括号后面只能是数字和三角函数或者内嵌括号
temp = 9;
}
if(str.equals(")") && (i+1 < list.size() && !(("+-×÷^)").indexOf(list.get(i + 1).charAt(0)) >= 0))){
//右括号后面只能是运算符
temp = 10;
}
if("sct".contains(str) && i+1 < list.size() && !("0123456789(".indexOf(list.get(i + 1).charAt(0)) >= 0)){
//三角函数后面必须跟上数字
temp = 11;
}
if(i == list.size() - 1 && !("0123456789!)".indexOf(str.charAt(0)) >= 0)){
// System.out.println(i + " " +str);
//最后一个字符必须是数字
temp = 12;
}
}
}
if(temp == 0) return true;
else return false;
}
private boolean isOperator(String string){
if(string.equals("+") || string.equals("-") ||string.equals("×") ||string.equals("÷") ||string.equals("^")
||string.equals("t") ||string.equals("c") ||string.equals("s") || string.equals("!")){
return true;
}else return false;
}
/**********************************begin******************************/
}
科学计算器(3)—合法中缀转换为后缀表达式
第1关:将中缀表达式转换为后缀表达式
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class TestMain {
/**********************************begin******************************/
public List<String> transMidToAfter(List<String> list) {
// 初始化一个栈和结果队列
Stack<String> stack = new Stack<>();
List<String> res = new ArrayList<>();
// 如果当前给定的中缀表达式不为空,可以进入循环。若为空则直接返回
if (!list.isEmpty()){
// str为列表里面拿出来的串
for (String str : list) {
// 数字直接入结果list
if ("0123456789".indexOf(str.charAt(0)) >= 0) {
res.add(str);
} else if (str.equals("(")) { // 左括号,直接入列
stack.push(str);
}else if (str.equals(")")) { // 右括号,需要进行匹配直到左括号为止
while (!stack.empty() && !stack.peek().equals("(")) {
// 遇见左括号之前不断地添加栈顶到结果List
res.add(stack.pop());
}
// 弹出左括号
stack.pop();
// 如果为运算符
}else if (isOperator(str)) {
// 需要判定遍历元素与栈顶元素的优先级以及栈内元素个数
if (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
// 当栈顶元素的优先级大于等于即将加入的运算符,不断地出栈
while (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
res.add(stack.peek());
stack.pop();
}
}
// 处理完将该遍历运算符加入栈中
stack.push(str);
}
}
}
// 最后当栈不为空时,按照栈的定义全部接入结果List
while(!stack.empty()){
res.add(stack.peek());
stack.pop();
}
// 返回结果
return res;
}
// 获取运算符的优先级,优先级数越大表明优先级越高
private int getOutStanding(String string){
// +-为1
if(string.equals("+") || string.equals("-")){
return 1;
} // ×÷为2优先级
else if(string.equals("×") || string.equals("÷")){
return 2;
} // ^为3优先级
else if(string.equals("^")){
return 3;
} // 其余三角函数与阶乘的优先级是最高的
else{
return 4;
}
}
// 判定是不是一个运算符
private boolean isOperator(String string){
if(string.equals("+") || string.equals("-") ||string.equals("×") ||string.equals("÷") ||string.equals("^")
||string.equals("t") ||string.equals("c") ||string.equals("s") || string.equals("!")){
return true;
}else return false;
}
/***********************************end*******************************/
}
科学计算器(4)—从后缀表达式获取表达式的计算结果
第1关:后缀表达式计算结果
import java.text.DecimalFormat;
import java.util.List;
import java.util.Stack;
public class TestMain {
public String getAfterResult(List<String> list){
/**********************************begin******************************/
// 初始化结果字符和栈
String res = "";
Stack<String> stack = new Stack<>();
// 遍历字符串
for(String string : list){
// 以第一个字符为准判断是否为数字
if("0123456789".indexOf(string.charAt(0)) >= 0){
stack.push(string);
}else{
// 暂存结果的变量初始化
Double resTemp = 0.0;
// 双目运算符,取两个数
if("+-×÷^".indexOf(string) >= 0){
// 不够两个数字
if(stack.size() < 2){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
Double num2 = Double.parseDouble(stack.pop());
switch(string){
case "+":
resTemp = num1 + num2;
break;
case "-":
resTemp = num2 - num1;
break;
case "×":
resTemp = num1 * num2;
break;
case "÷":
resTemp = num2 / num1;
break;
case "^":
resTemp = Math.pow(num2,num1);
}
}else if("tcs!".indexOf(string) >= 0){
// 单目运算符,取一个数字
if (stack.size() < 1){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
switch (string){
case "t":
resTemp = Math.tan(num1);
break;
case "c":
resTemp = Math.cos(num1);
break;
case "s":
resTemp = Math.sin(num1);
break;
case "!":
if(num1 == 0 || num1 == 1){
resTemp = 1.0;
}else if(num1 % 1 == 0 && num1 > 1){
resTemp = 1.0;
for(int i = 0 ; i < num1; i ++){
resTemp *= num1 - i;
}
}else{
return "自然数";
}
break;
}
}
stack.push(String.valueOf(resTemp));
}
}
// 最后栈中不是只有一个数。报错
if(stack.size() != 1){
return "表达式出错!";
}
res = stack.pop();
// 输出格式限制
DecimalFormat df = new DecimalFormat("#.######");
return df.format(Double.parseDouble(res));
/***********************************end*******************************/
}
}
科学计算器(5)—合并为一个calculate类
第1关:整合类测试
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class Calculate {
/**********************************begin******************************/
private static int label;
public String getResult(String str){
return getAfterResult(transMidToAfter(getMidExpression(str)));
}
//list只能对对象进行包装,不能声明为基础数据类型(char),故使用封装类Character
public List<String> getMidExpression(String str){
List<String> list = new ArrayList<>();
for(int i = 0 ; i < str.length() ; i ++){
char strTemp = str.charAt(i);
if("(+-×÷^!cst)".indexOf(strTemp) >= 0){
//巧用indexof解决匹配问题
list.add(strTemp + "");
}else if(str.equals("%")){
label = 1;
}else if("1234567890".indexOf(strTemp) >= 0){
String str1 = strTemp + "";
while(i + 1 < str.length() && "1234567980.".indexOf(str.charAt(i + 1)) >= 0){
str1 += str.charAt(i + 1);
i++;
}
list.add(str1);
}
}
return list;
}
// 中缀转换为后缀
public List<String> transMidToAfter(List<String> list){
Stack<String> stack = new Stack<>();
List<String> res = new ArrayList<>();
if (!list.isEmpty()){
// str为列表里面拿出来的串
for (String str : list) {
if ("0123456789".indexOf(str.charAt(0)) >= 0) {
// 数字直接入结果list
res.add(str);
} else if (str.equals("(")) {
// 左括号,直接入列
stack.push(str);
}else if (str.equals(")")) {
// 左括号,需要在栈中非空的情况下不断地拿出元素知道匹配括号
while (!stack.empty() && !stack.peek().equals("(")) {
res.add(stack.pop());
}
stack.pop();
}else if (isOperator(str)) {
// 对于当前需要入栈的操作符,需要判断它与当前栈顶元素运算符的优先级
if (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
while (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
res.add(stack.peek());
stack.pop();
}
}
stack.push(str);
}
}
}
// 最后所有的栈内元素都要弹出
while(!stack.empty()){
res.add(stack.peek());
stack.pop();
}
return res;
}
// 获取输入字符的优先级函数
private int getOutStanding(String string){
if(string.equals("+") || string.equals("-")){
return 1;
}else if(string.equals("×") || string.equals("÷")){
return 2;
}else if(string.equals("^")){
return 3;
}else{
return 4;
}
}
// 判断输入的字符是不是运算符
private boolean isOperator(String string){
if(string.equals("+") || string.equals("-") ||string.equals("×") ||string.equals("÷") ||string.equals("^")
||string.equals("t") ||string.equals("c") ||string.equals("s") || string.equals("!")){
return true;
}else return false;
}
/*
* 需要有一定的编译原理 — 词法分析
* */
public int wrongExpression(List<String> list){
int temp = 0;
if(list.size() == 0){
// 没有输入
temp = 1;
}else if(list.size() == 1){
// 只有一个输入并且输入的是不合法的运算符
if(list.get(0).equals("(") || list.get(0).equals(")") || isOperator(list.get(0)) || list.get(0).equals("t")
|| list.get(0).equals("c") || list.get(0).equals("s")){
temp = 2;
}
}else{
// 输入多于一个字符
for(int i = 0 ; i < list.size() ; i ++){
String str = list.get(i);
int isNumber = 0;
if(! "+-×÷^!sct()".contains(str)){
// 当str不是运算符时,如果不能转化为double说明数据格式有问题
try {
Double.parseDouble(str);
isNumber = 1;
}catch (NumberFormatException e){
temp = 3;
}
}
// 数字后面不可以再接数字
if(isNumber == 1 && i < str.length() - 1 && ! "+-×÷^!sct()".contains(list.get(i + 1))){
temp = 4;
}
int cnt = 0;
for(int j = 0 ; j < str.length() ; j ++){
// 处理小数点
if(str.charAt(j) == '.'){
cnt ++;
}
}
if(cnt == 1 && (str.indexOf('.') == 0 || str.indexOf(".") == str.length()- 1)){
// 只有一个小数点但是位于字符末尾,这情况parse无法检测
temp = 5;
}
if(i == 0 && !("sct1234567890(".indexOf(str.charAt(0)) >= 0)){
//第一个字符不是数字等
temp = 6;
}
if("+-×÷^".contains(str) && ((i - 1 >= 0 && !("1234567890)".indexOf(list.get(i - 1).charAt(0)) >= 0))
|| (i + 1 < list.size() && !("1234567890(".indexOf(list.get(i + 1).charAt(0)) >= 0)))){
//+-×÷^前后必须是数字
temp = 7;
}
if(str.equals("!") && !(i == list.size() - 1 || "+-×÷^)".indexOf(list.get(i + 1).charAt(0)) >= 0)){
// !后面必须是运算符或者是最后一个
temp = 8;
}
if(str.equals("(") && (i == list.size() - 1 || !("0123465789sct()".indexOf(list.get(i + 1).charAt(0)) >= 0))){
// 对于左括号后面只能是数字和三角函数或者内嵌括号
temp = 9;
}
if(str.equals(")") && (i+1 < list.size() && !(("+-×÷^)").indexOf(list.get(i + 1).charAt(0)) >= 0))){
//右括号后面只能是运算符
temp = 10;
}
if("sct".contains(str) && i+1 < list.size() && !("0123456789(".indexOf(list.get(i + 1).charAt(0)) >= 0)){
//三角函数后面必须跟上数字
temp = 11;
}
if(i == list.size() - 1 && !("0123456789!)".indexOf(str.charAt(0)) >= 0)){
//最后一个字符必须是数字
temp = 12;
}
}
}
return temp;
}
public String getAfterResult(List<String> list){
// 初始化结果字符和栈
String res = "";
Stack<String> stack = new Stack<>();
// 遍历字符串
for(String string : list){
// 以第一个字符为准判断是否为数字
if("0123456789".indexOf(string.charAt(0)) >= 0){
stack.push(string);
}else{
// 暂存结果的变量初始化
Double resTemp = 0.0;
// 双目运算符,取两个数
if("+-×÷^".indexOf(string) >= 0){
// 不够两个数字
if(stack.size() < 2){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
Double num2 = Double.parseDouble(stack.pop());
switch(string){
case "+":
resTemp = num1 + num2;
break;
case "-":
resTemp = num2 - num1;
break;
case "×":
resTemp = num1 * num2;
break;
case "÷":
resTemp = num2 / num1;
break;
case "^":
resTemp = Math.pow(num2,num1);
}
}else if("tcs!".indexOf(string) >= 0){
// 单目运算符,取一个数字
if (stack.size() < 1){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
switch (string){
case "t":
resTemp = Math.tan(num1);
break;
case "c":
resTemp = Math.cos(num1);
break;
case "s":
resTemp = Math.sin(num1);
break;
case "!":
if(num1 == 0 || num1 == 1){
resTemp = 1.0;
}else if(num1 % 1 == 0 && num1 > 1){
resTemp = 1.0;
for(int i = 0 ; i < num1; i ++){
resTemp *= num1 - i;
}
}else{
return "自然数";
}
break;
}
}
stack.push(String.valueOf(resTemp));
}
}
// 最后栈中不是只有一个数。报错
if(stack.size() != 1){
return "表达式出错!";
}
res = stack.pop();
// 输出格式限制
DecimalFormat df = new DecimalFormat("#.######");
return df.format(Double.parseDouble(res));
}
public static void main(String[] args) {
Calculate calculate = new Calculate();
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
System.out.println(calculate.getResult(input));
}
/***********************************end*******************************/
}
科学计算器(6)—初始化页面
第1关:新建一个计算器Frame
import javax.swing.*;
public class TestMain extends JFrame {
/**********************************begin******************************/
public TestMain(){
FrameInit();
}
public void FrameInit(){
// 设置布局管理器为空
this.setLayout(null);
// 设置窗口的大小
this.setSize(300, 400);
// 设置窗口不可编辑大小
this.setResizable(false);
// 设置窗口的名字
this.setTitle("my calculator");
// 设置相对位置,null表示会位于桌面中央
this.setLocationRelativeTo(null);
// 设置关闭操作。相应的时候进程会同步关闭
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口是可见的
this.setVisible(true);
}
/***********************************end*******************************/
}
第2关:在JPanel里添加组件—JButton与JTextFiled
import javax.swing.*;
import java.awt.*;
public class TempFor2 {
/**********************************begin******************************/
public JButton[] initButton(){
JButton[] jButton = new JButton[25];
// 以数组的形式创建数据,以便于后续初始化和样式调整
String[] strings = {
"(",")","x!","x^y","+",
"sin","7","8","9","-",
"cos","4","5","6","×",
"tan","1","2","3","÷",
"%","0",".","AC","="
};
//初始化按钮群
for(int i = 0 ; i < strings.length ; i ++){
// 声明需要提到Java的数组内存模式
jButton[i] = new JButton(strings[i]);
// 设置按钮的内容
jButton[i].setText(strings[i]);
// 设置按钮内容的文本
jButton[i].setFont(new Font("楷书",0,22));
// 不划定其界限
jButton[i].setBorderPainted(false);
}
return jButton;
}
//初始化文本框
public JTextField jTextFieldinit(){
// 初始化文本框
JTextField jTextField = new JTextField();
// 设置文本框内容数据是靠右
jTextField.setHorizontalAlignment(SwingConstants.RIGHT);
// 设置文本框的字体内容
jTextField.setFont(new Font("隶书",1,48));
// 设置文本框的边框是否显现
jTextField.setBorder(null);
// 设置文本库是可以进行编辑的
jTextField.setEditable(false);
return jTextField;
}
/***********************************end*******************************/
}
第3关:美化你的计算器
import javax.swing.*;
import java.awt.*;
import java.util.regex.Pattern;
class TestMainFor3 extends JFrame {
public JButton[] initButton1(){
JButton[] jButton = new JButton[25];
// 以数组的形式创建数据,以便于后续初始化和样式调整
String[] strings = {
"(",")","x!","x^y","+",
"sin","7","8","9","-",
"cos","4","5","6","×",
"tan","1","2","3","÷",
"%","0",".","AC","="
};
//初始化按钮群
for(int i = 0 ; i < strings.length ; i ++){
// 声明需要提到Java的数组内存模式
jButton[i] = new JButton(strings[i]);
// 设置按钮的内容
jButton[i].setText(strings[i]);
// 设置按钮内容的文本
jButton[i].setFont(new Font("楷书",0,22));
// 不划定其界限
jButton[i].setBorderPainted(false);
}
return jButton;
}
//初始化文本框
public JTextField jTextFieldinit(){
// 初始化文本框
JTextField jTextField = new JTextField();
// 设置文本框内容数据是靠右
jTextField.setHorizontalAlignment(SwingConstants.RIGHT);
// 设置文本框的字体内容
jTextField.setFont(new Font("隶书",1,48));
// 设置文本框的边框是否显现
jTextField.setBorder(null);
// 设置文本库是可以进行编辑的
jTextField.setEditable(false);
return jTextField;
}
public static void main(String[] args) {
// 初始化本类,进行数据处理
TestMainFor3 testMainFor2 = new TestMainFor3();
JPanel jPanel = new JPanel();
// 文本初始化
JTextField jTextField = testMainFor2.jTextFieldinit();
// 设置位置参数
jTextField.setBounds(0,0,375,95);
// 将文本加入到jPanel
jPanel.add(jTextField);
// 因为对按钮初始化时是一维数组,故需要新的参数。
int XButton = 78, YButton = 95, temp = 0;
// 调用上关定义的按钮初始化函数
JButton[] jButton = testMainFor2.initButton1();
// 使用正则匹配出数字,便于区别运算符进行按钮样式设置。同样可以使用上一节逻辑处理里面的contains进行处理
Pattern pattern = Pattern.compile("[0-9]+");
// 两层遍历对按钮进行初始化
for(int i = 0 ; i < 5 ; i ++){
// 好处:逻辑上可以更符合按钮布局
for(int j = 0 ; j < 5 ; j ++){
if(pattern.matcher(jButton[temp].getText()).matches()){
// 如果匹配出是数字,则给定为白色底色
jButton[temp].setBackground(Color.WHITE);
}else if(temp >= 23){
// 如果是等于和AC则给定底色为黄色
jButton[temp].setBackground(new Color(235,180,100));
}else{
// 如果是运算符给定灰色
jButton[temp].setBackground(new Color(240,240,240));
}
// 设定每一个按钮的相对位置
jButton[temp].setBounds(j * XButton, YButton * (i+1), XButton, YButton);
temp ++;
}
}
for (JButton jButton1 : jButton) {
// 将按钮通过遍历的方式加入jPanel。PS:可优化
jPanel.add(jButton1);
}
System.out.println(jButton.length);
// 设置jPanel的布局管理器为空
jPanel.setLayout(null);
// 将jPanel加入JFrame类中
testMainFor2.add(jPanel);
testMainFor2.setTitle("Calculator");
testMainFor2.setSize(388,600);
testMainFor2.setResizable(false);
testMainFor2.setLocationRelativeTo(null);
testMainFor2.setVisible(true);
testMainFor2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
科学计算器(7)—添加监听器
第1关:为组件添加各类监听器
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.Format;
import java.util.List;
import java.util.regex.Pattern;
public class CalculatorFrame extends JFrame {
//以数组的方式建立按钮,防止代码冗余
private String[] strings = {
"(",")","x!","x^y","+",
"sin","7","8","9","-",
"cos","4","5","6","×",
"tan","1","2","3","÷",
"%","0",".","AC","="
};
//初始化一个面板,用于装载所有的按钮和文本框
JPanel jPanel = new JPanel();
// 文本框定义
private JTextField jTextField = new JTextField("0",30);
// 按钮定义
private JButton[] jButton = new JButton[25];
private String strForCal = "";
/*请注意:本实例有一个已被初始化的字符串strForCal,其目的为给之后的算术预备表达式*/
public void addActionListener(){
/**********************************begin******************************/
int temp = 0;
// 遍历所有的按钮
for(JButton jButton1 : jButton){
// 当按钮为AC时,置空文本框。在计算表达式中加入内容。
if(jButton1.getText().equals("AC")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText("");
strForCal = "";
}
});
// 当按钮为幂运算符,文本框进行对应的变化。在计算表达式中加入内容。
}else if(jButton1.getText().equals("x^y")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "^");
strForCal += "^";
}
});
// 当按钮内容为阶乘,文本框加上!在计算表达式中加入内容。
}else if(jButton1.getText().equals("x!")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "!");
strForCal += "!";
}
});
// 当按钮内容为cos三角函数,在文本框放入cos。
// 在计算表达式中加入内容,为方便后续计算三角函数均取第一个字母。
}else if(jButton1.getText().equals("cos")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "cos");
strForCal += "c";
}
});
// 同cos
}else if(jButton1.getText().equals("sin")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "sin");
strForCal += "s";
}
});
// 同cos
}else if(jButton1.getText().equals("tan")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "tan");
strForCal += "t";
}
});
}
// 均不属于上面的运算符,直接将按钮内容加在文本框内
else{
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if(jTextField.getText().equals("0") && !jButton1.getText().equals(".")){
jTextField.setText(jButton1.getText());
strForCal += jButton1.getText();
}
else {
jTextField.setText(jTextField.getText() + jButton1.getText());
strForCal += jButton1.getText();
}
}
});
}
}
/***********************************end*******************************/
}
public JButton[] initButton(){
//初始化按钮群
int XButton = 78, YButton = 95, temp = 0;
Pattern pattern = Pattern.compile("[0-9]+");
for(int i = 0 ; i < strings.length ; i ++){
//声明需要提到Java的数组内存模式
jButton[temp] = new JButton(strings[temp]);
jButton[temp].setText(strings[temp]);
temp ++;
}
temp = 0;
for(int i = 0 ; i < 5 ; i ++){
for(int j = 0 ; j < 5 ; j ++){
if(pattern.matcher(jButton[temp].getText()).matches()){
jButton[temp].setBackground(Color.WHITE);
}else if(temp >= 23){
jButton[temp].setBackground(new Color(235,180,100));
}else{
jButton[temp].setBackground(new Color(240,240,240));
}
jButton[temp].setFont(new Font("楷书",0,22));
jButton[temp].setBounds(j * XButton, YButton * (i+1), XButton, YButton);
jButton[temp].setBorderPainted(false);
temp ++;
}
}
return jButton;
}
//初始化文本框
public void jTextFieldinit(){
jTextField.setHorizontalAlignment(SwingConstants.RIGHT);
jTextField.setFont(new Font("隶书",1,48));
jTextField.setBounds(0,0,375,95);
jTextField.setBorder(null);
jTextField.setEditable(false);
}
public CalculatorFrame() {
jTextFieldinit();
jPanel.add(jTextField);
JButton[] jButtons = initButton();
for (JButton jButton : jButtons) {
jPanel.add(jButton);
}
addActionListener();
jButtons[24].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println(strForCal);
}
});
jPanel.setLayout(null);
this.add(jPanel);
this.setTitle("Calculator");
this.setSize(388,600);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
科学计算器(终)—完成逻辑交互
第1关:计算器实现
CalculatorFrame(计算器界面类)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.util.List;
import java.util.regex.Pattern;
public class CalculatorFrame extends JFrame {
/**********************************begin******************************/
//以数组的方式建立按钮,防止代码冗余
private String[] strings = {
"(",")","x!","x^y","+",
"sin","7","8","9","-",
"cos","4","5","6","×",
"tan","1","2","3","÷",
"%","0",".","AC","="
};
//初始化一个面板,用于装载所有的按钮和文本框
JPanel jPanel = new JPanel();
private JTextField jTextField = new JTextField("0",30);
private JButton[] jButton = new JButton[25];
private String strForCal = "";
public JButton[] initButton(){
//初始化按钮群
int XButton = 78, YButton = 95, temp = 0;
Pattern pattern = Pattern.compile("[0-9]+");
for(int i = 0 ; i < strings.length ; i ++){
//声明需要提到Java的数组内存模式
jButton[temp] = new JButton(strings[temp]);
jButton[temp].setText(strings[temp]);
temp ++;
}
temp = 0;
for(int i = 0 ; i < 5 ; i ++){
for(int j = 0 ; j < 5 ; j ++){
if(pattern.matcher(jButton[temp].getText()).matches()){
jButton[temp].setBackground(Color.WHITE);
}else if(temp >= 23){
jButton[temp].setBackground(new Color(235,180,100));
}else{
jButton[temp].setBackground(new Color(240,240,240));
}
jButton[temp].setFont(new Font("楷书",0,22));
jButton[temp].setBounds(j * XButton, YButton * (i+1), XButton, YButton);
jButton[temp].setBorderPainted(false);
temp ++;
}
}
return jButton;
}
//初始化文本框
public void jTextFieldinit(){
jTextField.setHorizontalAlignment(SwingConstants.RIGHT);
jTextField.setFont(new Font("隶书",1,48));
jTextField.setBounds(0,0,375,95);
jTextField.setBorder(null);
jTextField.setEditable(false);
}
/*请注意:本实例有一个已被初始化的字符串strForCal,其目的为给之后的算术预备表达式*/
public void addActionListener(){
int temp = 0;
// 遍历所有的按钮
for(JButton jButton1 : jButton){
// 当按钮为AC时,置空文本框。在计算表达式中加入内容。
if(jButton1.getText().equals("AC")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText("");
strForCal = "";
}
});
// 当按钮为幂运算符,文本框进行对应的变化。在计算表达式中加入内容。
}else if(jButton1.getText().equals("x^y")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "^");
strForCal += "^";
}
});
// 当按钮内容为阶乘,文本框加上!在计算表达式中加入内容。
}else if(jButton1.getText().equals("x!")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "!");
strForCal += "!";
}
});
// 当按钮内容为cos三角函数,在文本框放入cos。
// 在计算表达式中加入内容,为方便后续计算三角函数均取第一个字母。
}else if(jButton1.getText().equals("cos")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "cos");
strForCal += "c";
}
});
// 同cos
}else if(jButton1.getText().equals("sin")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "sin");
strForCal += "s";
}
});
// 同cos
}else if(jButton1.getText().equals("tan")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
jTextField.setText(jTextField.getText() + "tan");
strForCal += "t";
}
});
}else if(jButton1.getText().equals("=")){
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println(strForCal);
Calculate calculate = new Calculate();
List<String> list = calculate.getMidExpression(strForCal);
if(calculate.wrongExpression(list) >= 1){
jTextField.setText("Wrong");
}else {
String strRes = calculate.getResult(strForCal);
if (strRes.matches("[\u2E80-\uFE4F]+")){
jTextField.setText(strRes);
} else if (!strRes.matches("[\u4e00-\u9fa5]") && Double.parseDouble(strRes) % 1 == 0) {
jTextField.setText(String.valueOf((int) Double.parseDouble(strRes)));
} else if (!strRes.matches("[\u4e00-\u9fa5]") && ! (Double.parseDouble(strRes) % 1 == 0)){
DecimalFormat df = new DecimalFormat("#.#######");
jTextField.setText(df.format(Double.parseDouble(strRes)));
} else {
jTextField.setText(strRes);
}
}
}
});
}
// 均不属于上面的运算符,直接将按钮内容加在文本框内
else{
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if(jTextField.getText().equals("0") && !jButton1.getText().equals(".")){
jTextField.setText(jButton1.getText());
strForCal += jButton1.getText();
}
else {
jTextField.setText(jTextField.getText() + jButton1.getText());
strForCal += jButton1.getText();
}
}
});
}
}
}
public CalculatorFrame() {
jTextFieldinit();
jPanel.add(jTextField);
JButton[] jButtons = initButton();
for (JButton jButton : jButtons) {
jPanel.add(jButton);
}
System.out.println(jButtons.length);
System.out.println(jTextField.getSize());
addActionListener();
jPanel.setLayout(null);
this.add(jPanel);
this.setTitle("Calculator");
this.setSize(388,600);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/***********************************end*******************************/
}
Calculate(计算逻辑类)
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Calculate {
/**********************************begin******************************/
private static int label;
public String getResult(String str){
return getAfterResult(transMidToAfter(getMidExpression(str)));
}
//list只能对对象进行包装,不能声明为基础数据类型(char),故使用封装类Character
public List<String> getMidExpression(String str){
List<String> list = new ArrayList<>();
for(int i = 0 ; i < str.length() ; i ++){
char strTemp = str.charAt(i);
if("(+-×÷^!cst)".indexOf(strTemp) >= 0){
//巧用indexof解决匹配问题
list.add(strTemp + "");
}else if(str.equals("%")){
label = 1;
}else if("1234567890".indexOf(strTemp) >= 0){
String str1 = strTemp + "";
while(i + 1 < str.length() && "1234567980.".indexOf(str.charAt(i + 1)) >= 0){
str1 += str.charAt(i + 1);
i++;
}
list.add(str1);
}
}
return list;
}
// 中缀转换为后缀
public List<String> transMidToAfter(List<String> list){
Stack<String> stack = new Stack<>();
List<String> res = new ArrayList<>();
if (!list.isEmpty()){
// str为列表里面拿出来的串
for (String str : list) {
if ("0123456789".indexOf(str.charAt(0)) >= 0) {
// 数字直接入结果list
res.add(str);
} else if (str.equals("(")) {
// 左括号,直接入列
stack.push(str);
}else if (str.equals(")")) {
// 左括号,需要在栈中非空的情况下不断地拿出元素知道匹配括号
while (!stack.empty() && !stack.peek().equals("(")) {
res.add(stack.pop());
}
stack.pop();
}else if (isOperator(str)) {
// 对于当前需要入栈的操作符,需要判断它与当前栈顶元素运算符的优先级
if (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
while (!stack.empty() && isOperator(str) && isOperator(stack.peek()) &&
getOutStanding(str) <= getOutStanding(stack.peek())) {
res.add(stack.peek());
stack.pop();
}
}
stack.push(str);
}
}
}
// 最后所有的栈内元素都要弹出
while(!stack.empty()){
res.add(stack.peek());
stack.pop();
}
return res;
}
// 获取输入字符的优先级函数
private int getOutStanding(String string){
if(string.equals("+") || string.equals("-")){
return 1;
}else if(string.equals("×") || string.equals("÷")){
return 2;
}else if(string.equals("^")){
return 3;
}else{
return 4;
}
}
// 判断输入的字符是不是运算符
private boolean isOperator(String string){
if(string.equals("+") || string.equals("-") ||string.equals("×") ||string.equals("÷") ||string.equals("^")
||string.equals("t") ||string.equals("c") ||string.equals("s") || string.equals("!")){
return true;
}else return false;
}
/*
* 需要有一定的编译原理 — 词法分析
* */
public int wrongExpression(List<String> list){
int temp = 0;
if(list.size() == 0){
// 没有输入
temp = 1;
}else if(list.size() == 1){
// 只有一个输入并且输入的是不合法的运算符
if(list.get(0).equals("(") || list.get(0).equals(")") || isOperator(list.get(0)) || list.get(0).equals("t")
|| list.get(0).equals("c") || list.get(0).equals("s")){
temp = 2;
}
}else{
// 输入多于一个字符
for(int i = 0 ; i < list.size() ; i ++){
String str = list.get(i);
int isNumber = 0;
if(! "+-×÷^!sct()".contains(str)){
// 当str不是运算符时,如果不能转化为double说明数据格式有问题
try {
Double.parseDouble(str);
isNumber = 1;
}catch (NumberFormatException e){
temp = 3;
}
}
// 数字后面不可以再接数字
if(isNumber == 1 && i < str.length() - 1 && ! "+-×÷^!sct()".contains(list.get(i + 1))){
temp = 4;
}
int cnt = 0;
for(int j = 0 ; j < str.length() ; j ++){
// 处理小数点
if(str.charAt(j) == '.'){
cnt ++;
}
}
if(cnt == 1 && (str.indexOf('.') == 0 || str.indexOf(".") == str.length()- 1)){
// 只有一个小数点但是位于字符末尾,这情况parse无法检测
temp = 5;
}
if(i == 0 && !("sct1234567890(".indexOf(str.charAt(0)) >= 0)){
//第一个字符不是数字等
temp = 6;
}
if("+-×÷^".contains(str) && ((i - 1 >= 0 && !("1234567890)".indexOf(list.get(i - 1).charAt(0)) >= 0))
|| (i + 1 < list.size() && !("1234567890(".indexOf(list.get(i + 1).charAt(0)) >= 0)))){
//+-×÷^前后必须是数字
temp = 7;
}
if(str.equals("!") && !(i == list.size() - 1 || "+-×÷^)".indexOf(list.get(i + 1).charAt(0)) >= 0)){
// !后面必须是运算符或者是最后一个
temp = 8;
}
if(str.equals("(") && (i == list.size() - 1 || !("0123465789sct()".indexOf(list.get(i + 1).charAt(0)) >= 0))){
// 对于左括号后面只能是数字和三角函数或者内嵌括号
temp = 9;
}
if(str.equals(")") && (i+1 < list.size() && !(("+-×÷^)").indexOf(list.get(i + 1).charAt(0)) >= 0))){
//右括号后面只能是运算符
temp = 10;
}
if("sct".contains(str) && i+1 < list.size() && !("0123456789(".indexOf(list.get(i + 1).charAt(0)) >= 0)){
//三角函数后面必须跟上数字
temp = 11;
}
if(i == list.size() - 1 && !("0123456789!)".indexOf(str.charAt(0)) >= 0)){
//最后一个字符必须是数字
temp = 12;
}
}
}
return temp;
}
public String getAfterResult(List<String> list){
// 初始化结果字符和栈
String res = "";
Stack<String> stack = new Stack<>();
// 遍历字符串
for(String string : list){
// 以第一个字符为准判断是否为数字
if("0123456789".indexOf(string.charAt(0)) >= 0){
stack.push(string);
}else{
// 暂存结果的变量初始化
Double resTemp = 0.0;
// 双目运算符,取两个数
if("+-×÷^".indexOf(string) >= 0){
// 不够两个数字
if(stack.size() < 2){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
Double num2 = Double.parseDouble(stack.pop());
switch(string){
case "+":
resTemp = num1 + num2;
break;
case "-":
resTemp = num2 - num1;
break;
case "×":
resTemp = num1 * num2;
break;
case "÷":
resTemp = num2 / num1;
break;
case "^":
resTemp = Math.pow(num2,num1);
}
}else if("tcs!".indexOf(string) >= 0){
// 单目运算符,取一个数字
if (stack.size() < 1){
return null;
}
Double num1 = Double.parseDouble(stack.pop());
switch (string){
case "t":
resTemp = Math.tan(num1);
break;
case "c":
resTemp = Math.cos(num1);
break;
case "s":
resTemp = Math.sin(num1);
break;
case "!":
if(num1 == 0 || num1 == 1){
resTemp = 1.0;
}else if(num1 % 1 == 0 && num1 > 1){
resTemp = 1.0;
for(int i = 0 ; i < num1; i ++){
resTemp *= num1 - i;
}
}else{
return "自然数";
}
break;
}
}
stack.push(String.valueOf(resTemp));
}
}
// 最后栈中不是只有一个数。报错
if(stack.size() != 1){
return "表达式出错!";
}
res = stack.pop();
// 输出格式限制
DecimalFormat df = new DecimalFormat("#.######");
return df.format(Double.parseDouble(res));
}
/***********************************end*******************************/
}