用Java實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
本項(xiàng)目為大家分享了Java實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能的具體代碼,供大家參考,具體內(nèi)容如下
一 項(xiàng)目說(shuō)明實(shí)訓(xùn)目的:掌握 Java GUI 開(kāi)發(fā)中的布局管理和事件處理機(jī)制。
實(shí)訓(xùn)要求:
(1)要使用 java 的 GUI 設(shè)計(jì)出計(jì)算器界面。
(2)通過(guò)界面按鈕,可以實(shí)現(xiàn)整數(shù)或浮點(diǎn)數(shù)的四則運(yùn)算,并能將結(jié)果顯示在界面中。
(3)計(jì)算可以有小數(shù)點(diǎn),和正負(fù)整數(shù)的計(jì)算。
(4)要有清零功能。
二、類(lèi)設(shè)計(jì)中綴表達(dá)式的計(jì)算solution(String str)用來(lái)中算后綴表達(dá)式的值,并將結(jié)果返回。準(zhǔn)備一個(gè)數(shù)字棧,一個(gè)運(yùn)算符棧。大致的思路就是遇到,數(shù)字直接入數(shù)字棧,運(yùn)算符看優(yōu)先級(jí)進(jìn)行處理,將要入運(yùn)算符棧的運(yùn)算符與棧頂?shù)倪\(yùn)算符進(jìn)行比較,棧頂運(yùn)算符優(yōu)先級(jí)比較高的話(huà),則把棧頂?shù)倪\(yùn)算符彈并且把數(shù)字棧的兩個(gè)數(shù)字進(jìn)行彈出,進(jìn)行運(yùn)算,并且把結(jié)果再次放到數(shù)字棧中,最后剩下的就是最終結(jié)果。如果運(yùn)算符優(yōu)先級(jí)比運(yùn)算符棧頂?shù)男。瑒t把運(yùn)算符進(jìn)棧,最后把運(yùn)算符都出棧。計(jì)算加減乘除余caculateResult(char optemp, double num1, double num2)通過(guò)傳入的optemp(表達(dá)式符號(hào))參數(shù)。是什么符號(hào)就進(jìn)行什么樣的運(yùn)算判斷符號(hào)的優(yōu)先級(jí)getOperlevel(char c)先乘除后加減,通過(guò)0,1,2對(duì)運(yùn)算符的優(yōu)先級(jí)進(jìn)行標(biāo)記
三 項(xiàng)目實(shí)現(xiàn)設(shè)計(jì)首先先設(shè)計(jì)一個(gè)GUI界面,先設(shè)置一個(gè)JFrame容器,容器中創(chuàng)建兩個(gè)面板和若干按鈕,先把按鈕要顯示的文字存入字符串?dāng)?shù)組,然后依次創(chuàng)建幾個(gè)按鈕。在設(shè)置一個(gè)文本框,用來(lái)接收用戶(hù)輸入的內(nèi)容,centerPanel.setLayout(new GridLayout(4, 4, 12, 16));設(shè)置中間面板的布局為網(wǎng)格布局,并指定該容器的行數(shù)和列數(shù)以及組件之間的水平、垂直間距。centerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));為面板創(chuàng)建一個(gè)框,框的頭部為5像素,左為5像素,底部為5像素,右為5像素寬。再設(shè)置單行文本域的大小,字體,風(fēng)格和字號(hào),然后為各按鈕設(shè)置監(jiān)聽(tīng)器。定義一個(gè)StringBuffer類(lèi),用于保存觸發(fā)產(chǎn)生的內(nèi)容,在用txt.setText(r.toString());方法將內(nèi)容輸出在文本框中,clear按鈕觸發(fā)后,用r.delete(0,r.length());方法清空字符串中的內(nèi)容并將結(jié)果顯示在文本框中,“=”按鈕是把觸發(fā)器觸發(fā)的數(shù)字保存StringBuffer里面,然后用該類(lèi)的toString()方法返回StringBuffer緩沖區(qū)中的字符對(duì)象,用String類(lèi)型的變量接收,該字符串接收到的就是一個(gè)中綴表達(dá)式,創(chuàng)建一個(gè)類(lèi),該類(lèi)用于將輸入的中綴表達(dá)式進(jìn)行計(jì)算,把計(jì)算的結(jié)果返回給“=”按鈕觸發(fā)器中的result變量,把該變量轉(zhuǎn)化為字符串輸出在文本框中。
四 運(yùn)行與測(cè)試首先,我看到這個(gè)題的第一反應(yīng)是這個(gè)界面的布局要用到網(wǎng)格布局,開(kāi)始我是想直接在觸發(fā)器里面實(shí)現(xiàn)相應(yīng)的加減乘除功能的,發(fā)現(xiàn)如果要計(jì)算四則運(yùn)算有點(diǎn)困難,單個(gè)的加減乘除還是挺容易的,后面寫(xiě)了一些代碼后,果斷刪了重寫(xiě),采用了數(shù)據(jù)結(jié)構(gòu)中的中綴表達(dá)式的計(jì)算算法(要用到棧),不過(guò)那個(gè)時(shí)候用的語(yǔ)言是C語(yǔ)言,所以關(guān)于棧的書(shū)寫(xiě)就只能去百度了,之后我知道了棧和他的有關(guān)方法,自己也嘗試這寫(xiě)了一段代碼進(jìn)行了測(cè)試,更加熟練的掌握了棧的用法。
還順便看了一下廣大網(wǎng)友的代碼和算法,發(fā)現(xiàn)都大同小異,我自己也在他們寫(xiě)的算法的基礎(chǔ)上寫(xiě)了一段代碼,新增加了實(shí)現(xiàn)小數(shù)四則運(yùn)算的功能,其中判斷運(yùn)算符的優(yōu)先級(jí)那段代碼直接搬運(yùn)了網(wǎng)上的代碼。
經(jīng)過(guò)測(cè)試,發(fā)現(xiàn)精度有一點(diǎn)問(wèn)題,運(yùn)算的結(jié)果有時(shí)是正確的,有時(shí)是無(wú)限接近正確結(jié)果(小數(shù)點(diǎn)后面的小數(shù)位太多了),還有就是實(shí)現(xiàn)不了負(fù)數(shù)的運(yùn)算,但可以實(shí)現(xiàn)浮點(diǎn)數(shù)的四則運(yùn)算。以我現(xiàn)在的水平,這個(gè)bug暫時(shí)還解決不了。所以就沒(méi)在修改了然后利用對(duì)象的調(diào)用把運(yùn)算結(jié)果輸出在文本框里面。有一段時(shí)間這個(gè)程序的界面老是顯示不出來(lái),控制臺(tái)console那里老是閃一下就滅了,我也非常納悶,之前我還可以顯示出來(lái)的啊,現(xiàn)在怎么就這樣的,百度了很久也沒(méi)找到答案,后面去請(qǐng)教同學(xué),才發(fā)現(xiàn)原來(lái)我的聊天窗口沒(méi)有設(shè)置為可見(jiàn)frame.setVisible(true);。所以一般在設(shè)置容器的時(shí)候,就在他的后面寫(xiě)完他的所有屬性,不要寫(xiě)完運(yùn)行出錯(cuò)了,才發(fā)現(xiàn)沒(méi)有寫(xiě)。`
Calculater:
package com.itcase_eight;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.text.DateFormat;import java.util.Date;/** * @author 羅志剛 * @date 2020/12/16 22:09 */public class Calculater { public static void createAndShowGUI() {Date date=new Date();DateFormat format=DateFormat.getDateInstance(DateFormat.SHORT);// 對(duì)計(jì)算器整體框架的建立startJFrame f = new JFrame('計(jì)算器');// 窗口JPanel centerPanel = new JPanel(); // 中間面板JPanel startPanel=new JPanel();// 初始化功能鍵JButton left=new JButton('(');JLabel data=new JLabel(format.format(date),JLabel.CENTER);data.setFont(new Font('Times New Roman',Font.BOLD,17));JButton clear=new JButton('Clear');JButton right=new JButton(')');String button[] = { '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '.', '0', '=', '+'};JButton but0 = new JButton(button[0]);JButton but1 = new JButton(button[1]);JButton but2 = new JButton(button[2]);JButton but3 = new JButton(button[3]);JButton but4 = new JButton(button[4]);JButton but5 = new JButton(button[5]);JButton but6 = new JButton(button[6]);JButton but7 = new JButton(button[7]);JButton but8 = new JButton(button[8]);JButton but9 = new JButton(button[9]);JButton but10 = new JButton(button[10]);JButton but11 = new JButton(button[11]);JButton but12 = new JButton(button[12]);JButton but13 = new JButton(button[13]);JButton but14 = new JButton(button[14]);JButton but15 = new JButton(button[15]);// 單行輸入文本框JTextField txt = new JTextField();// 使用網(wǎng)格布局方式centerPanel.setLayout(new GridLayout(5, 4, 12, 16)); // 左右上下間隔centerPanel.add(left);centerPanel.add(clear);centerPanel.add(right);centerPanel.add(data);centerPanel.add(but0);centerPanel.add(but1);centerPanel.add(but2);centerPanel.add(but3);centerPanel.add(but4);centerPanel.add(but5);centerPanel.add(but6);centerPanel.add(but7);centerPanel.add(but8);centerPanel.add(but9);centerPanel.add(but10);centerPanel.add(but11);centerPanel.add(but12);centerPanel.add(but13);centerPanel.add(but14);centerPanel.add(but15);centerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));// 設(shè)置容器大小txt.setPreferredSize(new Dimension(465, 40));// 設(shè)置字體,風(fēng)格和字號(hào)txt.setFont(new Font('宋體', Font.PLAIN, 28));f.add(startPanel);f.add(txt, BorderLayout.NORTH); // 將單行文本框添加到窗口的 北部f.add(centerPanel, BorderLayout.SOUTH); // 將中間面板添加到窗口的南部f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 點(diǎn)X關(guān)閉窗口f.setLocation(400, 200); // 初始化時(shí)定位f.setSize(500, 300);// 展示JFrame窗口f.setVisible(true);f.setResizable(false); // 禁止拖曳改變窗口大小f.pack(); // 讓窗口的大小自適應(yīng)// 對(duì)計(jì)算器整體框架的建立end// 為按鈕事件添加自定義監(jiān)聽(tīng)器startStringBuffer r=new StringBuffer();but0.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('7');txt.setText(r.toString()); }});but1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('8');txt.setText(r.toString()); }});but2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('9');txt.setText(r.toString()); }});but4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('4');txt.setText(r.toString()); }});but5.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('5');txt.setText(r.toString()); }});but6.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('6');txt.setText(r.toString()); }});left.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('(');txt.setText(r.toString()); }});right.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append(')');txt.setText(r.toString()); }});but8.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('1');txt.setText(r.toString()); }});but9.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('2');txt.setText(r.toString()); }});but10.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('3');txt.setText(r.toString()); }});but13.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('0');txt.setText(r.toString()); }});but15.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('+');txt.setText(r.toString()); }});but3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('/');txt.setText(r.toString()); }});but7.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('*');txt.setText(r.toString()); }});but12.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('.');txt.setText(r.toString()); }});but11.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('-');txt.setText(r.toString()); }});clear.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.delete(0,r.length()); //清空字符串中的內(nèi)容txt.setText(r.toString()); //將結(jié)果顯示在文本框中 }});but14.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {r.append('=');String str=r.toString();txt.setText('');double result= Computer.solution(str);String string=String.valueOf(result);r.delete(0,r.length());r.append(string);txt.setText(string); }}); } public static void main(String[] args) {SwingUtilities.invokeLater(Calculater::createAndShowGUI); }}
Computer類(lèi):
package com.itcase_eight;import java.util.Stack;/** * @author 羅志剛 * @date 2020/12/16 22:05 */public class Computer { public static double solution(String str) {Stack<Double> numStack = new Stack<>();Stack<Character> signalStack = new Stack<>();int index = 0;// 記錄已經(jīng)執(zhí)行的符號(hào)數(shù)int len = str.length();while (index < len) { char c = str.charAt(index); // 取出這一步的符號(hào) if (c == ’(’) {signalStack.push(c);// 若是左括號(hào)就進(jìn)棧 } // 否則要先判斷優(yōu)先級(jí) else if (c == ’+’ || c == ’-’ || c == ’*’ || c == ’/’) {int currOperLevel = getOperlevel(c);// 當(dāng)前符號(hào)的優(yōu)先級(jí)while (true) { int stackOperLevel = 0;// 棧頂元素的優(yōu)先級(jí) if (!signalStack.isEmpty()) {Object obj = signalStack.peek();stackOperLevel = getOperlevel((char) obj); } // 若當(dāng)前元素優(yōu)先級(jí)大于棧頂元素的優(yōu)先級(jí)則入棧 if (currOperLevel > stackOperLevel) {signalStack.push(c);break;// 直到讓比自己優(yōu)先級(jí)高的符號(hào)都出棧運(yùn)算了再把自己進(jìn)棧 } else {// 不能入棧就進(jìn)行計(jì)算try { char optemp = ’0’; double num1 = 0; double num2 = 0; if (!signalStack.isEmpty()) {optemp = (char) signalStack.pop();// 取出優(yōu)先級(jí)大的那個(gè)符號(hào) } if (!numStack.isEmpty()) {num1 = (double) numStack.pop();num2 = (double) numStack.pop();// 取出數(shù)據(jù)棧中的兩個(gè)數(shù) } numStack.push(caculateResult(optemp, num2, num1));// 將算出來(lái)的結(jié)果數(shù)據(jù)再次進(jìn)入數(shù)據(jù)棧} catch (Exception e) { // TODO: handle exception e.printStackTrace();} }} } else if (c == ’)’) {// 右括號(hào)就返回棧頂元素,右括號(hào)是不進(jìn)棧的while (true) { char theop = (char) signalStack.pop(); if (theop == ’(’) {break; } else {try { double num1 = (double) numStack.pop(); double num2 = (double) numStack.pop(); numStack.push(caculateResult(theop, num2, num1));// 運(yùn)算括號(hào)內(nèi)的內(nèi)容} catch (Exception e) { e.printStackTrace();} }} } else if (c >= ’0’ && c <= ’9’) {int tempIndex = index + 1;while (tempIndex < len) { char temp = str.charAt(tempIndex);// 取字符串中處于當(dāng)前字符的下一位 if ((temp >= ’0’ && temp <= ’9’) || temp == ’.’) {tempIndex++;// 若為數(shù)字則繼續(xù)向后取 } else {break;// 證明數(shù)字去完 }}String numstr = str.substring(index, tempIndex);// 截取這個(gè)字符串則為兩個(gè)符號(hào)之間的數(shù)字try { double numnum = Double.parseDouble(numstr);// 將數(shù)字轉(zhuǎn)換成整型便于運(yùn)算 numStack.push(numnum); index = tempIndex - 1;} catch (Exception e) { e.printStackTrace();} } index++;}// 檢查符號(hào)棧是否為空while (true) { Object obj = null; if (signalStack.isEmpty() == false) {obj = signalStack.pop(); } if (obj == null) {break;// 為空證明運(yùn)算已結(jié)束 } else {// 不為空就出棧運(yùn)算char opterTemp = (char) obj;double num1 = (double) numStack.pop();double num2 = (double) numStack.pop();numStack.push(caculateResult(opterTemp, num2, num1)); }}double result = 0;try { result = (double) numStack.pop();} catch (Exception e) { // TODO: handle exception e.printStackTrace();}return result; } //計(jì)算加減乘除余 private static Double caculateResult(char optemp, double num1, double num2) {switch (optemp) { case ’+’:return num1 + num2; case ’-’:return num1 - num2; case ’*’:return num1 * num2; case ’/’:return num1 / num2;}return 0.0; } //返回符號(hào)優(yōu)先級(jí) private static int getOperlevel(char c) {switch (c) { case ’(’:return 0; case ’+’: case ’-’:return 1; case ’*’: case ’/’:return 2; default:return 0;} }}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. Python獲取抖音關(guān)注列表封號(hào)賬號(hào)的實(shí)現(xiàn)代碼2. Warning: require(): open_basedir restriction in effect,目錄配置open_basedir報(bào)錯(cuò)問(wèn)題分析3. php網(wǎng)絡(luò)安全中命令執(zhí)行漏洞的產(chǎn)生及本質(zhì)探究4. 解決Python 進(jìn)程池Pool中一些坑5. php測(cè)試程序運(yùn)行速度和頁(yè)面執(zhí)行速度的代碼6. Python如何讀寫(xiě)CSV文件7. 三個(gè)不常見(jiàn)的 HTML5 實(shí)用新特性簡(jiǎn)介8. ajax請(qǐng)求添加自定義header參數(shù)代碼9. python利用os模塊編寫(xiě)文件復(fù)制功能——copy()函數(shù)用法10. 無(wú)線(xiàn)標(biāo)記語(yǔ)言(WML)基礎(chǔ)之WMLScript 基礎(chǔ)第1/2頁(yè)
