android实现简单计算器

最近在做一个计算器小demo,中间真是踩了不少坑,所以打算系统的总结一下,也不枉我耗费了这么多心血。
计算器要求如下图所示,要求可以进行简单的加减乘除运算,按下clear按钮清空上面的表达式。
android实现简单计算器_第1张图片

一、界面设计

上面是一个EditText用来表示输入框

下面键盘设计是GridView

代码如下:




    

        
        

        

    



然后用一个适配器给键盘上的数字赋值:

 //按钮中的字符
    private final String[] buttons = new String[]{
            "9", "8", "7", "+",
            "6", "5", "4", "-",
            "3", "2", "1", "x",
            "0", "clear", "=", "/",
    };
 //设置适配器
        ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, buttons);
        gridView.setAdapter(adapter);

二、设置触发事件

其中 toDoString表示即将要计算的表达式
doneString表示已经计算完的表达式
isExecuteNow用来表示当前计算的表达式是否已完成,如果已完成就将他加到 doneString中,否则就将按下的每一个字符加到 toDoString中:
 //触发事件
    private class OnButtonItemClickListener implements AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView adapterView, View view, int position, long id) {
            String text = (String) adapterView.getAdapter().getItem(position);
            if (text.equals("=")) {
                toDoString += "=";
                ExcuteExpression();
            } else if (text.equals("clear")) {
                doneString = "";
                toDoString = "";
                isExecuteNow = false;
                editText.setText("");
            } else {
                if (isExecuteNow) {
                    /*把待计算的表达式加到已计算表达式中,后面再加个换行符
                     * */
                    doneString = doneString + toDoString + "
"; isExecuteNow = false; toDoString = text; } else { toDoString += text; } setText(); } } }

其中setText()函数用来向EditText中显示要计算的表达式和已经计算完的表达式
/**
     * 设置EditText的显示内容,计算完成后换行等
     */
    private void setText() {
        final String[] tags = new String[]{
                "",
                "",
                ""
        };
        StringBuilder builder = new StringBuilder();
        builder.append(tags[0]).append(doneString).append(tags[2]);
        builder.append(tags[1]).append(toDoString).append(tags[2]);
        //显示内容
        editText.setText(Html.fromHtml(builder.toString()));
        //设置光标在最后的位置
        editText.setSelection(editText.getText().length());
    }

三、计算表达式

因为我们输入的表达式是中缀表达式,所以要根据中缀表达式转换后缀表达式的思想进行转换,然后 再计算,详细解释见上一篇文章java中缀表达式转化成后缀表达式并计算结果
这里就直接贴上代码,就不再多赘述了
private String converExpr(String expression) {
        int InfixIndex = 0;
        int PostfixIndex = 0;
        String PostStr[] = new String[expression.length()];
        PostStr[0]="";
        Stack stack = new Stack();
        //char post[] = new char[100];
        String topString;//栈顶元素
        String curString="";//当前元素
        String NextString = "";//当前元素的下一个元素
        int isMul=0;//判断是否是复数
         while(!NextString.equals("=")) {
            curString = String.valueOf(expression.charAt(InfixIndex));
            NextString = String.valueOf(expression.charAt(InfixIndex+1));
            //  如果是数字,直接添加进字符中
            // 如果前下一个字符也是数字,把他们并到一起
            if (curString.matches("[\\d\\.]") && NextString.matches("[\\d\\.]")) {
                if(isMul==0) {
                    PostStr[PostfixIndex] = PostStr[PostfixIndex] + curString.concat(NextString);
                    Log.i("a", "PostStr[i]" + PostStr[PostfixIndex]);
                }
                else{
                    PostStr[PostfixIndex] = PostStr[PostfixIndex].concat(NextString);
                    Log.i("a", "PostStr[i]" + PostStr[PostfixIndex]);
                }
                isMul=1;
                //InfixIndex++;
                //PostfixIndex++;
            } else if(curString.matches("[\\d\\.]")&& NextString.matches("[^\\d\\.]")&& isMul==0){
                PostStr[PostfixIndex]=curString;
                Log.i("a","PostStr[i]"+PostStr[PostfixIndex]);
                PostfixIndex++;
            } else if(curString.matches("[\\d\\.]")&& NextString.matches("[^\\d\\.]")&& isMul==1){
                isMul=0;
                PostfixIndex++;
                PostStr[PostfixIndex]="";
            } else if (curString.equals(")")) {
                //如果是右括号,将栈中其他运算符出栈,添加进字符数组,知道匹配到左括号
                while (!stack.peek().equals("(")) {
                    PostStr[PostfixIndex] = stack.peek();
                    PostfixIndex++;
                    stack.pop();
                }
                stack.pop();
            } else if (curString.equals("+")|| curString.equals("-")) {
                //如果是加减符号
                if (stack.isEmpty())//空栈就直接入栈
                    stack.push(curString);
                else {//弹出优先级高于加减的运算符(因为加减运算符优先级最低)
                    while (!stack.isEmpty()) {
                        topString = stack.peek();
                        stack.pop();
                        if (topString .equals("(")) {
                            stack.push(topString);
                            break;
                        } else {
                            PostStr[PostfixIndex] = topString;
                            PostfixIndex++;
                        }
                    }
                    stack.push(curString);
                }
            } else if (curString .equals("x") || curString .equals("/") || curString .equals("(")) {
                //如果是乘除、左括号,优先级高,直接入栈
                stack.push(curString);
            }else{
                return "格式错误";
            }
            InfixIndex++;

            Log.i("ss","PostStr[i]"+PostStr[PostfixIndex]);
        }
        //字符遍历完后将栈中剩余的字符出栈
        while (!stack.isEmpty()) {
            PostStr[PostfixIndex] = stack.peek();
            PostfixIndex++;
            stack.pop();
        }
        return calcuPost(PostStr);

    }

    /**
     * 根据后缀表达式计算结果
     * @param post
     */
    private String calcuPost(String post[]) {
        LinkedList mList = new LinkedList<>();
        for (String s : post) {
            if (!TextUtils.isEmpty(s)) {
                //遇到运算符就对栈顶的两个数字运算
                if (isEqualString(s)) {
                    if (!mList.isEmpty()) {
                        int num1 = Integer.valueOf(mList.pop());
                        int num2 = Integer.valueOf(mList.pop());
                        if (s.equals("/") && num1 == 0) {
                            return "除数不能为空";
                        }
                        mList.push(cal(num2,num1,s));
                    }
                } else {
                    //遇到数字就入栈
                    mList.push(s);
                }
            }
        }
        if (!mList.isEmpty()) {
            return mList.pop();
        }
        return "表达式错误";
    }

    private static String cal(int num2, int num1, String op) {
        switch (op) {
            case "+":
                return String.valueOf(num1 + num2);
            case "-":
                return String.valueOf(num2 - num1);
            case "x":
                return String.valueOf(num1 * num2);
            case "/":
                return String.valueOf(num2*1.0 / num1);
            default:
                return "";
        }
    }

四、将结果输出

result表示最后计算的结果,将结果加入到toDoString中,再利用setText()在输入框中显示即可:
 /**
     * 输出表达式的值
     */
    private void ExcuteExpression() {
        String result = "";
        try {
            result = converExpr(toDoString);
            Log.i("tag", result);
        } catch (Exception e) {
            isExecuteNow = false;
        }
        toDoString += result;
        setText();
        isExecuteNow = true;
    }

五、测试

android实现简单计算器_第2张图片



你可能感兴趣的:(android)