2012年4月6日 星期五

【Android】計算機





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

layout
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <EditText android:layout_height="wrap_content" android:id="@+id/editText_result"
  6. android:layout_width="match_parent" android:hint="1+2-3" android:focusable="false">
  7. </EditText>
  8.  
  9. <TableLayout android:layout_width="match_parent"
  10. android:layout_height="wrap_content" android:stretchColumns="*">
  11. <TableRow>
  12. <Button android:text="1" android:id="@+id/button_num1"
  13. android:layout_width="match_parent" android:layout_height="wrap_content" />
  14. <Button android:text="2" android:id="@+id/button_num2"
  15. android:layout_width="match_parent" android:layout_height="wrap_content" />
  16. <Button android:text="3" android:id="@+id/button_num3"
  17. android:layout_height="wrap_content" android:layout_width="match_parent" />
  18. </TableRow>
  19. <TableRow>
  20. <Button android:text="4" android:id="@+id/button_num4"
  21. android:layout_width="match_parent" android:layout_height="wrap_content" />
  22. <Button android:text="5" android:id="@+id/button_num5"
  23. android:layout_width="match_parent" android:layout_height="wrap_content" />
  24. <Button android:text="6" android:id="@+id/button_num6"
  25. android:layout_height="wrap_content" android:layout_width="match_parent" />
  26. </TableRow>
  27. <TableRow>
  28. <Button android:text="7" android:id="@+id/button_num7"
  29. android:layout_width="match_parent" android:layout_height="wrap_content" />
  30. <Button android:text="8" android:id="@+id/button_num8"
  31. android:layout_width="match_parent" android:layout_height="wrap_content" />
  32. <Button android:text="9" android:id="@+id/button_num9"
  33. android:layout_height="wrap_content" android:layout_width="match_parent" />
  34. </TableRow>
  35. <TableRow>
  36. <Button android:text="+" android:id="@+id/button_plus"
  37. android:layout_width="match_parent" android:layout_height="wrap_content" />
  38. <Button android:text="-" android:id="@+id/button_sub"
  39. android:layout_width="match_parent" android:layout_height="wrap_content" />
  40. <Button android:text="=" android:id="@+id/button_amount"
  41. android:layout_height="wrap_content" android:layout_width="match_parent" />
  42. </TableRow>
  43. </TableLayout>
  44.  
  45. </LinearLayout>

第一種 使用Stack
原理就是把符號跟數字分別拆到個別的Stack,然後再put出來,依據符號進行計算。
  1. package npust.edu.klab;
  2.  
  3. import java.util.Stack;
  4.  
  5. import android.app.Activity;
  6. import android.os.Bundle;
  7. import android.view.View;
  8. import android.view.View.OnClickListener;
  9. import android.view.inputmethod.InputMethodManager;
  10. import android.widget.Button;
  11. import android.widget.EditText;
  12.  
  13. public class Calculator extends Activity {
  14.  
  15. @Override
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.main);
  19. // set all ui component.
  20. final EditText edtxt_result = (EditText) this
  21. .findViewById(R.id.editText_result);
  22. Button btn_amount = (Button) this.findViewById(R.id.button_amount);
  23. //to hide the virtual keyboard.
  24. InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
  25. imm.hideSoftInputFromWindow(edtxt_result.getWindowToken(), 0);
  26. // get all button then set a listener for general.
  27. Button[] btns = { (Button) this.findViewById(R.id.button_num1),
  28. (Button) this.findViewById(R.id.button_num2),
  29. (Button) this.findViewById(R.id.button_num3),
  30. (Button) this.findViewById(R.id.button_num4),
  31. (Button) this.findViewById(R.id.button_num5),
  32. (Button) this.findViewById(R.id.button_num6),
  33. (Button) this.findViewById(R.id.button_num7),
  34. (Button) this.findViewById(R.id.button_num8),
  35. (Button) this.findViewById(R.id.button_num9),
  36. (Button) this.findViewById(R.id.button_plus),
  37. (Button) this.findViewById(R.id.button_sub) };
  38.  
  39. OnClickListener generalOnClick = new OnClickListener() {
  40. public void onClick(View v) {
  41. // set the txt of editText plus the text of button.
  42. edtxt_result.setText(edtxt_result.getText().toString()
  43. + ((Button) v).getText());
  44. }
  45. };
  46.  
  47. for (Button btn : btns)
  48. btn.setOnClickListener(generalOnClick);
  49.  
  50. // calculate
  51. btn_amount.setOnClickListener(new OnClickListener() {
  52. public void onClick(View v) {
  53.  
  54. String formula = edtxt_result.getText().toString();
  55. // stacks for '+'、'-' and numbers.
  56. Stack symbols = new Stack();
  57. Stack nums = new Stack();
  58. // split by '+'、'-'
  59. String[] numAry = formula.toString().split("[\\+\\-/]");
  60. // set stacks.
  61. for (String num : numAry)
  62. nums.push(Integer.valueOf(num));
  63. for (char c : formula.toCharArray())
  64. if (c == '+' || c == '-')
  65. symbols.push(c);
  66. // calculate by symbol.
  67. int result = 0;
  68. while (!symbols.isEmpty()) {
  69. switch (symbols.pop()) {
  70. case '+':
  71. result += nums.pop();
  72. break;
  73. case '-':
  74. result -= nums.pop();
  75. break;
  76. }
  77. }
  78. // plus the last num in stack.
  79. result += nums.pop();
  80. if(result<0){
  81. edtxt_result.setText("");
  82. edtxt_result.setHint("不支援負數計算");
  83. }
  84. else
  85. edtxt_result.setText(result + "");
  86. }
  87. });
  88. }
  89. }

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

  1. package npust.edu.klab;
  2.  
  3.  
  4. import android.app.Activity;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.view.inputmethod.InputMethodManager;
  9. import android.widget.Button;
  10. import android.widget.EditText;
  11.  
  12. public class Calculator extends Activity {
  13.  
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18.  
  19. // set all ui component.
  20. final EditText edtxt_result = (EditText) this
  21. .findViewById(R.id.editText_result);
  22. Button btn_amount = (Button) this.findViewById(R.id.button_amount);
  23.  
  24. // to hide the virtual keyboard.
  25. InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
  26. imm.hideSoftInputFromWindow(edtxt_result.getWindowToken(), 0);
  27.  
  28. // get all button then set a listener for general.
  29. Button[] btns = { (Button) this.findViewById(R.id.button_num1),
  30. (Button) this.findViewById(R.id.button_num2),
  31. (Button) this.findViewById(R.id.button_num3),
  32. (Button) this.findViewById(R.id.button_num4),
  33. (Button) this.findViewById(R.id.button_num5),
  34. (Button) this.findViewById(R.id.button_num6),
  35. (Button) this.findViewById(R.id.button_num7),
  36. (Button) this.findViewById(R.id.button_num8),
  37. (Button) this.findViewById(R.id.button_num9),
  38. (Button) this.findViewById(R.id.button_plus),
  39. (Button) this.findViewById(R.id.button_sub) };
  40.  
  41. OnClickListener generalOnClick = new OnClickListener() {
  42. public void onClick(View v) {
  43. // set the txt of editText plus the text of button.
  44. edtxt_result.setText(edtxt_result.getText().toString()
  45. + ((Button) v).getText());
  46. }
  47. };
  48.  
  49. for (Button btn : btns)
  50. btn.setOnClickListener(generalOnClick);
  51.  
  52. // calculate
  53. btn_amount.setOnClickListener(new OnClickListener() {
  54. public void onClick(View v) {
  55. // reverse string to create a tree which grow to right side
  56. String formula = new StringBuffer(edtxt_result.getText().toString()).reverse().toString();
  57.  
  58. Node root = new Node(), now = root;
  59. int last_index_ofSymbol = 0;
  60. for (int i = 0; i < formula.toCharArray().length; i++) {
  61. if (formula.toCharArray()[i] == '+' || formula.toCharArray()[i] == '-') {
  62. now.value = formula.toCharArray()[i] + "";
  63. now.right = new Node();
  64. if(last_index_ofSymbol==0)
  65. now.right.value = formula.substring(last_index_ofSymbol, i);
  66. else
  67. now.right.value = formula.substring(last_index_ofSymbol+1, i);
  68. last_index_ofSymbol = i;
  69. now.left = new Node();
  70. now = now.left;
  71. } else if (i == formula.toCharArray().length - 1) {
  72. now.value = formula.substring(last_index_ofSymbol+1);
  73. }
  74. }
  75.  
  76. // calculate by symbol.
  77. int result = 0;
  78. result = Node.inOrder(root);
  79. // plus the last num in stack.
  80. if (result < 0) {
  81. edtxt_result.setText("");
  82. edtxt_result.setHint("不支援負數計算");
  83. } else
  84. edtxt_result.setText(result + "");
  85. }
  86. });
  87. }
  88. }
  89.  
  90. class Node {
  91. public Node() {
  92. value = "";
  93. left = null;
  94. right = null;
  95. }
  96.  
  97. String value;
  98. Node left;
  99. Node right;
  100. public static int inOrder(Node n){
  101. if(n!=null){
  102. if(n.value.equals("+"))
  103. return inOrder(n.left) + inOrder(n.right);
  104. else if(n.value.equals("-"))
  105. return inOrder(n.left) - inOrder(n.right);
  106. }
  107. return Integer.parseInt(n.value);
  108. }
  109. }
本來以為樹狀結構的話程式碼可以少寫很多,結果根本也沒有,而且一開始向右生長的樹被我寫成向左生長,所以減法一直算錯,自己還在那裏想半天。

1 則留言:

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

    但編譯器說明:

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

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

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

    回覆刪除