安卓作業----慕課移動互聯網作業7使用逆波蘭式實現處理加減乘除複合運算的計算器

這是中國大學慕課移動終端應用開發的網課作業7,我會持續更新我的作業,如果有需要關注一下吧

說明

1.本計算器利用逆波蘭式能實現加減乘除複合運算
2.第一個數字輸入小數點能自動補全爲 0.
3.能檢測重複輸入小數點情況
4.能檢測式子語法正確情況

如果發現bug,或者有優化方案,可評論或私信聯繫我

博客中用到的數據結構鏈棧和鏈隊,在棧的java實現隊的java實現這兩篇博文中。

界面展示

在這裏插入圖片描述

代碼部分

佈局文件 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:shrinkColumns="*"
    android:stretchColumns="*"
    android:background="@color/blue">

    <TableRow>

        <EditText
            android:id="@+id/edit_show"
            android:layout_height="100dp"
            android:layout_span="4"
            android:background="@color/white"
            android:gravity="right"
            android:textSize="40dp"
            android:paddingTop="20dp"
            android:layout_margin="10dp"/>
    </TableRow>

    <TableRow>
        <Button
            android:text="C"
            android:onClick="clean"
            style="@style/symbol"
            android:background="@color/red"
            />
        <Button
            android:text="DEL"
            style="@style/symbol"
            android:onClick="delete"
            android:layout_span="2"
            />
        <Button
            android:id="@+id/division"
            android:text="/"
            android:onClick="addFormula"
            style="@style/symbol"
            />

    </TableRow>

    <TableRow>
        <Button
            android:id="@+id/number7"
            android:text="7"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number8"
            android:text="8"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number9"
            android:text="9"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/multiplication"
            android:text="*"
            android:onClick="addFormula"
            style="@style/symbol"
            />

    </TableRow>

    <TableRow>
        <Button
            android:id="@+id/number4"
            android:text="4"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number5"
            android:text="5"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number6"
            android:text="6"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/add"
            android:text="+"
            android:onClick="addFormula"
            style="@style/symbol"
            />

    </TableRow>

    <TableRow>
        <Button
            android:id="@+id/number1"
            android:text="1"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number2"
            android:text="2"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/number3"
            android:text="3"
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:id="@+id/sub"
            android:text="-"
            android:onClick="addFormula"
            style="@style/symbol"
            />

    </TableRow>

    <TableRow>
        <Button
            android:id="@+id/number0"
            android:text="0"
            android:onClick="addFormula"
            style="@style/number"
            android:layout_span="2"
            />
        <Button
            android:id="@+id/number_point"
            android:text="."
            android:onClick="addFormula"
            style="@style/number"
            />
        <Button
            android:text="="
            android:onClick="equal"
            style="@style/symbol"
            />

    </TableRow>


</TableLayout>
主題邏輯 MainActivity.java
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.example.course8.model.LinkQueue;
import com.example.course8.model.LinkStack;

public class MainActivity extends AppCompatActivity {
    private EditText mEditTextShow; //用於顯示的編輯框
    private String strFormula = "";     //用於記錄算式
    private boolean isFirstChar = true;  //記錄判斷是不是第一個字符
    private String tempNumber = "";//用於記錄一個數字,爲了判斷是否連續輸入小數點
    private boolean newCalc = true;//用於記錄是否是新的一輪計算


    private void init(){
        mEditTextShow = findViewById(R.id.edit_show);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    //執行按到非功能鍵的時候執行的操作
    public void addFormula(View v){
        if (newCalc){//新一輪計算
            cleanCalc();
            newCalc = false;
        }
        String value = "";
        switch(v.getId()){
            case R.id.number0:
                value = "0";
                break;
            case R.id.number1:
                value = "1";
                break;
            case R.id.number2:
                value = "2";
                break;
            case R.id.number3:
                value = "3";
                break;
            case R.id.number4:
                value = "4";
                break;
            case R.id.number5:
                value = "5";
                break;
            case R.id.number6:
                value = "6";
                break;
            case R.id.number7:
                value = "7";
                break;
            case R.id.number8:
                value = "8";
                break;
            case R.id.number9:
                value = "9";
                break;
            case R.id.number_point:
                value = ".";
                break;
            case R.id.sub:
                value = "-";
                break;
            case R.id.add:
                value = "+";
                break;
            case R.id.multiplication:
                value = "*";
                break;
            case R.id.division:
                value = "/";
                break;
        }

        //如果是第一個符號
        if (isFirstChar){
            if (isNumber(value)){//如果是數字
                if (value.equals(".")){ //如果是小數點
                    strFormula = "0.";
                }else {
                    strFormula = value;    //添加進式子
                }
                tempNumber = strFormula;
                isFirstChar = false;

            }else{  //是運算符
                if (value.equals("+")||value.equals("-")){  //加減默認是正負號
                    strFormula = "0"+value;
                    isFirstChar = false;
                }else {//是乘除,不符合
                    Toast.makeText(MainActivity.this,value+"不可放在式子最前端",Toast.LENGTH_SHORT).show();
                }
            }
            mEditTextShow.setText(strFormula);  //顯示在界面上

        }else {//不是第一個字符
            //判斷符不符合規則
            if (isNumber(value)){//如果是數字
                if (value.equals(".")){
                    if (tempNumber.indexOf(".")>-1){//已經有小數點了
                        Toast.makeText(MainActivity.this,"不可重複放置小數點",Toast.LENGTH_SHORT).show();
                    }else if (isOperator(getLastStr(strFormula))){
                        Toast.makeText(MainActivity.this,"運算符後不可放置小數點",Toast.LENGTH_SHORT).show();
                    }else {
                        strFormula += ".";
                        tempNumber += ".";
                    }
                }else { //不是小數點
                    strFormula += value;
                    tempNumber += value;
                }

            }else {//是符號
                if (isOperator(getLastStr(strFormula))){//如果式子最後一個字符是符號
                    Toast.makeText(MainActivity.this,"算術符號不符規則",Toast.LENGTH_SHORT).show();
                }else {
                    strFormula += value;    //增加式子
                    tempNumber="";//重置數字暫存
                }
            }
            //更新ui
            mEditTextShow.setText(strFormula);
        }

    }

    //按到等於鍵
    public void equal(View v) throws Exception {
        if (newCalc){//新一輪計算
            cleanCalc();
            newCalc = false;
        }
        //判斷輸入的式子是否合法
        if (isLegal(strFormula)){
            //獲取式子的中綴表達式的隊列
            LinkQueue infixQueue = getInfixQueue(strFormula);

            //獲取後綴表達式
            LinkQueue suffixQueue = getSuffixQueue(infixQueue);

            //計算
            LinkStack tempStack = new LinkStack();  //中間棧
            int length = suffixQueue.length();
            for(int i = 0;suffixQueue != null && i < length;i++){
                String c = (String) suffixQueue.poll();//從後綴表達式中取出第一個
                if(isOperator(c)){//當爲操作符的時候

                    //取出兩個操作數
                    double d2 = Double.valueOf(tempStack.pop().toString());
                    double d1 = Double.valueOf(tempStack.pop().toString());

                    double d3 = 0;
                    if(c.equals("+")){
                        d3 = d1 + d2;
                    }else if(c.equals("-")){
                        d3 = d1 - d2;
                    }else if(c.equals("*")){
                        d3 = d1 * d2;
                    }else if(c.equals("/")){
                        if (d2==0){
                            Toast.makeText(MainActivity.this,"0不能作爲被除數",Toast.LENGTH_SHORT).show();
                            return;
                        }
                        d3 = d1 / d2;
                    }
                    tempStack.push(d3);
                }else{  //爲操作數時候
                    tempStack.push(c);
                }
            }
            mEditTextShow.setText(""+tempStack.pop());//返回運算結果
            newCalc = true;//新一輪計算標誌
        }
    }
    //將中綴表達式轉換爲逆波蘭式,即返回一個後綴隊列
    public LinkQueue getSuffixQueue(LinkQueue infixQueue) throws Exception {
        LinkQueue suffixQueue = new LinkQueue();
        LinkStack tempStack = new LinkStack();    //中間棧,運算時存儲運算符

        int length = infixQueue.length();//因爲這隊列是動態的,所以只能用固定的長度值
        for(int i = 0;(infixQueue!=null)&&i<length;i++){
            String c = (String)infixQueue.poll();//從中綴表達式中出隊第一個
            if(!c.equals("")){//如果c不是空格
                if(isOperator(c)){//爲運算符
                    if(!tempStack.isEmpty()){//棧非空,取棧頂優先級高的運算符送往後綴表達式
                        String ac = (String) tempStack.pop();
                        while(ac!=null && priority(ac) >= priority(c)){
                            suffixQueue.offer(ac);
                            ac = (String) tempStack.pop();
                        }
                        if(ac!=null){//若最後一次取出的優先級低的操作符,重新壓棧
                            tempStack.push(ac);
                        }
                    }
                    tempStack.push(c);
                }else{//爲操作數,將其添加到後綴表達式的隊列末尾,裏面有-1
                    suffixQueue.offer(c);
                }
            }
        }
        while(!tempStack.isEmpty()){//棧中剩餘的所有操作符挨個進入後綴表達式
            suffixQueue.offer(tempStack.pop());
        }
        return suffixQueue;
    }

    //判斷運算法的優先級
    public int priority(String c){
        if(c.equals("*")||c.equals("/")){
            return 2;
        }else if(c.equals("-")||c.equals("+")){
            return 1;
        }else{
            return 0;
        }
    }

    //將輸入的字符串式子轉換成隊列,運算符單獨爲一個單元,數字爲一個單元
    private LinkQueue getInfixQueue(String value)throws Exception{
        //翻轉字符
        value = new StringBuilder(value).reverse().toString();
        LinkQueue queue = new LinkQueue();
        String numberStr="";
        while (value.length()>0){
            if (isNumber(getLastStr(value))){
                numberStr += getLastStr(value);
                value = deleteLastStr(value);
            }else {
                queue.offer(numberStr);
                numberStr="";
                queue.offer(getLastStr(value));
                value = deleteLastStr(value);
            }
        }
        queue.offer(numberStr);

        return queue;
    }

    //判斷輸入的式子是否合法的方法
    private boolean isLegal(String value){
        if (value.equals("")){  //啥也沒有
            Toast.makeText(MainActivity.this,"無計算內容",Toast.LENGTH_SHORT).show();
            return false;
        }else if (isOperator(getLastStr(value))){   //式子以運算符結尾
            Toast.makeText(MainActivity.this,"算式不允以運算符結尾",Toast.LENGTH_SHORT).show();
            return false;
        }else if (getLastStr(value).equals(".")){
            Toast.makeText(MainActivity.this,"算式不允以小數點結尾",Toast.LENGTH_SHORT).show();
            return false;
        }else {
            return true;
        }
    }


    //按到刪除鍵
    public void delete(View v){
        if (newCalc){//新一輪計算
            cleanCalc();
            newCalc = false;
        }
        if (strFormula.length()>0){
            strFormula = deleteLastStr(strFormula);
            mEditTextShow.setText(strFormula);
            if (strFormula.length()==0){//刪除過後爲0,則執行清除操作
                cleanCalc();
                newCalc = false;
            }
        }else {
            isFirstChar = true;
            Toast.makeText(MainActivity.this,"無內容可後退",Toast.LENGTH_SHORT).show();
        }
    }

    //按到清除鍵
    public void clean(View v){
        cleanCalc();
    }

    //清除計算
    private void cleanCalc(){
        mEditTextShow.setText("");
        strFormula = "";     //用於記錄算式
        isFirstChar = true;  //記錄判斷是不是第一個字符
        tempNumber = "";//用於記錄一個數字,爲了判斷是否連續輸入小數點
        newCalc = true;//用於記錄是否是新的一輪計算
    }

    //判斷是不是數字
    private boolean isNumber(String value){
        return "0123456789.".indexOf(value)>-1;
    }

    //判斷是不是算術符號
    private boolean isOperator(String value){
        return "+-*/".indexOf(value)>-1;
    }

    //獲取一個字符串最後一個字符
    private String getLastStr(String value){
        return value.substring(value.length()-1);
    }

    //獲取一個字符串除了最後一個字符的其他字符
    private String deleteLastStr(String value){
        return value.substring(0,value.length()-1);
    }
}
風格文件 styles.xml
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="number">
        <item name="android:textSize">30dp</item>
        <item name="android:layout_margin">5dp</item>
        <item name="android:background">#fff</item>
        <item name="android:layout_span">1</item>
    </style>

    <style name="symbol">
        <item name="android:textSize">30dp</item>
        <item name="android:layout_margin">5dp</item>
        <item name="android:background">#F8E6AC</item>
        <item name="android:layout_span">1</item>
    </style>

</resources>
顏色文件 colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="white">#F3F3F3</color>
    <color name="blue">#D9F8F8</color>
    <color name="red">#F7BCB7</color>
</resources>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章