java實現科學計算器的全過程與代碼
介紹
本次設計的是一個有33個按鈕的科學計算器。可以進行加,減,乘,除,開根號,階乘,次方,百分號,對數,三角函數的計算。
實現思路
通過點擊按鈕可以得到一個算術表達式,並且它是一個字符串類型,然後需要做的就是把這個字符串轉化為計算機可計算的形式。這裡就需要用到中綴表達式轉化為後綴表達式。轉化完之後通過棧來一步步的進行輸出和計算,最後輸出結果。
實現過程和代碼
1.界面設計
設計效果如圖所示:
由圖片可知,總共設計瞭兩個文本框和33個按鈕(這裡的佈局是我直接用setBounds()方法設計的。因為如果用佈局管理器的話要達到自己想要的效果不太方便)。
在設計時要註意的是:
1.不能把按鈕和文本框直接加入JFrame中,因為如果JFrame.setLayout(null)的話,面板上就會出問題,什麼都看不到或者其他情況。因此建議創建一個JPanel,把JPanel的setLayout()設置為空。把按鈕和文本框加入到JPanel中,再把JPanel加入到JFrame中。就不會出問題瞭。JFrame的佈局管理器默認為流式佈局,位置是中心區域。
2.設計完長度後,寬度一般要再加15個像素點,高度要再加35個像素點.要不然會有一部分按鈕看不到。如我本意要設計的面板寬為600,高為400,則實際上是
jFrame.setSize(614, 437);
下面就是我設計的界面的代碼:
private JFrame jFrame = new JFrame("計算器"); //設置字體,是否加粗,大小 private FontUIResource f = new FontUIResource("隸書", 1, 20); private FontUIResource f1 = new FontUIResource("楷書", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; //兩個文本框 private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("輸入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; //33個按鈕 private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy);//設置位置 jTextField1.setFont(f1);設置字體 jTextField1.setHorizontalAlignment(JLabel.RIGHT);//文本靠右 jTextField1.setEditable(false);//不可修改 jTextField1.setBackground(Color.WHITE);//顏色為白色 jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按鈕添加到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null);//佈局管理器為空,自定義設計 } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel);//把jPanel添加到jFrame中 jFrame.setSize(614, 437);//jFrame的長寬 jFrame.setResizable(false);//大小不可修改 jFrame.setLocationRelativeTo(null);//位置為顯示器的正中間 //窗口監聽器,點右上角的關閉就關閉窗口 //可以不寫,應為JFrame默認的就可以關閉,不需要寫事件監聽器。如果是Frame的話需要寫。 jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true);//設置面板可見 }
2.棧,中綴轉後綴
我總共設計瞭12種運算符:(+, -, * , /, ^, !, g, l, o, s, c, t)分別是加,減,乘,除,次方,階乘,開根號,,對數ln, 對數log2, sin, cos, tan
e是Math.E, p是Math.PI, %是直接乘以0.001
把中綴表達式轉換為後綴表達式。例如:
中綴表達式:1+2*3+(l2+3)/2
後綴表達式為:123*+23+2/+
後綴表達式的運算步驟是:
1.16+23+2/+
2.723+2/+
3.752/+
4.7 2.5+
5.9.5
代碼如下:
private List<String> zhongZhui(String str) {//把輸入的字符串轉換成中綴表達式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接添加至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是數字,判斷多位數的情況 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中綴表達式轉換稱後綴表達式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符棧不為空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入棧 fuZhan.push(list.get(i)); } else {//出棧 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判斷是否為操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判斷是否為操作數 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判斷操作符的優先級 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; }
3.判斷錯誤
下面是一些我能想到的一些輸入錯誤和運算錯誤:
//當隻有一位字符時,隻能是“0123456789ep”中的一個
//1.第一個字符隻能為"losctg(0123456789ep"中的一個
//2.“±/”後面隻能是"0123456789losctg(ep"中的一個
//3.".“後面隻能是“0123456789”中的一個
//4.”!"後面隻能是“±/^)”中的一個
//5."losctg"後面隻能是“0123456789(ep”中的一個
//6."0"的判斷操作
//1.當0的上一個字符不為"0123456789."時,後一位隻能是“±/.!^)”中的一個
//2.如果0的上一位為“.”,則後一位隻能是“0123456789±/.^)”中的一個
//3.如果0到上一個運算符之間沒有“.”的話,整數位第一個隻能是“123456789”,
// 且後一位隻能是“0123456789±/.!^)”中的一個。
//4.如果0到上一個運算符之間有一個“.”的話,則後一位隻能是“0123456789±/.^)”中的一個
//7."123456789"後面隻能是“0123456789±/.!^)”中的一個
//8."(“後面隻能是“0123456789locstg()ep”中的一個
//9.”)"後面隻能是“±/!^)”中的一個
//10.最後一位字符隻能是“0123456789!)ep”中的一個
//12.不能有多個“.”
//13."ep"後面隻能是“±*/^)”中的一個
除數不能為0
階乘必須為自然數
ln的x必須大於0
log的x必須大於0
tan的x不能為±(π/2 + kπ)
括號是否匹配
代碼如下:
public void estimate(){//判斷輸入是否錯誤 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //當隻有一位字符時,隻能是“0123456789ep”中的一個 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一個字符隻能為"losctg(0123456789ep"中的一個 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.“+-*/”後面隻能是"0123456789losctg(ep"中的一個 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //3."."後面隻能是“0123456789”中的一個 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4."!"後面隻能是“+-*/^)”中的一個 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //5."losctg"後面隻能是“0123456789(ep”中的一個 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //6."0"的判斷操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.當0的上一個字符不為"0123456789."時,後一位隻能是“+-*/.!^)”中的一個 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.如果0的上一位為“.”,則後一位隻能是“0123456789+-*/.^)”中的一個 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一個運算符之間沒有“.”的話,整數位第一個隻能是“123456789”, // 且後一位隻能是“0123456789+-*/.!^)”中的一個。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4.如果0到上一個運算符之間有一個“.”的話,則後一位隻能是“0123456789+-*/.^)”中的一個 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (is > 1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //7."123456789"後面隻能是“0123456789+-*/.!^)”中的一個 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //8."("後面隻能是“0123456789locstg()ep”中的一個 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //9.")"後面隻能是“+-*/!^)”中的一個 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //10.最後一位字符隻能是“0123456789!)ep”中的一個 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //12.不能有多個“.” if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //13."ep"後面隻能是“+-*/^)”中的一個 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } } }
4.計算後綴表達式
代碼如下:
public double math(List<String> list2) {//通過後綴表達式進行計算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除數不能為0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("階乘必須為自然數"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能為+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//進行計算,並且判斷括號是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判斷括號是否成對 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } }
5.事件監聽器
因為設置瞭33個按鈕,所以每個按鈕都要設計事件監聽器,我設置的目的是把點中的按鈕的值寫入到文本框中輸出,並且把它代表的數值或者操作符存放到字符串中,以便於進行中綴轉後綴和運算。
代碼如下:
public void buttonLister(){//事件監聽器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); }
完整代碼
直接拷貝到Java中就可以用:
一個類走完程序。
main函數中還可以設置面板風格。有
- Niumbus風格
- Windows風格
- Windows經典風格
三種風格可以自定義選擇,我個人覺得Niumbus風格比較好看。選擇哪一個就釋放哪一個,把另外兩個註釋掉就可以瞭。
package com.lmdxyt; import javax.swing.*; import javax.swing.plaf.FontUIResource; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class JSQ { private JFrame jFrame = new JFrame("計算器"); private FontUIResource f = new FontUIResource("隸書", 1, 20); private FontUIResource f1 = new FontUIResource("楷書", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("輸入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy); jTextField1.setFont(f1); jTextField1.setHorizontalAlignment(JLabel.RIGHT); jTextField1.setEditable(false); jTextField1.setBackground(Color.WHITE); jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按鈕添加到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null); } private List<String> zhongZhui(String str) {//把輸入的字符串轉換成中綴表達式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接添加至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是數字,判斷多位數的情況 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中綴表達式轉換稱後綴表達式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符棧不為空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入棧 fuZhan.push(list.get(i)); } else {//出棧 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判斷是否為操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判斷是否為操作數 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判斷操作符的優先級 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; } public void buttonLister(){//事件監聽器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel); jFrame.setSize(614, 437); jFrame.setResizable(false); jFrame.setLocationRelativeTo(null); jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true); } public void estimate(){//判斷輸入是否錯誤 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //當隻有一位字符時,隻能是“0123456789ep”中的一個 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一個字符隻能為"losctg(0123456789ep"中的一個 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.“+-*/”後面隻能是"0123456789losctg(ep"中的一個 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //3."."後面隻能是“0123456789”中的一個 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4."!"後面隻能是“+-*/^)”中的一個 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //5."losctg"後面隻能是“0123456789(ep”中的一個 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //6."0"的判斷操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.當0的上一個字符不為"0123456789."時,後一位隻能是“+-*/.!^)”中的一個 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.如果0的上一位為“.”,則後一位隻能是“0123456789+-*/.^)”中的一個 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一個運算符之間沒有“.”的話,整數位第一個隻能是“123456789”, // 且後一位隻能是“0123456789+-*/.!^)”中的一個。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4.如果0到上一個運算符之間有一個“.”的話,則後一位隻能是“0123456789+-*/.^)”中的一個 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (is > 1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //7."123456789"後面隻能是“0123456789+-*/.!^)”中的一個 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //8."("後面隻能是“0123456789locstg()ep”中的一個 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //9.")"後面隻能是“+-*/!^)”中的一個 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //10.最後一位字符隻能是“0123456789!)ep”中的一個 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //12.不能有多個“.” if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //13."ep"後面隻能是“+-*/^)”中的一個 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } } } public double math(List<String> list2) {//通過後綴表達式進行計算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除數不能為0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("階乘必須為自然數"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能為+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//進行計算,並且判斷括號是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判斷括號是否成對 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } } public static void main(String[] args) { /* * 1.在輸入過程中每兩個數值之間必須有運算符,否則報錯. * 例如:錯誤:2ln4(5+8), 2sin2 等 * 正確:2*ln4*(5+8), 2*sin2 * 2.不支持負數,要想得到負數,隻能0-x * 例如:錯誤:-2+3*(-2*6) * 正確:0-2+3*((0-2)+6) * */ new JSQ().init(); //Niumbus風格 try { UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } /*//Windows風格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ /* //Windows經典風格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ } }
總結
到此這篇關於java實現科學計算器的文章就介紹到這瞭,更多相關java科學計算器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!