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;
            }
        }
    

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令&#xff1a; 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体&#xff0c;就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛&#xff0c;这门课会介绍许多方法去利用离散点最大化地逼近这个函数&#xff0c;甚至它的导数、积分&#xff0c;甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;14届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09; ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目&#xff1a; 解题思路&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 总代码&#xff1a; 题目&#xff1a; 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验&#xff0c;睡觉过程中突然意识清醒&#xff0c;身体却动弹不了。这时候感觉非常恐怖&#xff0c;希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况&#xff0c;一年有一百多次&#xff0c;那时候很害怕晚上到来&#xff0c;睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别&#xff08;move-only type&#xff0c;只移型别还有std::mutex等&#xff09;。 结合一下工厂模式&#xff0c;看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在&#xff0c;但代码中需要用到它&#xff0c;通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能&#xff0c;通常需要完成两步操作&#xff1a;一.是在Web页面中添加上传输入项&#xff1b;二是在Servlet中读取上传文件的数据&#xff0c;并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度&#xff08;&#xff1f;&#xff09; 不管两个高积木之间的的积木是怎样乱七八糟的高度&#xff0c;最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的&#xff0c;用的是MFC VS2019. 详见&#xff1a;http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936&#xff0c;然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一&#xff1a;区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点&#xff0c;使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N&#xff0c;表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家&#xff0c;在他的着作中曾经提到&#xff1a;「若有一只免子每个月生一只小免子&#xff0c;一个月后小免子也开始生产。起初只有一只免子&#xff0c;一个月后就有两只免子&#xff0c;二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源&#xff0c;一般分为两类&#xff1a; 系统内置资源&#xff1a;Android SDK中所提供的已经定义好的资源&#xff0c;用户可以直接拿来使用。 用户自定义资源&#xff1a;用户自己定义或引入的&#xff0c;只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法&#xff08;Algorithm&#xff09;是一系列解决问题的清晰指令&#xff0c;也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获得所要求的输出。 如果一个算法有缺陷&#xff0c;或不适合于某个问题&#xff0c;执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习人工智能&#xff1a;知识图谱实战前言一、实体建模工具Protegepython&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习 人工智能&#xff1a;知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…