1. 程式人生 > >Android簡易計算器(四)—— 完整邏輯程式碼

Android簡易計算器(四)—— 完整邏輯程式碼

  最近在學安卓的相關知識,第一個demo做了一個簡易計算器,功能仿手機上自帶的計算器,沒有加括號,簡單的四則運算,支援長表示式運算。此篇貼出本次簡易計算器完整邏輯程式碼。

程式碼如下:

package com.example.zwkkkk1.caculator1;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import java.math.BigDecimal;
import
java.util.Stack; import java.util.regex.Pattern; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static String TAG = "CACULATOR"; TextView txt_result, txt_edit; boolean isOperateDown = false;//運算子是否已經按過一次,預設沒有按過 false boolean isDotDown = false
;//. 是否已經按過一次,預設沒有按過 false @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt_edit = (TextView)findViewById(R.id.txt_edit); txt_result = (TextView)findViewById(R.id.txt_result); findViewById(R.id.btn_0).setOnClickListener(this
); findViewById(R.id.btn_1).setOnClickListener(this); findViewById(R.id.btn_2).setOnClickListener(this); findViewById(R.id.btn_3).setOnClickListener(this); findViewById(R.id.btn_4).setOnClickListener(this); findViewById(R.id.btn_5).setOnClickListener(this); findViewById(R.id.btn_6).setOnClickListener(this); findViewById(R.id.btn_7).setOnClickListener(this); findViewById(R.id.btn_8).setOnClickListener(this); findViewById(R.id.btn_9).setOnClickListener(this); findViewById(R.id.btn_divide).setOnClickListener(this); findViewById(R.id.btn_multi).setOnClickListener(this); findViewById(R.id.btn_plus).setOnClickListener(this); findViewById(R.id.btn_sub).setOnClickListener(this); findViewById(R.id.btn_equal).setOnClickListener(this); findViewById(R.id.btn_clear).setOnClickListener(this); findViewById(R.id.btn_back).setOnClickListener(this); findViewById(R.id.btn_equal).setOnClickListener(this); findViewById(R.id.btn_dot).setOnClickListener(this); } public void onClick(View v) { switch (v.getId()) { case R.id.btn_0: num_down("0");break; case R.id.btn_1: num_down("1");break; case R.id.btn_2: num_down("2");break; case R.id.btn_3: num_down("3");break; case R.id.btn_4: num_down("4");break; case R.id.btn_5: num_down("5");break; case R.id.btn_6: num_down("6");break; case R.id.btn_7: num_down("7");break; case R.id.btn_8: num_down("8");break; case R.id.btn_9: num_down("9");break; case R.id.btn_plus: operator_down("+");break; case R.id.btn_sub: operator_down("-");break; case R.id.btn_divide: operator_down("÷");break; case R.id.btn_multi: operator_down("×");break; case R.id.btn_clear: isDotDown = false; isOperateDown = false; txt_edit.setText("0"); txt_result.setText(""); break; case R.id.btn_back: { String strEdit = txt_edit.getText().toString(); int length = strEdit.length(); if (Pattern.matches("^=[0-9].*", strEdit)) { txt_edit.setText("0"); txt_result.setText(""); } else { if (length > 0) { String word = strEdit.substring(length - 1, length); if(word.equals(".")) isDotDown = false; if(word.equals("+") || word.equals("-") || word.equals("×") || word.equals("÷")) isOperateDown = false; txt_edit.setText(strEdit.substring(0, length - 1)); } } break; } case R.id.btn_dot: { String strEdit = txt_edit.getText().toString(); if (!isDotDown) { isDotDown = true; if(Pattern.matches("^=[0-9].*", strEdit)) strEdit = "0"; txt_edit.setText(strEdit + "."); } break; } case R.id.btn_equal: equal();break; } } //按下數字函式 private void num_down(String num) { String strEdit = txt_edit.getText().toString(); isOperateDown = false; if (strEdit.equals("0") || Pattern.matches("^=[0-9].*", strEdit)) { txt_edit.setText(num); txt_result.setText(""); } else { txt_edit.setText(strEdit + num); } } // 按下運算子函式 private void operator_down(String operator) { if(!isOperateDown) { String strEdit = txt_edit.getText().toString(); isOperateDown = true; isDotDown = false; if(Pattern.matches("^=[0-9].*", strEdit)) strEdit = strEdit.substring(1, strEdit.length()); txt_edit.setText(strEdit + operator); } } private void equal() { String strEdit = txt_edit.getText().toString(); int length = strEdit.length(); if(!Pattern.matches("^=[0-9].*", strEdit)) { txt_result.setText(strEdit); if(Pattern.matches(".*[\\+\\-\\×\\÷\\.]$", strEdit)) { strEdit = strEdit.substring(0, length - 1); } String postfixExp = getPostfixExp(strEdit); txt_edit.setText("=" + calPostfix(postfixExp)); } } //將中綴表示式轉換為字尾表示式 private String getPostfixExp(String str) { String postfix = ""; String numString = ""; //因數字 不止一位需要String儲存 Stack numStack = new Stack(); Stack opStack = new Stack(); for(int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if(Character.isDigit(ch) || ch == '.') { //判定ch 是否是數字 或者是 . numString += String.valueOf(ch); //將數字和 .放入numString,等待下一個運算子 } else { //ch為運算子時 if(numString.length() > 0) { numStack.push(numString);//將此運算子前數字壓入數字棧 numString = ""; //壓入棧後,初始化 numString } opPush(opStack, numStack, ch); } } //最後判定numString是否為空,因為最後一個可能是數字,沒有運算子進行判定 if(numString.length() > 0) numStack.push(numString); //檢測完後,將運算子棧中轉入到數字棧中 while(!opStack.empty()) { numStack.push(opStack.pop()); } //將數字棧打印出來得到字尾表示式 //此處需要將字串逆序,才得到字尾表示式,但是有小數點的存在,不能直接用 reverse 的逆序函式 //通過兩個棧的先進後出特點,得到棧的逆序 while(!numStack.empty()) { opStack.push(numStack.pop()); } while(!opStack.empty()) { postfix = postfix + String.valueOf(opStack.pop()) + " "; } return postfix; } //計算字尾表示式 private String calPostfix(String str) { String result = ""; Stack numStack = new Stack(); for(int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if(ch == ' ') { //運算子時 if(result.length() > 0 && (result.equals("+") || result.equals("-") || result.equals("×") || result.equals("÷"))) { double num = 0; double secondNum = Double.parseDouble(String.valueOf(numStack.pop())); double firstNum = Double.parseDouble(String.valueOf(numStack.pop())); switch (result) { case "+": num = firstNum + secondNum;break; case "-": num = firstNum - secondNum;break; case "×": num = firstNum * secondNum;break; case "÷": num = firstNum / secondNum;break; } numStack.push(num); } else if(result.length() > 0) { numStack.push(result); } result = ""; } else { result += String.valueOf(ch); } } return BigDecimal.valueOf(Double.valueOf(String.valueOf(numStack.pop()))).stripTrailingZeros().toPlainString(); } //獲取運算子權重 private int getOpWeight(char ch) { // + - 權重為1 if(ch == '+' || ch == '-') return 1; //× ÷ 權重為2 if(ch == '×' || ch == '÷') return 4; return -1; } //將運算子壓入棧 private void opPush(Stack opStack, Stack numStack, char ch) { if(canOpPush(opStack, ch)) { //判定能否將運算子壓入棧內 opStack.push(ch); //true則壓入棧內 } else { //false(即 待壓入運算子優先順序 <= 棧頂運算子優先順序) //將棧頂運算子取出壓入數字棧 numStack.push(String.valueOf(opStack.pop())); //此處需要遞迴判定,彈出所有優先順序 >= 該運算子的棧頂元素 opPush(opStack, numStack, ch); } } //判定運算子能否壓入運算子棧 private Boolean canOpPush(Stack opStack, char ch) { //當運算子棧為空時,返回true;或當待壓入運算子權重大於棧頂權重,返回true if(opStack.empty() || (getOpWeight(ch) > getOpWeight(String.valueOf(opStack.peek()).charAt(0)))) return true; return false; //其他情況返回false } }

相關推薦

Android簡易計算器—— 完整邏輯程式碼

  最近在學安卓的相關知識,第一個demo做了一個簡易計算器,功能仿手機上自帶的計算器,沒有加括號,簡單的四則運算,支援長表示式運算。此篇貼出本次簡易計算器完整邏輯程式碼。 程式碼如下: package com.example.zwkkkk1.cacul

Android MVP系列完整MVC

今天這篇文章主要分為兩大部分: 一、為上一章的MVC賦予靈動的生命; 二、指出MVC的不足和引出MVP的優點; 題外話 可能有人會說,你寫個MVP,為啥用了前面三篇(Android MVP系列(一)、Android MVP系列(二)之MVC結構、Andr

Android Camera2 拍照——對焦模式

ask als size com ontouch eating fault tdi release 原文:Android Camera2 拍照(四)——對焦模式 本

Android SurfaceFlinger服務 ----- 消息機制MessageQueue

events on() inpu str lB 取消 onf CA andro SurfaceFlinger有著自己的消息隊列MessageQueue,用來處理顯示相關的消息,比如Vsync消息。 相關文件: frameworks/native/services/surf

Android 開發:Button圓角實現

本節學習button的圓角實現: 利用上節登入button示例: 1.效果對比: <Button android:layout_width="match_parent" android:layout_height="45dp

智慧語音計算器

最後說訊飛的語音引擎部分,這部分的實現邏輯可以參考官方給的demo,一步一步來就行。 #ifndef CALCULATORASR_H #define CALCULATORASR_H #include <stdio.h> #include <string.h> #include

Android入門筆記

 四、fragment argument 和 頁面資料更新 4.1 為什麼要使用 fragment argument        當 fragment 和 activity 間的資料進行傳遞時,如果只是簡單的使用 intent 的 extra 來進行傳遞資訊,不僅破

Ocelot簡易教程之請求聚合以及服務發現

上篇文章給大家講解了Ocelot的一些特性並對路由進行了詳細的介紹,今天呢就大家一起來學習下Ocelot的請求聚合以及服務發現功能。希望能對大家有所幫助。 請求聚合 Ocelot允許你宣告聚合路由,這樣你可以把多個正常的ReRoutes打包並對映到一個物件來對客戶端的請求進行響應。比如,你請求訂單資訊,訂單

Android進階:Activity啟動過程(最詳細&最簡單)

1.前言 最近一直在看 《Android進階解密》 的一本書,這本書編寫邏輯、流程都非常好,而且很容易看懂,非常推薦大家去看看(沒有收廣告費,單純覺得作者寫的很好)。 上一篇簡單的介紹了Android進階(三):Application啟動過程(最詳細&最簡單)

Android開發筆記字串格式化

字串的格式化 博主原來是搞C的,C裡面有sprintf來格式化字串,後來轉到java變傻了,拼接String只會用n個“+”,要麼就是用StringBuilder的append方法,但要是遇上把數字格式化的情況(比如左補0等等),就只能傻乎乎的if else判斷該補幾個0。

床頭筆記之Android開發學習

新建HelloWorld工程專案目錄說明: 工程目錄: 按著下圖順序講解 HelloWorld: 專案名 src: 自己編寫的程式存放處 gen: 系統自動生成的檔案R.java(和res資原始檔關聯,為其子檔案drawable下每個圖片及values下的鍵值

Android產品研發-->減小Apk大小

隨著移動技術的深入發展,各種炫酷效果的更新,在我們追求UI與UE的同時一個不如忽視的問題逐漸暴露出來,那就是apk檔案越來越大,可能有的童鞋會說現在都是wifi環境,apk檔案增大幾M不是什麼大不了的問題,這其實也是有一定道理的,但是作為開發人員的我們這絕不

Android Firebase接入-- AdMob廣告

AdMob廣告可以幫助app實現盈利。一、配置Android應用並下載google-service.json檔案:二、新增AdMob依賴:implementation 'com.google.firebase:firebase-ads:15.0.0'初始化AdMob,推薦在A

Android Multimedia實戰MediaProjection實現截圖,與MediaMuxer實現錄屏為MP4,Gif格式

MediaProjection可以用來捕捉螢幕,具體來說可以擷取當前螢幕和錄製螢幕視訊 (5.0以上) 先總結下系統是如何實現組合鍵截圖的: 都應該知道Android原始碼中對按鍵的捕獲位於檔案PhoneWindowManager.java中 當滿足按鍵

Android動畫篇:最終效果篇CircleProgressSuperBar

前言 今天終於有時間把最後的成果分享給大家了,為了提高一下部落格的逼格,我也找了一個專門做原型、導圖的線上網站:processon(www.processon.com),這個工具真的很棒,也很方便,這裡給他點個贊。 CircleProgressSuperBa

我所理解的Android模組化——常見問題和注意事項

   關於Android模組化,前面已經寫了三篇文章,沒有了解的大家可以先去看一下,附上鍊接地址:   下面主要來說一下Android模組化過程中的常見問題和注意事項: 注意事項   記得在一篇技術部落格中看到微信Tinker的開發人員說過一句話

Android原始碼編譯系統原始碼目錄

Android 8.0之後原始碼目錄有所改變 Android平臺四層架構對應原始碼中的目錄: 第一層:應用程式層(applications)對應根目錄下packages/apps 第二層:應用程式框架層(application framework)對應根目錄下的f

Android學習筆記--RecyclerView擴充套件下拉重新整理與左滑刪除

今天在使用QQ的時候就想到製作一個訊息列表的類似效果,可以實現下拉重新整理和左滑刪除效果,於是就抽空試了試。先上效果圖。 這是正在重新整理的時候。然後就會增添一個item(那個重新整理的圈是會轉的然後還可以變顏色我不會截動圖)。見下圖。 Recycl

Android學習筆記之碎片化Fragment實現仿人人客戶端的側邊欄

    其實一種好的UI佈局,可以使使用者感到更加的親切與方便。最近非常流行的莫過於側邊欄了,其實我也做過很多側邊欄的應用,但是那些側邊欄的使用我都不是很滿意,現在重新整理,重新寫了一個相對來說我比較滿意的側邊欄,其中運用的就是android3.0版本之後新加的Fragme

Android學習路線構建一個簡單的UI

Android應用的圖形化使用者介面的構建使用的是View 和  物件的層次巢狀。 View 物件通常是UI部件,例如 buttons 或者 text fields ,而  是用來定義它的子佈局如何排布的容器,它通常是不可見的,例如一個網格或者一個垂直的列表。 And