安卓作业----慕课移动互联网作业7使用逆波兰式实现处理加减乘除符合运算的计算器

这是中国大学慕课移动终端应用开发的网课作业7,我会持续更新我的作业,如果有需要关注一下吧

说明

1.本计算器利用逆波兰式能实现加减乘除复合运算
2.第一个数字输入小数点能自动补全为 0.
3.能检测重复输入小数点情况
4.能检测式子语法正确情况

如果发现bug,或者有优化方案,可评论或私信联系我

界面展示

在这里插入图片描述

代码部分

布局文件 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>
发布了34 篇原创文章 · 获赞 65 · 访问量 3687

猜你喜欢

转载自blog.csdn.net/baidu_41860619/article/details/105010288