Java利用棧實現簡易計算器功能
利用棧實現一個簡易計算器(Java實現),供大家參考,具體內容如下
一、思路分析
當我們輸入一個類似于“7*2+100-5+3-4/2”的簡單中綴表達式時,我們的編譯器能夠利用我們所編寫的代碼將這個表達式掃描并計算出其結果
在這個表達式中主要有兩種元素,一種是數字,一種是符號,那么我們就需要創(chuàng)建兩個棧結構存儲數據
- 數棧numStack:存放數
- 符號棧operStack:存放運算符
1、首先我們需要定義一個index(索引),來遍歷我們的表達式
2、如果掃描到一個數字,就直接入數棧
3、如果掃描到一個運算符,那就要分以下幾種情況:
? 3.1、如果當前符號棧為空,就直接入棧
? 3.2、如果符號棧有運算符,就需要進行比較
? 如果當前運算符的優(yōu)先級小于或等于棧中的運算符,就需要從數棧中pop出兩個數,在符號棧中pop出一個符號,進行運算,得到結果,入數棧,然后將當前的操作符入符號棧
? 如果當前運算符的優(yōu)先級大于棧中的運算符,就直接入符號棧
4、當表達式掃描完畢,就順序的從數棧和符號棧中pop出相應的數和符號,并進行計算
5、最后保留在數棧中的那個數字就是運算的結果
二、代碼實現
package com.hsy.stack; public class Calculator { ? ? public static void main(String[] args) { ? ? ? ? //根據前面老師思路,完成表達式的運算 ? ? ? ? String expression = "7*2+100-5+3-4/2";//如何處理多位數的問題? ? ? ? ? //創(chuàng)建兩個棧,數棧,一個符號棧 ? ? ? ? ArrayStack2 numStack = new ArrayStack2(10); ? ? ? ? ArrayStack2 operStack = new ArrayStack2(10); ? ? ? ? //定義需要的相關變量 ? ? ? ? int index = 0;//用于掃描 ? ? ? ? int num1 = 0; ? ? ? ? int num2 = 0; ? ? ? ? int oper = 0; ? ? ? ? int res = 0; ? ? ? ? char ch = ' '; //將每次掃描得到char保存到ch ? ? ? ? String keepNum = ""; //用于拼接 多位數 ? ? ? ? //開始while循環(huán)的掃描expression ? ? ? ? while(true) { ? ? ? ? ? ? //依次得到expression 的每一個字符 ? ? ? ? ? ? ch = expression.substring(index, index+1).charAt(0); ? ? ? ? ? ? //判斷ch是什么,然后做相應的處理 ? ? ? ? ? ? if(operStack.isOper(ch)) {//如果是運算符 ? ? ? ? ? ? ? ? //判斷當前的符號棧是否為空 ? ? ? ? ? ? ? ? if(!operStack.isEmpty()) { ? ? ? ? ? ? ? ? ? ? //如果符號棧有操作符,就進行比較,如果當前的操作符的優(yōu)先級小于或者等于棧中的操作符,就需要從數棧中pop出兩個數, ? ? ? ? ? ? ? ? ? ? //在從符號棧中pop出一個符號,進行運算,將得到結果,入數棧,然后將當前的操作符入符號棧 ? ? ? ? ? ? ? ? ? ? if(operStack.priority(ch) <= operStack.priority(operStack.peek())) { ? ? ? ? ? ? ? ? ? ? ? ? num1 = numStack.pop(); ? ? ? ? ? ? ? ? ? ? ? ? num2 = numStack.pop(); ? ? ? ? ? ? ? ? ? ? ? ? oper = operStack.pop(); ? ? ? ? ? ? ? ? ? ? ? ? res = numStack.cal(num1, num2, oper); ? ? ? ? ? ? ? ? ? ? ? ? //把運算的結果如數棧 ? ? ? ? ? ? ? ? ? ? ? ? numStack.push(res); ? ? ? ? ? ? ? ? ? ? ? ? //然后將當前的操作符入符號棧 ? ? ? ? ? ? ? ? ? ? ? ? operStack.push(ch); ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? //如果當前的操作符的優(yōu)先級大于棧中的操作符, 就直接入符號棧. ? ? ? ? ? ? ? ? ? ? ? ? operStack.push(ch); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? }else { ? ? ? ? ? ? ? ? ? ? //如果為空直接入符號棧.. ? ? ? ? ? ? ? ? ? ? operStack.push(ch); // 1 + 3 ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else { //如果是數,則直接入數棧 ? ? ? ? ? ? ? ? //numStack.push(ch - 48); //? "1+3" '1' => 1 ? ? ? ? ? ? ? ? //分析思路 ? ? ? ? ? ? ? ? //1. 當處理多位數時,不能發(fā)現是一個數就立即入棧,因為他可能是多位數 ? ? ? ? ? ? ? ? //2. 在處理數,需要向expression的表達式的index 后再看一位,如果是數就進行掃描,如果是符號才入棧 ? ? ? ? ? ? ? ? //3. 因此我們需要定義一個變量 字符串,用于拼接 ? ? ? ? ? ? ? ? //處理多位數 ? ? ? ? ? ? ? ? keepNum += ch; ? ? ? ? ? ? ? ? //如果ch已經是expression的最后一位,就直接入棧 ? ? ? ? ? ? ? ? if (index == expression.length() - 1) { ? ? ? ? ? ? ? ? ? ? numStack.push(Integer.parseInt(keepNum)); ? ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ? ? //判斷下一個字符是不是數字,如果是數字,就繼續(xù)掃描,如果是運算符,則入棧 ? ? ? ? ? ? ? ? ? ? //注意是看后一位,不是index++ ? ? ? ? ? ? ? ? ? ? if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))) { ? ? ? ? ? ? ? ? ? ? ? ? //如果后一位是運算符,則入棧 keepNum = "1" 或者 "123" ? ? ? ? ? ? ? ? ? ? ? ? numStack.push(Integer.parseInt(keepNum)); ? ? ? ? ? ? ? ? ? ? ? ? //重要的!!!!!!, keepNum清空 ? ? ? ? ? ? ? ? ? ? ? ? keepNum = ""; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? //讓index + 1, 并判斷是否掃描到expression最后. ? ? ? ? ? ? index++; ? ? ? ? ? ? if (index >= expression.length()) { ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? //當表達式掃描完畢,就順序的從 數棧和符號棧中pop出相應的數和符號,并運行. ? ? ? ? while(true) { ? ? ? ? ? ? //如果符號棧為空,則計算到最后的結果, 數棧中只有一個數字【結果】 ? ? ? ? ? ? if(operStack.isEmpty()) { ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? num1 = numStack.pop(); ? ? ? ? ? ? num2 = numStack.pop(); ? ? ? ? ? ? oper = operStack.pop(); ? ? ? ? ? ? res = numStack.cal(num1, num2, oper); ? ? ? ? ? ? numStack.push(res);//入棧 ? ? ? ? } ? ? ? ? //將數棧的最后數,pop出,就是結果 ? ? ? ? int res2 = numStack.pop(); ? ? ? ? System.out.printf("表達式 %s = %d", expression, res2); ? ? } } //先創(chuàng)建一個棧,直接使用前面創(chuàng)建好 //定義一個 ArrayStack2 表示棧, 需要擴展功能 class ArrayStack2 { ? ? private int maxSize; // 棧的大小 ? ? private int[] stack; // 數組,數組模擬棧,數據就放在該數組 ? ? private int top = -1;// top表示棧頂,初始化為-1 ? ? //構造器 ? ? public ArrayStack2(int maxSize) { ? ? ? ? this.maxSize = maxSize; ? ? ? ? stack = new int[this.maxSize]; ? ? } ? ? //增加一個方法,可以返回當前棧頂的值, 但是不是真正的pop ? ? public int peek() { ? ? ? ? return stack[top]; ? ? } ? ? //棧滿 ? ? public boolean isFull() { ? ? ? ? return top == maxSize - 1; ? ? } ? ? //棧空 ? ? public boolean isEmpty() { ? ? ? ? return top == -1; ? ? } ? ? //入棧-push ? ? public void push(int value) { ? ? ? ? //先判斷棧是否滿 ? ? ? ? if(isFull()) { ? ? ? ? ? ? System.out.println("棧滿"); ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? top++; ? ? ? ? stack[top] = value; ? ? } ? ? //出棧-pop, 將棧頂的數據返回 ? ? public int pop() { ? ? ? ? //先判斷棧是否空 ? ? ? ? if(isEmpty()) { ? ? ? ? ? ? //拋出異常 ? ? ? ? ? ? throw new RuntimeException("???,沒有數據~"); ? ? ? ? } ? ? ? ? int value = stack[top]; ? ? ? ? top--; ? ? ? ? return value; ? ? } ? ? //顯示棧的情況[遍歷棧], 遍歷時,需要從棧頂開始顯示數據 ? ? public void list() { ? ? ? ? if(isEmpty()) { ? ? ? ? ? ? System.out.println("棧空,沒有數據~~"); ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? //需要從棧頂開始顯示數據 ? ? ? ? for(int i = top; i >= 0 ; i--) { ? ? ? ? ? ? System.out.printf("stack[%d]=%d\n", i, stack[i]); ? ? ? ? } ? ? } ? ? //返回運算符的優(yōu)先級,優(yōu)先級是程序員來確定, 優(yōu)先級使用數字表示 ? ? //數字越大,則優(yōu)先級就越高. ? ? public int priority(int oper) { ? ? ? ? if(oper == '*' || oper == '/'){ ? ? ? ? ? ? return 1; ? ? ? ? } else if (oper == '+' || oper == '-') { ? ? ? ? ? ? return 0; ? ? ? ? } else { ? ? ? ? ? ? return -1; // 假定目前的表達式只有 +, - , * , / ? ? ? ? } ? ? } ? ? //判斷是不是一個運算符 ? ? public boolean isOper(char val) { ? ? ? ? return val == '+' || val == '-' || val == '*' || val == '/'; ? ? } ? ? //計算方法 ? ? public int cal(int num1, int num2, int oper) { ? ? ? ? int res = 0; // res 用于存放計算的結果 ? ? ? ? switch (oper) { ? ? ? ? ? ? case '+': ? ? ? ? ? ? ? ? res = num1 + num2; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case '-': ? ? ? ? ? ? ? ? res = num2 - num1;// 注意順序 ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case '*': ? ? ? ? ? ? ? ? res = num1 * num2; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case '/': ? ? ? ? ? ? ? ? res = num2 / num1; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? default: ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? return res; ? ? } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法(報數據重復Duplicate entry的
在開發(fā)中,我們經常會有邏輯刪除和唯一索引同時使用的情況,但當使用mybatis plus時,如果同時使用邏輯刪除和唯一索引,會報數據重復Duplicate entry的問題,如何解決這個問題呢,小編給大家分享Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法,一起看看吧2023-11-11SpringBoot如何手寫一個starter并使用這個starter詳解
starter是SpringBoot中的一個新發(fā)明,它有效的降低了項目開發(fā)過程的復雜程度,對于簡化開發(fā)操作有著非常好的效果,下面這篇文章主要給大家介紹了關于SpringBoot如何手寫一個starter并使用這個starter的相關資料,需要的朋友可以參考下2022-12-12windows環(huán)境下java開發(fā)工具maven的安裝教程圖解
Maven是一個項目管理和綜合工具。Maven提供了開發(fā)人員構建一個完整的生命周期框架。這篇文章主要介紹了windows環(huán)境下java開發(fā)工具maven的安裝,非常不錯對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07SpringBoot如何使用p6spy監(jiān)控數據庫
這篇文章主要介紹了SpringBoot如何使用p6spy監(jiān)控數據庫問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01Java使用PreparedStatement接口及ResultSet結果集的方法示例
這篇文章主要介紹了Java使用PreparedStatement接口及ResultSet結果集的方法,結合實例形式分析了PreparedStatement接口及ResultSet結果集的相關使用方法與操作注意事項,需要的朋友可以參考下2018-07-07