2012年4月6日 星期五

【Android】計算機





上學期上課寫的計算機,寫好用Stack的寫法之後,想說再試試看用樹狀結構跑中序,有bug,又想說哪一天有空再來改,結果一拖就是一學期...

layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText android:layout_height="wrap_content" android:id="@+id/editText_result"
        android:layout_width="match_parent" android:hint="1+2-3" android:focusable="false">
    </EditText>

    <TableLayout android:layout_width="match_parent"
        android:layout_height="wrap_content" android:stretchColumns="*">
        <TableRow>
            <Button android:text="1" android:id="@+id/button_num1"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="2" android:id="@+id/button_num2"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="3" android:id="@+id/button_num3"
                android:layout_height="wrap_content" android:layout_width="match_parent" />
        </TableRow>
        <TableRow>
            <Button android:text="4" android:id="@+id/button_num4"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="5" android:id="@+id/button_num5"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="6" android:id="@+id/button_num6"
                android:layout_height="wrap_content" android:layout_width="match_parent" />
        </TableRow>
        <TableRow>
            <Button android:text="7" android:id="@+id/button_num7"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="8" android:id="@+id/button_num8"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="9" android:id="@+id/button_num9"
                android:layout_height="wrap_content" android:layout_width="match_parent" />
        </TableRow>
        <TableRow>
            <Button android:text="+" android:id="@+id/button_plus"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="-" android:id="@+id/button_sub"
                android:layout_width="match_parent" android:layout_height="wrap_content" />
            <Button android:text="=" android:id="@+id/button_amount"
                android:layout_height="wrap_content" android:layout_width="match_parent" />
        </TableRow>
    </TableLayout>

</LinearLayout>

第一種 使用Stack
原理就是把符號跟數字分別拆到個別的Stack,然後再put出來,依據符號進行計算。
package npust.edu.klab;

import java.util.Stack;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;

public class Calculator extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // set all ui component.
        final EditText edtxt_result = (EditText) this
                .findViewById(R.id.editText_result);
        Button btn_amount = (Button) this.findViewById(R.id.button_amount);
        
        //to hide the virtual keyboard.
        InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);                
        imm.hideSoftInputFromWindow(edtxt_result.getWindowToken(), 0);
        
        // get all button then set a listener for general.
        Button[] btns = { (Button) this.findViewById(R.id.button_num1),
                (Button) this.findViewById(R.id.button_num2),
                (Button) this.findViewById(R.id.button_num3),
                (Button) this.findViewById(R.id.button_num4),
                (Button) this.findViewById(R.id.button_num5),
                (Button) this.findViewById(R.id.button_num6),
                (Button) this.findViewById(R.id.button_num7),
                (Button) this.findViewById(R.id.button_num8),
                (Button) this.findViewById(R.id.button_num9),
                (Button) this.findViewById(R.id.button_plus),
                (Button) this.findViewById(R.id.button_sub) };

        OnClickListener generalOnClick = new OnClickListener() {
            public void onClick(View v) {
                // set the txt of editText plus the text of button.
                edtxt_result.setText(edtxt_result.getText().toString()
                        + ((Button) v).getText());
            }
        };

        for (Button btn : btns)
            btn.setOnClickListener(generalOnClick);

        // calculate
        btn_amount.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {

                String formula = edtxt_result.getText().toString();
                // stacks for '+'、'-' and numbers.
                Stack symbols = new Stack();
                Stack nums = new Stack();
                // split by '+'、'-'
                String[] numAry = formula.toString().split("[\\+\\-/]");

                // set stacks.
                for (String num : numAry)
                    nums.push(Integer.valueOf(num));
                for (char c : formula.toCharArray())
                    if (c == '+' || c == '-')
                        symbols.push(c);

                // calculate by symbol.
                int result = 0;
                while (!symbols.isEmpty()) {
                    switch (symbols.pop()) {
                    case '+':
                        result += nums.pop();
                        break;
                    case '-':
                        result -= nums.pop();
                        break;
                    }
                }

                // plus the last num in stack.
                result += nums.pop();
                if(result<0){
                    edtxt_result.setText("");
                    edtxt_result.setHint("不支援負數計算");
                }
                else
                    edtxt_result.setText(result + "");
            }
        });
    }
}

第二種 使用樹狀結構
就是依據樹狀中序去做運算,結構如圖。

package npust.edu.klab;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;

public class Calculator extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // set all ui component.
        final EditText edtxt_result = (EditText) this
                .findViewById(R.id.editText_result);
        Button btn_amount = (Button) this.findViewById(R.id.button_amount);

        // to hide the virtual keyboard.
        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(edtxt_result.getWindowToken(), 0);

        // get all button then set a listener for general.
        Button[] btns = { (Button) this.findViewById(R.id.button_num1),
                (Button) this.findViewById(R.id.button_num2),
                (Button) this.findViewById(R.id.button_num3),
                (Button) this.findViewById(R.id.button_num4),
                (Button) this.findViewById(R.id.button_num5),
                (Button) this.findViewById(R.id.button_num6),
                (Button) this.findViewById(R.id.button_num7),
                (Button) this.findViewById(R.id.button_num8),
                (Button) this.findViewById(R.id.button_num9),
                (Button) this.findViewById(R.id.button_plus),
                (Button) this.findViewById(R.id.button_sub) };

        OnClickListener generalOnClick = new OnClickListener() {
            public void onClick(View v) {
                // set the txt of editText plus the text of button.
                edtxt_result.setText(edtxt_result.getText().toString()
                        + ((Button) v).getText());
            }
        };

        for (Button btn : btns)
            btn.setOnClickListener(generalOnClick);

        // calculate
        btn_amount.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                
                // reverse string to create a tree which grow to right side
                String formula = new StringBuffer(edtxt_result.getText().toString()).reverse().toString();

                Node root = new Node(), now = root;
                int last_index_ofSymbol = 0;
                
                for (int i = 0; i < formula.toCharArray().length; i++) {
                    if (formula.toCharArray()[i] == '+' || formula.toCharArray()[i] == '-') {                        
                        now.value = formula.toCharArray()[i] + "";
                        now.right = new Node();
                        if(last_index_ofSymbol==0)
                            now.right.value = formula.substring(last_index_ofSymbol, i);
                        else
                            now.right.value = formula.substring(last_index_ofSymbol+1, i);
                        last_index_ofSymbol = i;
                        now.left = new Node();
                        now = now.left;
                    } else if (i == formula.toCharArray().length - 1) {
                        now.value = formula.substring(last_index_ofSymbol+1);
                    }
                }

                // calculate by symbol.
                int result = 0;
                result = Node.inOrder(root);
                
                // plus the last num in stack.
                if (result < 0) {
                    edtxt_result.setText("");
                    edtxt_result.setHint("不支援負數計算");
                } else
                    edtxt_result.setText(result + "");
            }
        });
    }
}

class Node {
    public Node() {
        value = "";
        left = null;
        right = null;
    }

    String value;
    Node left;
    Node right;
    
    public static int inOrder(Node n){
        if(n!=null){    
            if(n.value.equals("+"))
                return inOrder(n.left) + inOrder(n.right);
            else if(n.value.equals("-"))
                return inOrder(n.left) - inOrder(n.right);
        }
        return Integer.parseInt(n.value);
    }
}
本來以為樹狀結構的話程式碼可以少寫很多,結果根本也沒有,而且一開始向右生長的樹被我寫成向左生長,所以減法一直算錯,自己還在那裏想半天。

1 則留言:

  1. 兄弟,我在研究您的Stack並且執行看看,

    但編譯器說明:

    int result = 0;
    while (!symbols.isEmpty()) {
    switch (symbols.pop()) {
    case '+':
    result += nums.pop();
    break;
    case '-':
    result -= nums.pop();
    break;
    }
    }

    此段程式碼有些錯誤,似乎是與INT、操作碼的錯誤!

    是不是型態類型有問題呢?

    回覆刪除