Android开发:可以区分优先级和括号的计算器

Android开发:可以区分优先级和括号的计算器

此计算器是基于将中缀表达式转化为后缀表达式,从而对表达式求值的算法。

成果图如下:

image-20210413035451331 image-20210413034203162

xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="10dp"
        tools:context="com.example.caculator.MainActivity"
        >

    <EditText
            android:id="@+id/et_input"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:inputType="none"
            android:gravity="center|right"
            android:background="#f0f0f0"/>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:orientation="horizontal">

        <Button
                android:id="@+id/left_parenthese"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="("
                android:textSize="20sp"/>

        <Button
                android:id="@+id/right_parenthese"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text=")"
                android:textSize="20sp" />

    </LinearLayout>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

        <Button
                android:id="@+id/btn_clear"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="C"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_del"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="DEL"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_divide"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="/"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_multply"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="*"
                android:textSize="20sp"/>

    </LinearLayout>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

        <Button
                android:id="@+id/btn_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="7"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="8"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_9"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="9"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_minus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="-"
                android:textSize="20sp"/>

    </LinearLayout>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

        <Button
                android:id="@+id/btn_4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="5"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="6"
                android:textSize="20sp"/>

        <Button
                android:id="@+id/btn_plus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:text="+"
                android:textSize="20sp"/>

    </LinearLayout>

    <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

        <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

            <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                <Button
                        android:id="@+id/btn_1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="1"
                        android:textSize="20sp"/>

                <Button
                        android:id="@+id/btn_2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="5dp"
                        android:text="2"
                        android:textSize="20sp"/>

                <Button
                        android:id="@+id/btn_3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="5dp"
                        android:text="3"
                        android:textSize="20sp"/>

            </LinearLayout>

            <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingTop="10dp"
                    android:weightSum="1"
                    android:orientation="horizontal">

                <Button
                        android:id="@+id/btn_0"
                        android:layout_width="180dp"
                        android:layout_height="wrap_content"
                        android:text="0"
                        android:textSize="20sp"/>

                <Button
                        android:id="@+id/btn_point"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="5dp"
                        android:layout_weight="18.10"
                        android:text="."
                        android:textSize="20sp"/>


            </LinearLayout>

        </LinearLayout>

        <Button
                android:id="@+id/btn_equal"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="5dp"
                android:background="@android:color/holo_orange_light"
                android:text="="
                android:textSize="20sp"/>

    </LinearLayout>

</LinearLayout>

Activity

  • 定义监听器类,注册监听器对象

    //基于监听接口的事件处理机制。第一步:定义监听器类,在监听器中针对事件编写响应的处理代码
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private Button btn_0;//0数字按钮
        private Button btn_1;//1数字按钮
        private Button btn_2;//2数字按钮
        private Button btn_3;//3数字按钮
        private Button btn_4;//4数字按钮
        private Button btn_5;//5数字按钮
        private Button btn_6;//6数字按钮
        private Button btn_7;//7数字按钮
        private Button btn_8;//8数字按钮
        private Button btn_9;//9数字按钮
        private Button btn_point;//小数点按钮
        private Button btn_clear;//clear按钮
        private Button btn_del;//del按钮
        private Button btn_plus;//+按钮
        private Button btn_minus;//-按钮
        private Button btn_multply;//*按钮
        private Button btn_divide;//除号按钮
        private Button btn_equal;//=按钮
    
        private Button left_parenthese;
        private Button right_parenthese;
        private EditText editText;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn_0 = (Button) findViewById(R.id.btn_0);
            btn_1 = (Button) findViewById(R.id.btn_1);
            btn_2 = (Button) findViewById(R.id.btn_2);
            btn_3 = (Button) findViewById(R.id.btn_3);
            btn_4 = (Button) findViewById(R.id.btn_4);
            btn_5 = (Button) findViewById(R.id.btn_5);
            btn_6 = (Button) findViewById(R.id.btn_6);
            btn_7 = (Button) findViewById(R.id.btn_7);
            btn_8 = (Button) findViewById(R.id.btn_8);
            btn_9 = (Button) findViewById(R.id.btn_9);
            btn_point = (Button) findViewById(R.id.btn_point);
            btn_clear = (Button) findViewById(R.id.btn_clear);
            btn_del = (Button) findViewById(R.id.btn_del);
            btn_plus = (Button) findViewById(R.id.btn_plus);
            btn_minus = (Button) findViewById(R.id.btn_minus);
            btn_multply = (Button) findViewById(R.id.btn_multply);
            btn_divide = (Button) findViewById(R.id.btn_divide);
            btn_equal = (Button) findViewById(R.id.btn_equal);
            editText = (EditText) findViewById(R.id.et_input);
            left_parenthese=(Button)findViewById(R.id.left_parenthese);
            right_parenthese=(Button)findViewById(R.id.right_parenthese);
            //注册监听器对象,将监听器对象绑定在该事件源上,当事件发生时,调用监听器中的事件响应代码
            btn_0.setOnClickListener(this);
            btn_1.setOnClickListener(this);
            btn_2.setOnClickListener(this);
            btn_3.setOnClickListener(this);
            btn_4.setOnClickListener(this);
            btn_5.setOnClickListener(this);
            btn_6.setOnClickListener(this);
            btn_7.setOnClickListener(this);
            btn_8.setOnClickListener(this);
            btn_9.setOnClickListener(this);
            btn_point.setOnClickListener(this);
            btn_clear.setOnClickListener(this);
            btn_del.setOnClickListener(this);
            btn_plus.setOnClickListener(this);
            btn_minus.setOnClickListener(this);
            btn_multply.setOnClickListener(this);
            btn_divide.setOnClickListener(this);
            btn_equal.setOnClickListener(this);
            left_parenthese.setOnClickListener(this);
            right_parenthese.setOnClickListener(this);
        }
    
    
  • 处理事件:将点击按钮的结果显示在editText中

    public Stack<Character> parStack=new Stack<>();
        @Override
        public void onClick(View view) {
            //view是事件源
            String editTextContent = editText.getText().toString();
            switch (view.getId()) {
                //只有当前面是空或者是运算符的时候才能加左括号
                case R.id.left_parenthese:
                    if (editTextContent.equals("")){
                        parStack.push('(');
                        editText.setText(editTextContent + "(");
                        break;
                    }
                    char previousChar=editTextContent.charAt(editTextContent.length()-1);
                    if (previousChar=='+'||previousChar=='-'||previousChar=='*'||previousChar=='/'){
                        parStack.push('(');
                        editText.setText(editTextContent + "(");
                    }
                    break;
                //只有当栈顶是左括号并且前面是数字时才能加右括号
                case R.id.right_parenthese:
                    if (editTextContent.equals(""))
                        break;
                    char previousChar2=editTextContent.charAt(editTextContent.length()-1);
                    if (parStack.isEmpty()||previousChar2=='+'||previousChar2=='-'||previousChar2=='*'||previousChar2=='/')
                        break;
                    parStack.pop();
                    editText.setText(editTextContent + ")");
                    break;
                case R.id.btn_0:
                case R.id.btn_1:
                case R.id.btn_2:
                case R.id.btn_3:
                case R.id.btn_4:
                case R.id.btn_5:
                case R.id.btn_6:
                case R.id.btn_7:
                case R.id.btn_8:
                case R.id.btn_9:
                case R.id.btn_point:
                    editText.setText(editTextContent + ((Button) view).getText());
                    break;
                case R.id.btn_plus:
                case R.id.btn_minus:
                case R.id.btn_multply:
                case R.id.btn_divide:
                    if (!editTextContent.equals(""))
                        editText.setText(editTextContent + ((Button) view).getText());
                    break;
                case R.id.btn_clear:
                    editTextContent = "";
                    editText.setText("");
                    break;
                case R.id.btn_del:
                    if (!editTextContent.equals("")) {
                        editTextContent = editTextContent.substring(0, editTextContent.length() - 1);
                        editText.setText(editTextContent);
                    }
                    break;
                case R.id.btn_equal:
                    if (!editTextContent.equals(""))
                        getResult();
                    break;
            }
    
        }
    
  • 求出editText中表达式的结果:将表达式由中缀表达式转化为后缀表达式,再求解

    public Stack<Double>numberStack=new Stack<>();
        public Stack<Character>operatorStack=new Stack<>();
        //运算结果
        private void getResult() {
            String exp = editText.getText().toString();
    
            String number="";
            for (int i=0;i<exp.length();i++){
                switch (exp.charAt(i)){
                    //如果是左括号,不管栈顶的优先级多高,直接进栈
                    case '(':
                        if (number!="") {
                            numberStack.push(Double.parseDouble(number));
                            number = "";
                        }
    
                        operatorStack.push('(');
                        break;
                    //如果是右括号,将栈中直到左括号为止(包括左括号)的所有符号全部出栈
                    case ')':
                        if (number!="") {
                            numberStack.push(Double.parseDouble(number));
                            number = "";
                        }
                        char c;
                        while ((c=operatorStack.pop())!='('){
                            numberStack.push(caculateTwoNumber(numberStack.pop(),numberStack.pop(),c));
                        }
                        break;
    
                    case '+':
                    case '-':
                        if (number!="") {
                            numberStack.push(Double.parseDouble(number));
                            number = "";
                        }
                        //如果符号栈不为空,由于+-优先级最低,所以需要将栈中的符号一直出栈,直到栈顶为左括号,或者栈为空
                        while (!operatorStack.isEmpty()&&operatorStack.peek()!='('){
                            numberStack.push(caculateTwoNumber(numberStack.pop(),numberStack.pop(),operatorStack.pop()));
                        }
                        operatorStack.push(exp.charAt(i));
                        break;
    
                    case '*':
                    case '/':
                        if (number!="") {
                            numberStack.push(Double.parseDouble(number));
                            number = "";
                        }
                        //优先级比自己高的全部出栈,直到栈为空
                        while (!operatorStack.isEmpty()&&(operatorStack.peek()=='*'||operatorStack.peek()=='/'))
                            numberStack.push(caculateTwoNumber(numberStack.pop(),numberStack.pop(),operatorStack.pop()));
                        operatorStack.push(exp.charAt(i));
                        break;
                    //如果是数字的话,先将数值的每一位合起来,当遇到符号位时,就形成了一个完整的数,再将这个数加入数值栈
                    default:
                        number+=exp.charAt(i);
                }
            }
            numberStack.push(Double.parseDouble(number));
            while (numberStack.size()>1&&!operatorStack.isEmpty()){
                numberStack.push(caculateTwoNumber(numberStack.pop(),numberStack.pop(),operatorStack.pop()));
            }
            editText.setText(String.valueOf(numberStack.pop()));
        }
        private double caculateTwoNumber(double right,double left,char operator){
            switch (operator){
                case '+':
                    return left+right;
                case '-':
                    return left-right;
                case '*':
                    return left*right;
                case '/':
                    return left/right;
                default:
                    return 0.0;
            }
        }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值