超级简陋的计算器

又学了一天,感觉一天都不知道在干嘛,都在写这个菜鸟计算器。

参考:https://blog.csdn.net/sakurakider/article/details/76283801
昨天随便弄了个计算器界面之后就睡觉了,实现我完全不会,今天早上早早起来就为了搞定它,是越搞越头疼,优先级问题我居然想不到栈,我学到狗身上了,都还给老师了,service使用我居然也能忘,真的蠢,忘了吃饭,忘了睡觉也不能忘了service啊。作业后面3个要求都没做出来,还得努力。
xml如下,这是漏洞百出的界面,别喷我,饶了我这脆弱的心灵:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout 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"
    tools:context=".MainActivity"
    android:padding="10dp"
    android:background="#bbbbbb">
        <TextView
            android:id="@+id/tv_result"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:background="#fff"
            android:padding="8dp"
            android:gravity="center_vertical|right"
            android:text="0"
            android:textSize="25sp"
            android:textColor="#aaaaaa"
            />
    <TableRow android:layout_marginTop="25dp">
        <Button
            android:id="@+id/btn_7"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="7"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_8"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="8"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_9"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="9"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_plus"
            android:layout_width="100dp"
            android:layout_height="70dp"
            android:text="+"
            android:textSize="25sp"
            />
    </TableRow>
    <TableRow android:layout_marginTop="10dp">
        <Button
            android:id="@+id/btn_4"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="4"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_5"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="5"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_6"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="6"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_sub"
            android:layout_width="100dp"
            android:layout_height="70dp"
            android:text="-"
            android:textSize="25sp"
            />
    </TableRow>
    <TableRow android:layout_marginTop="10dp">
        <Button
            android:id="@+id/btn_1"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="1"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_2"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="2"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_3"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="3"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_multiply"
            android:layout_width="100dp"
            android:layout_height="70dp"
            android:text="*"
            android:textSize="25sp"
            android:gravity="center"
            />
    </TableRow>
    <TableRow android:layout_marginTop="10dp">
        <Button
            android:id="@+id/btn_0"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="0"
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_point"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="."
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_equal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="70dp"
            android:text="="
            android:textSize="25sp"
            />
        <Button
            android:id="@+id/btn_division"
            android:layout_width="100dp"
            android:layout_height="70dp"
            android:text="/"
            android:textSize="25sp"
            />
    </TableRow>

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="8dp">
        <TextView
            android:padding="8dp"
            android:id="@+id/tv_showLog"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:text="Log"
            android:textSize="18sp"
            android:textColor="#fff"
            android:background="#000000"
            />
    </LinearLayout>
</TableLayout>

效果图:

漏洞百出的简单计算器
作业要求用service,所以首先创建Service类,service使用线程池新建了一个线程用来转换中缀表达式和计算,应该用IntentService更好吧。但是视频讲的是IntentService所以就想试试Service,计算完成后将结果放入Intent,在通过发送广播的方式传回结果。service代码如下:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import java.util.concurrent.Executors;


public class ComputeService extends Service {
    public static final String ACTION_COMPUTE = "ACTION_COMPUTE"; //action标识
    InfixInToSuffix infixInToSuffix = new InfixInToSuffix();      //转化和计算的类,别人写的

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        Executors.defaultThreadFactory().newThread(new Runnable() {
            @Override
            public void run() {
               StringBuilder a = new StringBuilder(intent.getStringExtra("text"));//获取中缀表达式
                String text = infixInToSuffix.toSuffix(a);//中缀表达式转换为后缀表达式
                Intent result = new Intent();
                result.setAction(ACTION_COMPUTE);
                result.putExtra("text","Get Task!" + a);
                result.putExtra("result",infixInToSuffix.dealEquation(text));//获取后缀表达式计算结果
                sendBroadcast(result);//发送广播
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

service里面的InfixInToSuffix就是别人写好的中缀表达式转换为后缀表达式还有后缀表达式计算,中缀转后缀规则:
1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
原文:https://blog.csdn.net/qq_34992845/article/details/70313588

InfixInToSuffix代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class InfixInToSuffix {
    //使用集合定义好符号的运算优先级别
    private static final Map<Character,Integer> basic =new HashMap<Character, Integer>();
    static {
        basic.put('-',1);
        basic.put('+', 1);
        basic.put('*', 2);
        basic.put('/', 2);
        basic.put('(', 0);//在运算中()的优先级最高,但是此处因程序中需要 故设置为0
    }

    //将中缀表达式转换为后缀表达式
    public String toSuffix(StringBuilder infix){
        List<String> queue = new ArrayList<String>();//定义队列,用于存储数字以及最后的后缀表达式
        List<Character> stack = new ArrayList<Character>(); //定义栈,用于存储运算符,最后stack中会被弹空

        char[] charArr = infix.substring(0,infix.length()).trim().toCharArray(); //字符数组,用于拆分数字或符号
        String standard = "*/+-()"; //判定标准 将表达式中会出现的运算符写出来
        char ch = '&'; //在循环中用来保存 字符数组的当前循环变量的  这里仅仅是初始化一个值  没有意义
        int len = 0; //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】
        for (int i = 0; i < charArr.length; i++) {//开始迭代

            ch = charArr[i];//保存当前迭代变量
            if(Character.isDigit(ch)) {  //如果当前变量为 数字
                len++;
            }else if(ch == '.'){ //如果当前变量为  .  会出现在小数里面
                len++;
            }else if(standard.indexOf(ch) != -1) {//如果是上面标准中的 任意一个符号
                if(len > 0) { //长度也有
                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));//说明符号之前的可以截取下来做数字
                    len = 0;  //长度置空
                }
                if(ch == '(') {  //如果是左括号
                    stack.add(ch);//将左括号 放入栈中
                    continue;  //跳出本次循环  继续找下一个位置
                }
                if (!stack.isEmpty()) {  //如果栈不为empty
                    int size = stack.size() - 1;//获取栈的大小-1  即代表栈最后一个元素的下标
                    boolean flag = false; //设置标志位
                    while (size >= 0 && ch == ')' && stack.get(size) != '(') { //若当前ch为右括号,则 栈里元素从栈顶一直弹出,直到弹出到 左括号
                        queue.add(String.valueOf(stack.remove(size)));//注意此处条件:ch并未入栈,所以并未插入队列中;同样直到找到左括号的时候,循环结束了,所以左括号也不会放入队列中【也就是:后缀表达式中不会出现括号】
                        size--;//size-- 保证下标永远在栈最后一个元素【栈中概念:指针永远指在栈顶元素】
                        flag = true; //设置标志位为true  表明一直在取()中的元素
                    }
                    if(ch==')'&&stack.get(size) == '('){
                        flag = true;
                    }
                    while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) {  //若取得不是()内的元素,并且当前栈顶元素的优先级>=对比元素 那就出栈插入队列
                        queue.add(String.valueOf(stack.remove(size)));//同样  此处也是remove()方法,既能得到要获取的元素,也能将栈中元素移除掉
                        size--;
                    }
                }
                if(ch != ')') { //若当前元素不是右括号
                        stack.add(ch);   //就要保证这个符号 入栈
                } else {  //否则就要出栈 栈内符号
                    stack.remove(stack.size() - 1);
                }
            }
            if(i == charArr.length - 1) { //如果已经走到了  中缀表达式的最后一位
                if(len > 0) {   //如果len>0  就截取数字
                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1)));
                }
                int size = stack.size() - 1;   //size表示栈内最后一个元素下标
                while (size >= 0) {   //一直将栈内  符号全部出栈 并且加入队列中  【最终的后缀表达式是存放在队列中的,而栈内最后会被弹空】
                    queue.add(String.valueOf(stack.remove(size)));
                    size--;
                }
            }

        }
        String a = queue.toString();
        return a.substring(1,a.length()-1);
    }

    public String dealEquation(String equation){

        String [] arr = equation.split(", ");                                    //根据, 拆分字符串
        List<String> list = new ArrayList<String>();   //用于计算时存储运算过程的集合【例如list中当前放置  100   20  5  /  则取出20/5 最终将结果4存入list   此时list中结果为  100  4 】


        for (int i = 0; i < arr.length; i++) {     //此处就是上面说的运算过程,因为list.remove的缘故,所以取出最后一个数个最后两个数  都是size-2
            int size = list.size();
            switch (arr[i]) {
                case "+":
                    double a = Double.parseDouble(list.remove(size-2))
                            + Double.parseDouble(list.remove(size-2));
                    list.add(String.valueOf(a));
                    break;
                case "-":
                    double b = Double.parseDouble(list.remove(size-2))
                        - Double.parseDouble(list.remove(size-2));
                    list.add(String.valueOf(b));
                    break;
                case "*":
                    double c = Double.parseDouble(list.remove(size-2))
                            * Double.parseDouble(list.remove(size-2));
                    list.add(String.valueOf(c));
                    break;
                case "/":
                    double d = Double.parseDouble(list.remove(size-2))
                            / Double.parseDouble(list.remove(size-2));
                    list.add(String.valueOf(d));
                    break;
                default:
                    list.add(arr[i]);
                    break;              //如果是数字  直接放进list中
            }
        }

        return list.size() == 1 ? list.get(0) : "运算失败" ;     //最终list中仅有一个结果,否则就是算错了
    }

最后,数据处理完了,在MainActivity里注册并接受广播,判断是否是你要的广播,再获取Service发送过来的Intent里的内容输出到TextView中就好了。代码如下:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity  implements View.OnClickListener {
    private TextView tv_show;
    private TextView tv_log;
    private Button btn_0,btn_1,btn_2,btn_3,btn_4,btn_5,btn_6,btn_7, btn_8,btn_9,
                    btn_plus,btn_sub,btn_multiply,btn_divide,btn_point,btn_equal;
    private StringBuilder builder = new StringBuilder();
    private String[] log = new String[10];
    private MyBroadcastReceiver myBroadcastReceiver;
    private String result;
    private String text;

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

        initViews();    //初始化视图
        registerBroadcastReceiver();    //注册广播接收者

    }

    /**
     * 注册广播接收器
     */
    private void registerBroadcastReceiver() {
        myBroadcastReceiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter(ComputeService.ACTION_COMPUTE);
        registerReceiver(myBroadcastReceiver,intentFilter);
    }

    /**
     * 初始化视图
     */
    private void initViews() {
        tv_log = findViewById(R.id.tv_showLog);
        tv_show = findViewById(R.id.tv_result);
        btn_0 = findViewById(R.id.btn_0);
        btn_1 = findViewById(R.id.btn_1);
        btn_2 = findViewById(R.id.btn_2);
        btn_3 = findViewById(R.id.btn_3);
        btn_4 = findViewById(R.id.btn_4);
        btn_5 = findViewById(R.id.btn_5);
        btn_6 = findViewById(R.id.btn_6);
        btn_7 = findViewById(R.id.btn_7);
        btn_8 = findViewById(R.id.btn_8);
        btn_9 = findViewById(R.id.btn_9);
        btn_plus = findViewById(R.id.btn_plus);
        btn_sub = findViewById(R.id.btn_sub);
        btn_multiply = findViewById(R.id.btn_multiply);
        btn_divide = findViewById(R.id.btn_division);
        btn_point = findViewById(R.id.btn_point);
        btn_equal = findViewById(R.id.btn_equal);

        btn_point.setOnClickListener(this);
        btn_plus.setOnClickListener(this);
        btn_sub.setOnClickListener(this);
        btn_multiply.setOnClickListener(this);
        btn_divide.setOnClickListener(this);
        btn_equal.setOnClickListener(this);
        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);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_0:
                builder = builder.append("0");
                tv_show.setText(builder);
                break;
            case R.id.btn_1:
                builder = builder.append("1");
                tv_show.setText(builder);
                break;
            case R.id.btn_2:
                builder = builder.append("2");
                tv_show.setText(builder);
                break;
            case R.id.btn_3:
                builder = builder.append("3");
                tv_show.setText(builder);
                break;
            case R.id.btn_4:
                builder = builder.append("4");
                tv_show.setText(builder);
                break;
            case R.id.btn_5:
                builder = builder.append("5");
                tv_show.setText(builder);
                break;
            case R.id.btn_6:
                builder = builder.append("6");
                tv_show.setText(builder);
                break;
            case R.id.btn_7:
                builder = builder.append("7");
                tv_show.setText(builder);
                break;
            case R.id.btn_8:
                builder = builder.append("8");
                tv_show.setText(builder);
                break;
            case R.id.btn_9:
                builder = builder.append("9");
                tv_show.setText(builder);
                break;
            case R.id.btn_plus:
                builder = builder.append("+");
                tv_show.setText(builder);
                break;
            case R.id.btn_sub:
                builder = builder.append("-");
                tv_show.setText(builder);
                break;
            case R.id.btn_multiply:
                builder = builder.append("*");
                tv_show.setText(builder);
                break;
            case R.id.btn_division:
                builder = builder.append("/");
                tv_show.setText(builder);
                break;
            case R.id.btn_point:
                builder = builder.append(".");
                tv_show.setText(builder);
                break;
            case R.id.btn_equal:
                Intent intent = new Intent(MainActivity.this,ComputeService.class);
                intent.putExtra("text",builder.toString());//将文本信息存入intent
                startService(intent);//开启服务
                builder = builder.delete(0,builder.length());//清除文本
                tv_show.setText(builder);

                break;

        }
    }

    /**
     * 重写广播接收器的Receive抽象方法,用以接收数据
     */
    class MyBroadcastReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {//接收广播传来的intent
            if (ComputeService.ACTION_COMPUTE == intent.getAction()) {
                result = intent.getStringExtra("result");
                text = intent.getStringExtra("text");
                tv_log.setText(text + "\nTask is finished and result is " + result);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

好了,继续学习,数据结构也要复习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值