【bnuz_ad】安卓计算器--实验6(2021-10-16)

事情的严重性

实验六 第一个小项目

实验目的:

1.掌握布局的使用
2.学习事件处理

实验内容:

编写一个计算器程序,尽量多的实现按键功能
1.用GridLayout布局设计界面,如下图
2.设计按钮事件处理程序,实现计算器功能

在这里插入图片描述

作业提交:
网络教学平台,把项目包打包到一起上传,打包文件名“学号+姓名”,学号在前,姓名在后

在这里插入图片描述

MainActivity.java

package com.lxy.lxy_myapp_sy6;

import androidx.appcompat.app.AppCompatActivity;

import android.view.View.OnClickListener;

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

import com.lxy.lxy_myapp_sy6.myClass.Calculator;
import com.lxy.lxy_myapp_sy6.myClass.MyKuoHao;

import java.net.IDN;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;


/**
 *  推荐测试数据
 */

public class MainActivity extends AppCompatActivity {

    // 文本框
    private EditText textQuestion;  // 显示题目
    private EditText textResult;    //显示答案

    //数字1-9
    private Button num1;
    private Button num2;
    private Button num3;
    private Button num4;
    private Button num5;
    private Button num6;
    private Button num7;
    private Button num8;
    private Button num9;
    private Button num0;

    //运算符
    private Button optPlus;         // +
    private Button optSubtract;     // -
    private Button optMultiply;     // *
    private Button optDivide;       // /
    private Button optRemainder;    // %
    private Button optFraction;     // 1/x
    private Button optEqual;        // =

    //括号
    private Button bntA;    // (
    private Button bntB;    // )

    //小数点
    private Button symbolPoint;  // .

    //大操作
    private Button mCE;         // 清除    清除本次操作 不包括历史记录
    private Button mDE;         // 删除    删除一个符号 【数字+符号】
    private Button mC;          // 清除    全部

    //小操作存储符号
    private Button mClear;      // 清除  存到strList中mIndex数字
    private Button mRead;       // 读取  存到strList中mIndex数字
    private Button mSave;       // 存储  存到strList中
    private Button mPlus;       // m+   strList中下一个数
    private Button mSubtract;   // m-   strList中上一个数


    // 当前存储、操作、定义数据
    private StringBuffer strBufAll = new StringBuffer();    // 记录这一次的全部操作
    private Stack<Integer> stSta = new Stack<>();
    private String nowAns = "0.0";
    private String nowDo = "";
    private int leftKuoNum = 0;  // 记录左括号
    private int rightKuoNum = 0; // 记录右括号

    // 小操作
    private List<String> strListRes = new ArrayList<>();        // 存储全部结果值
    private List<String> strListAll = new ArrayList<>();       // 存储全部操作
    private List<Stack<Integer>> stStaAll = new ArrayList<>(); // 记录每一次的状态
    private int mIndex = 0;        // 记录strList中读取、存储、删除的下标


    //关于栈记录的状态说明
    // 初始 : 0
    // 数字 : 1
    // +—  : 2
    // ( : 3
    // ) :4
    // . : 5

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定文本
        textQuestion = findViewById(R.id.text_question);
        textResult = findViewById(R.id.text_result);

        //设定textQuestion和textResult框不可编辑
        textQuestion.setFocusable(false);
        textQuestion.setFocusableInTouchMode(false);
        textResult.setFocusable(false);
        textResult.setFocusableInTouchMode(false);


        //绑定数字按钮
        num0 = (Button) findViewById(R.id.num_0);
        num1 = (Button) findViewById(R.id.num_1);
        num2 = (Button) findViewById(R.id.num_2);
        num3 = (Button) findViewById(R.id.num_3);
        num4 = (Button) findViewById(R.id.num_4);
        num5 = (Button) findViewById(R.id.num_5);
        num6 = (Button) findViewById(R.id.num_6);
        num7 = (Button) findViewById(R.id.num_7);
        num8 = (Button) findViewById(R.id.num_8);
        num9 = (Button) findViewById(R.id.num_9);

        //绑定小数点
        symbolPoint = (Button) findViewById(R.id.symbol_point);

        //绑定运算符
        optPlus = findViewById(R.id.opr_plus);            // +
        optSubtract = findViewById(R.id.opt_subtract);    // -
        optMultiply = findViewById(R.id.opt_multiply);    // *
        optDivide = findViewById(R.id.opt_divide);        // /
        optRemainder = findViewById(R.id.opt_remainder);  // %
        optFraction = findViewById(R.id.opt_fraction);    // 1/x
        optEqual = findViewById(R.id.opt_equal);          // =

        // 绑定 左右括号
        bntA = findViewById(R.id.bnt_a);
        bntB = findViewById(R.id.bnt_b);

        // 绑定大操作
        mDE = findViewById(R.id.m_de);        // de 删除一个符号【数字+符号】
        mCE = findViewById(R.id.m_ce);        // ce 清除本次操作 不包括历史记录
        mC = findViewById(R.id.m_c);          // c  清除全部

        //绑定小操作存储
        mClear = findViewById(R.id.m_clear);        // mc
        mRead = findViewById(R.id.m_read);          // mr
        mSave = findViewById(R.id.m_save);          // ms
        mPlus = findViewById(R.id.m_plus);          // m+
        mSubtract = findViewById(R.id.m_subtract);  // m-

        //初始化 显示栏
        textQuestion.setText("");
        textResult.setText("0.0");

        stSta.push(0);


        //数字按钮按下后,strBuf写入数字
        num0.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                    textQuestion.setText("");
                    return;
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                if (strBufAll.charAt(strBufAll.length()-1) == '/' || strBufAll.charAt(strBufAll.length()-1) == '%' ){
                    Toast.makeText(MainActivity.this, "除数不能为0", Toast.LENGTH_LONG).show();
                }
                stSta.push(1);
                strBufAll.append("0");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("1");
                textQuestion.setText(strBufAll.toString());

            }
        });
        num2.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("2");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num3.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("3");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num4.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("4");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num5.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("5");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num6.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("6");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num7.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    Toast.makeText(new MainActivity(), "请输入符号", Toast.LENGTH_LONG).show();
                    return;
                }
                stSta.push(1);
                strBufAll.append("7");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num8.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("8");
                textQuestion.setText(strBufAll.toString());
            }
        });
        num9.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                if (stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(1);
                strBufAll.append("9");
                textQuestion.setText(strBufAll.toString());
            }
        });


        // 小数点
        symbolPoint.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() != 1) {
                    myShowToast(stSta.peek());
                    // . 前面不能不是数字
                    return;
                }
                boolean isPoint = false;
                for (int i=strBufAll.length()-1; i>0; i--){
                    if (strBufAll.charAt(i) == '.'){
                        isPoint = true;
                        break;
                    }
                    if (strBufAll.charAt(i)>'9' || strBufAll.charAt(i) < '0'){
                        break;
                    }
                }
                if (!isPoint){
                    strBufAll.append(".");
                    textQuestion.setText(strBufAll.toString());
                    stSta.push(5);
                }
                else{
                    Toast.makeText(MainActivity.this, "数字不能有两个小数点",Toast.LENGTH_LONG).show();
                }
            }
        });


        // 大操作
        // 删除一个字符
        mDE.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() == 0) {
                    myShowToast(stSta.peek());
                    return;
                }
                // 不为空
                strBufAll.deleteCharAt(strBufAll.length() - 1);
                textQuestion.setText(strBufAll.toString());
                stSta.pop();
            }
        });
        // 删除一组字符 123、32、2、+、%
        mCE.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                // 删除当前的这个 不清空存储的
                textResult.setText("0.0");
                textQuestion.setText("");
                strBufAll = new StringBuffer("");
                stSta = new Stack<>();
                stSta.push(0);
                nowAns = "0.0";
                nowDo = "";
                leftKuoNum = 0;
                rightKuoNum = 0;


              
            }
        });

        // 全部清空  包括记录 相当于初始化
        mC.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                strBufAll = new StringBuffer("");
                stSta = new Stack<>();
                textQuestion.setText("");
                textResult.setText("0.0");
                strListRes = new ArrayList<>();
                strListAll = new ArrayList<>();
                stStaAll = new ArrayList<>();
                mIndex = 0;
                leftKuoNum = 0;
                rightKuoNum = 0;
                nowAns = "0.0";
                nowDo = "";
                stSta.push(0);
            }
        });


        //小操作
        // 删除存储中一次操作全过程 以及 结果 以及 栈
        mClear.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (strListAll.size() == 0) {
                    return;
                }
                strBufAll = new StringBuffer("");
                stSta = new Stack<>();
                textResult.setText("0.0");
                textQuestion.setText("");
                strListRes.remove(mIndex);
                strListAll.remove(mIndex);
                stStaAll.remove(mIndex);
                mIndex = 0;
                stSta.push(0);
            }
        });

        //equation
        // 效果和m+相同 但是m+会改变mIndex
        mRead.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (strListAll.size() == 0) {
                    return;
                }
                String qu = strListAll.get(mIndex);
                String res = strListRes.get(mIndex);
                stSta = stStaAll.get(mIndex);
                strBufAll = new StringBuffer(qu);
                textQuestion.setText(qu);
                textResult.setText(res);
            }
        });

        // 将当前算式+结果存入 无结果的 存""
        mSave.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (strBufAll.toString().equals("")) {
                    strListAll.add(nowDo);
                } else {
                    strListAll.add(strBufAll.toString());
                }
                mIndex = 0;
                strListRes.add(textResult.getText().toString());
                stStaAll.add(stSta);
            }
        });

        mPlus.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (strListAll.size() == 0) {
                    return;
                }
                mIndex++;
                if (mIndex >= strListAll.size()) {
                    mIndex = 0;
                }
                String qu = strListAll.get(mIndex);
                String res = strListRes.get(mIndex);
                stSta = stStaAll.get(mIndex);
                strBufAll = new StringBuffer(qu);
                textQuestion.setText(qu);
                textResult.setText(res);
            }
        });
        mSubtract.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (strListAll.size() == 0) {
                    return;
                }
                mIndex--;
                if (mIndex < 0) {
                    mIndex = strListAll.size() - 1;
                }
                String qu = strListAll.get(mIndex);
                String res = strListRes.get(mIndex);
                stSta = new Stack<>();
                stSta = stStaAll.get(mIndex);
                strBufAll = new StringBuffer(qu);
                textQuestion.setText(qu);
                textResult.setText(res);
            }
        });


        //栈 end ---------
        */

        // 括号
        bntA.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                System.out.println(stSta);
                if (stSta.peek() == 1 || stSta.peek() == 4) {
                    myShowToast(stSta.peek());
                    // ( 前面不能为数字 和 ) 必须是*
                    return;
                }
                if (stSta.peek() == 0) {
                    textResult.setText("0.0");
                }
                stSta.push(3);
                leftKuoNum++;
                strBufAll.append("(");
                textQuestion.setText(strBufAll.toString());

            }
        });
        bntB.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                // ) 前面不能是* 也不能是空 也必须有可以匹配的(
                if (stSta.peek() == 0 || stSta.peek() == 2 || leftKuoNum <= rightKuoNum) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(4);
                rightKuoNum++;
                strBufAll.append(")");
                textQuestion.setText(strBufAll.toString());
            }
        });

        //新c类 start 【支持()】 ------------
        ///*
        // 加 符号前面不能是 空 |(
        optPlus.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(2);
                strBufAll.append("+");
                textQuestion.setText(strBufAll.toString());
            }
        });

        //减
        optSubtract.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(2);
                strBufAll.append("-");
                textQuestion.setText(strBufAll.toString());
            }
        });

        //乘
        optMultiply.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
                    myShowToast(stSta.peek());
                    return;
                }
                stSta.push(2);
                strBufAll.append("*");
                textQuestion.setText(strBufAll.toString());
            }
        });

        //除
        optDivide.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
                    myShowToast(stSta.peek());
                    return;
                }

                stSta.push(2);
                strBufAll.append("/");
                textQuestion.setText(strBufAll.toString());

            }
        });

        // 余
        optRemainder.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
                    myShowToast(stSta.peek());
                    return;
                }
               
                stSta.push(2);
                strBufAll.append("%");
                textQuestion.setText(strBufAll.toString());
            }
        });


        //等于
        optEqual.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("====start====");
                System.out.println(nowDo);
                System.out.println(stSta);
                int iss = stSta.peek();
                if (stSta.peek() == 0 || stSta.peek() == 2 || stSta.peek() == 3 || stSta.peek() == 5  ) {
                    myShowToast(iss);
                    return;
                }
                if (leftKuoNum != rightKuoNum){
                    Toast.makeText(MainActivity.this, "括号没完", Toast.LENGTH_LONG).show();
                    return;
                }
                try {
                    nowAns = myKuoHaoTest();
                } catch (Exception e) {
                    Toast.makeText(MainActivity.this,"!警告 有问题!",Toast.LENGTH_LONG).show();
                    Toast.makeText(MainActivity.this,""+e,Toast.LENGTH_LONG).show();
                    System.out.println(e);
                    //e.printStackTrace();
                }
                nowDo = strBufAll.toString();
                textResult.setText(nowAns);
                leftKuoNum = 0;
                rightKuoNum = 0;
                stSta = new Stack<>();
                stSta.push(0);
                strBufAll = new StringBuffer("");
                System.out.println("=====end====");
            }
        });


        //新c类 end ---------
        //*/


    }


    //    c类
    public String myKuoHaoTest() throws Exception {
        MyKuoHao myKuoHao = new MyKuoHao();
        String ans = myKuoHao.getAnsKuoHao(strBufAll.toString());
        return ans;
    }


    public void myShowToast(int preSta) {
        switch (preSta) {
            case 0:
                Toast.makeText(MainActivity.this, "请先输入数字", Toast.LENGTH_LONG).show();
                break;
            case 1:
                Toast.makeText(MainActivity.this, "不可以在数字后直接输入括号", Toast.LENGTH_LONG).show();
                break;
            case 2:
                Toast.makeText(MainActivity.this, "注意格式", Toast.LENGTH_LONG).show();
                break;
            case 3:
                Toast.makeText(MainActivity.this, "前面是左括号", Toast.LENGTH_LONG).show();
                break;
            case 4:
                Toast.makeText(MainActivity.this, "前面是右括号", Toast.LENGTH_LONG).show();
                break;
            case 5:
                Toast.makeText(MainActivity.this, "小数点后只能是数字", Toast.LENGTH_LONG).show();
                break;
            default:
        }
    }
}

MyKuoHao.java


package com.lxy.lxy_myapp_sy6.myClass;

import java.util.Stack;

public class MyKuoHao {


    public MyKuoHao() {

    }


    public String getAnsKuoHao(String str) throws Exception {
        //String s = "(1 + 2^3!-4)*(5!-(6-( 7-(89-0!))))#";// 2013
        //strBufAll.append("#");
        String ans;

        String s = str + "#";
        StringBuffer rpn = new StringBuffer();
        //try {
            float ansNum = calcExpression(s, rpn);
            System.out.println("结果:" + calcExpression(s, rpn));
            System.out.println("逆波兰表达式:" + rpn);

            System.out.println("\n计算逆波兰表达式:");
            calcExpressionRpn(rpn.toString());
            ans = String.valueOf(ansNum);
            return ans;
            //textResult.setText(String.valueOf(ans));
        //} catch (Exception e) {
        //    e.printStackTrace();

        //}
        //return "";
    }

    private Stack<Character> optr = new Stack<Character>();// 操作符栈
    private Stack<Float> opnd = new Stack<Float>();// 操作数栈
    private final Character END_Character = '#';// 输入表达式的结束字符

    public final int ADD = 0, SUB = 1, MUL = 2, DIV = 3, MOD = 4, POW = 5, FAC = 6, L_P = 7, R_P = 8, EOF = 9;
    public final char[][] PRI = {//运算符优先等级  [栈顶]'levle'[当前]
            //         |----------------当前运算符----------------|
            //           +   -   *   /   %   ^   !   (   )   #(结束字符)
            /*    + */ {'>','>','<','<','<','<','<','<','>','>'},
            /*    - */ {'>','>','<','<','<','<','<','<','>','>'},
            /* 栈     * */ {'>','>','>','>','>','<','<','<','>','>'},
            /* 顶     / */ {'>','>','>','>','>','<','<','<','>','>'},
            /* 运     % */ {'>','>','>','>','>','<','<','<','>','>'},
            /* 算     ^ */ {'>','>','>','>','>','>','<','<','>','>'},
            /* 符     ! */ {'>','>','>','>','>','>','>',' ','>','>'},
            /*    ( */ {'<','<','<','<','<','<','<','<','=',' '},
            /*    ) */ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
            /*    # */ {'<','<','<','<','<','<','<','<',' ','='}
    };

    /**
     * 中缀表达式计算,程序核心部分
     * @param expression
     *            输入的有效中缀表达式
     * @param RPN
     *            输出的逆波兰表达式(Reverse Polish Notation)
     * @return
     */
    public float calcExpression(String expression, StringBuffer RPN) throws Exception {
        // 初始时操作符栈压入开始标识符,与结束字符对应
        optr.push(END_Character);

        // 剔除表达式中的空格
        expression = removeSpace(expression);

        int i = 0;// 表示读取表示式的位置
        while (!optr.empty()) {
            char currenSymbol = expression.charAt(i);// 当前扫描到的表达式符号
            if (Character.isDigit(currenSymbol)) {
                i = readNumber(expression, i, opnd);// 读入(可能多位的)操作数
                RPN.append(opnd.peek() + " ");// 计入逆波兰表达式
            } else {
                switch (orderBetween(optr.peek(), currenSymbol)) {
                    case '>':// 栈顶运算符的优先级大于当前运算符,则1.取出操作符栈顶运算符,2.取出数据栈中的一个或多个数据(取决于运算符的类型),3.运算并把结果压入数据栈中
                        char op = optr.pop();// 取出栈顶操作符
                        RPN.append(op + " ");// 当操作符可以计算时计入逆波兰表达式,与逆波兰表达式的计算过程恰好吻合

                        Calculator ca = new Calculator();// 基本计算操作对象

                        if ('!' == op) {// 一元运算符的计算
                            float number = opnd.pop();// 取出操作数栈顶数值
                            System.out.println("计算过程:" + "[" + number + "]" + "" + op + "=" + "[" +ca.calcu(number, op) +"]" );
                            opnd.push(ca.calcu(number, op));// 计算并将结果入栈
                        } else {// 二元运算符的计算
                            float number2 = opnd.pop();// 取出操作数栈顶数值
                            float number1 = opnd.pop();// 取出操作数栈顶数值
                            System.out.println("计算过程:" + "[" + number1 + "]" + "" + op + "" + "[" + number2 + "]" + "=" + "[" +ca.calcu(number1, op, number2) + "]");
                            opnd.push(ca.calcu(number1, op, number2));// 计算并将结果入栈
                        }
                        break;
                    case '<':// 栈顶运算符的优先级小于当前运算符,计算推迟,当前运算符入栈
                        optr.push(currenSymbol);
                        i++;
                        break;
                    case '=':// 栈顶运算符的优先级等于当前运算符,脱括号并接收下一个字符
                        optr.pop();
                        i++;
                        break;
                    case ' ':
                        throw new Exception("ERROR");
                }
            }
        }

        return opnd.pop();// 操作数栈的最后一个元素即为需要的结果
    }

    /**
     * 只关注于求中缀表达式的接口
     * @param expression
     * @return
     * @throws Exception
     */
    public float calcExpression(String expression) throws Exception {
        return calcExpression(expression, new StringBuffer());
    }

    /**
     * 对逆波兰表达式进行计算
     * @param rpn
     * @return
     * @throws Exception
     */
    public float calcExpressionRpn(String rpn) throws Exception{
        String[] chs = rpn.split(" ");
        int i = 0;
        int chLength = chs.length;
        while(i < chLength) {
            Calculator ca = new Calculator();// 基本计算操作对象
            if( convertStrToDigit(chs[i]) != null ) {// 操作数直接入栈
                opnd.push(convertStrToDigit(chs[i]));
            } else {
                char op = chs[i].charAt(0);
                if("!".equals( chs[i] )) {
                    float number = opnd.pop();
                    opnd.push(ca.calcu(number, op));
                    System.out.println("计算过程:" + "[" + number + "]" + "" + op + "=" + "[" +ca.calcu(number, op) +"]" );

                } else {
                    float number2 = opnd.pop();// 取出操作数栈顶数值
                    float number1 = opnd.pop();// 取出操作数栈顶数值
                    System.out.println("计算过程:" + "[" + number1 + "]" + "" + op + "" + "[" + number2 + "]" + "=" + "[" +ca.calcu(number1, op, number2) + "]");
                    opnd.push(ca.calcu(number1, op, number2));// 计算并将结果入栈
                }
            }
            i++;
        }
        return opnd.pop();
    }

    /**
     * 将字符串转化为浮点数
     * @param str
     * @return
     */
    private Float convertStrToDigit(String str) {
        try{
            float num = Float.valueOf(str);
            return num;
        } catch(Exception e){
            return null;
        }
    }

    /**
     *  将char型的数字字符转为浮点型数据
     * @param ch
     * @return
     */
    private float CharToFloat(char ch) {
        return Float.valueOf("" + ch);
    }

    /**
     * 将起始为i的子串解析为数值,并存入操作数栈中
     * @param expression 表达式
     * @param i 开始解析的位置
     * @param stk 将解析完毕的数值存入此栈中
     * @return 该数值解析完毕后,返回表达式需要解析的下一个位置
     * @throws Exception 解析错误
     */
    private int readNumber(String expression, int i, Stack<Float> stk) throws Exception {
        stk.push(CharToFloat(expression.charAt(i++)));// 当前数位对应的数值进栈
        char op = expression.charAt(i); // 读取下一个字符
        while (Character.isDigit(op)) {// 只要后续还有紧邻的数字
            stk.push(stk.pop() * 10 + CharToFloat(op));// 弹出原操作数并追加新数位后,新数值重新入栈
            op = expression.charAt(++i);// 下一个字符
        }
        if ('.' != op)
            return i;// 如果最后一个数字后面不是小数点,说明解析完成,则返回当前位置
        op = expression.charAt(++i);
        float fraction = 1;
        while (Character.isDigit(op)) {
            stk.push(stk.pop() + CharToFloat(op) * (fraction /= 10));
            op = expression.charAt(++i);
        }
        if ('.' == op)
            throw new Exception("ERROR");// 如果还有小数点则错误
        return i;// 返回当前解析字符的位置
    }

    /**
     * 根据运算符获取在优先级表中的秩(RANK)
     * @param op
     * @return
     * @throws Exception
     */
    private int getOperRank(char op) throws Exception {
        switch (op) {
            case '+':
                return ADD;
            case '-':
                return SUB;
            case '*':
                return MUL;
            case '/':
                return DIV;
            case '%':
                return MOD;
            case '^':
                return POW;
            case '!':
                return FAC;
            case '(':
                return L_P;
            case ')':
                return R_P;
            case '#':
                return EOF;
            default:
                throw new Exception("ERROR");
        }
    }

    /**
     * 比较栈顶和当前字符的优先级
     * @param peekOptr 栈顶运算符
     * @param currenOptr 当前扫描到的运算符
     * @return 优先级表中的数据项
     * @throws Exception
     */
    private Character orderBetween(Character peekOptr, char currenOptr) throws Exception {
        return PRI[getOperRank(peekOptr)][getOperRank(currenOptr)];
    }

    /**
     * 剔除字符串之间的空格
     * @param str
     * @return
     */
    public String removeSpace(String str) {
        char[] chs = str.toCharArray();
        StringBuffer newStr = new StringBuffer();
        int i = 0;
        while (i < str.length()) {
            if (' ' != chs[i]) {
                newStr.append(chs[i]);
            }
            i++;
        }
        return newStr.toString();
    }

}

Calculator.java


package com.lxy.lxy_myapp_sy6.myClass;

public class Calculator {

    public float calcu(float n, char op) throws Exception {
        return fact(n);// 这里只有阶乘一个一元运算符
    }

    /**
     * 二元运算符
     *
     * @param a
     *            操作数1
     * @param op
     *            操作符
     * @param b
     *            操作数2
     * @return 结果浮点型
     * @throws Exception
     */
    public float calcu(float a, char op, float b) throws Exception {
        switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return div(a, b);
            case '%':
                return mod(a, b);
            case '^':
                return (float) Math.pow(a, b);
            default:
                throw new Exception("ERROR");
        }
    }

    private float div(float a, float b) throws Exception {
        if (b == 0)
            throw new Exception("除数不能为0!");
        return a / b;
    }

    // 取余
    private float mod(float a, float b) throws Exception {
        if (b == 0)
            throw new Exception("除数不能为0!");
        return a % b;
    }

    // 阶乘 n!(n<=20)
    private float fact(float n) throws Exception {
        if (n < 0)
            throw new Exception("阶乘运算数不能为负数!");
        if (n > 34)
            throw new Exception("阶乘数不能超过34,否则越界!");// 可以考虑改进以使计算更大数值的阶乘

        if (n == 0)
            return 1;// 0!=1
        int num = (int) n;
        if (num == n) {// n为整数
            float result = 1;
            while (num > 0) {
                result *= num--;
            }
            return result;
        } else
            throw new Exception("阶乘运算数必须为整数!");
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"

    android:padding="30dp">


    <EditText
        android:id="@+id/text_question"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@null"
        android:textSize="15pt"
        android:layout_marginTop="10dp"
        android:gravity="end"
        />

    <EditText
        android:id="@+id/text_result"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:layout_marginTop="10dp"
        android:background="@null"
        android:textSize="43dp"
        android:gravity="end"
        />

    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="fill"
        android:columnCount="5"
        android:orientation="horizontal"
        android:rowCount="6">

        <Button
            android:id="@+id/m_clear"
            style="@style/bnt_3"
            android:text="@string/mc" />

        <Button
            android:id="@+id/m_read"
            style="@style/bnt_3"
            android:text="@string/mr" />

        <Button
            android:id="@+id/m_save"
            style="@style/bnt_3"
            android:text="@string/ms" />

        <Button
            android:id="@+id/m_plus"
            style="@style/bnt_3"
            android:text="@string/m_plus" />

        <Button
            android:id="@+id/m_subtract"
            style="@style/bnt_3"
            android:text="@string/m_subtract" />


        <Button
            android:id="@+id/m_de"
            style="@style/bnt_1"
            android:text="DE" />

        <Button
            android:id="@+id/m_ce"
            style="@style/bnt_1"
            android:text="@string/ce" />

        <Button
            android:id="@+id/m_c"
            style="@style/bnt_1"
            android:text="@string/c" />

        <Button
            android:id="@+id/bnt_a"
            style="@style/bnt_1"
            android:text="(" />

        <Button
            android:id="@+id/bnt_b"
            style="@style/bnt_1"
            android:text=")" />


        <Button
            android:id="@+id/num_7"
            style="@style/bnt_2"
            android:text="7"

            android:textSize="20dp" />

        <Button
            android:id="@+id/num_8"
            style="@style/bnt_2"
            android:text="8" />

        <Button
            android:id="@+id/num_9"
            style="@style/bnt_2"
            android:text="9" />

        <Button
            android:id="@+id/opt_divide"
            style="@style/bnt_2"
            android:text="/" />


        <Button
            android:id="@+id/opt_remainder"
            style="@style/bnt_2"
            android:text="%" />


        <Button
            android:id="@+id/num_4"
            style="@style/bnt_2"
            android:text="4" />

        <Button
            android:id="@+id/num_5"
            style="@style/bnt_2"
            android:text="5" />

        <Button
            android:id="@+id/num_6"
            style="@style/bnt_2"
            android:text="6" />

        <Button
            android:id="@+id/opt_multiply"
            style="@style/bnt_2"
            android:text="*" />


        <Button
            android:id="@+id/opt_fraction"
            style="@style/bnt_2"
            android:textSize="20dp"
            android:text="/x" />

        <Button
            android:id="@+id/num_1"
            style="@style/bnt_2"
            android:text="1" />

        <Button
            android:id="@+id/num_2"
            style="@style/bnt_2"
            android:text="2" />

        <Button
            android:id="@+id/num_3"
            style="@style/bnt_2"
            android:text="3" />

        <Button
            android:id="@+id/opt_subtract"
            style="@style/bnt_2"
            android:text="-" />

        <Button
            android:id="@+id/opt_equal"
            android:layout_width="64dp"
            android:layout_height="126dp"
            android:layout_rowSpan="2"
            android:textSize="25dp"
            android:layout_margin="3dp"
            android:text="=" />

        <Button
            android:id="@+id/num_0"
            android:layout_height="60dp"
            android:layout_columnSpan="2"
            android:layout_gravity="fill_horizontal"
            android:layout_margin="3dp"
            android:text="0"
            android:textSize="25dp" />

        <Button
            android:id="@+id/symbol_point"
            style="@style/bnt_2"
            android:text="." />

        <Button
            android:id="@+id/opr_plus"
            style="@style/bnt_2"
            android:text="+" />


    </GridLayout>


</LinearLayout>

在这里插入图片描述

colors.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#D2C8FF</color>
    <color name="purple_500">#BEB0FF</color>
    <color name="purple_700">#2D00F8</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
</resources>

strings.xml

<resources>
    <string name="app_name">lxy计算器</string>
    <string name="m_subtract">M-</string>
    <string name="m_plus">M+</string>
    <string name="ms">MS</string>
    <string name="mr">MR</string>
    <string name="mc">MC</string>
    <string name="delete">back</string>
    <string name="ce">CE</string>
    <string name="c">C</string>

</resources>

style.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="bnt_1">
        <!--<item name=""-->
        <item name="android:layout_height">60dp</item>
        <item name="android:layout_width">64dp</item>
        <item name="android:layout_margin">3dp</item>

    </style>
    <!--number-->
    <style name="bnt_2">
        <item name="android:layout_height">60dp</item>
        <item name="android:layout_width">64dp</item>
        <item name="android:layout_margin">3dp</item>
        <item name="android:textSize">25dp</item>
    </style>
    <style name="bnt_3">
        <item name="android:layout_height">45dp</item>
        <item name="android:layout_width">64dp</item>
        <item name="android:layout_margin">3dp</item>
        <item name="android:textSize">15dp</item>
    </style>
</resources>

在这里插入图片描述

在这里插入图片描述

安卓计算机-sy6

参考
安卓布局方面
https://blog.csdn.net/qq_29656961/article/details/77977361
https://blog.csdn.net/wintershii/article/details/81663455
算法方面
https://blog.csdn.net/wj1243008609/article/details/82348654

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值