小学四则运算APP 第三阶段冲刺
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars="vertical" android:paddingBottom="10dp" android:paddingTop="5dp" android:background="@drawable/b1"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:paddingLeft="8dp" android:paddingRight="8dp"> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <EditText android:id="@+id/editText" android:layout_width="fill_parent" android:layout_height="90dp" android:autoText="true" android:hint="@string/editText_hint_text" android:minHeight="60dp" android:background="@drawable/selector" android:paddingTop="10dp" android:paddingBottom="15dp" android:singleLine="false" android:scrollbars="vertical"/> <TextView android:id="@+id/tv" android:layout_alignRight="@id/editText" android:layout_alignBottom="@id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/kong" android:textColor="#CD0000"/> </RelativeLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:paddingTop="10dip" android:paddingBottom="5dp" > <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="(" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/left" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text=")" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/right" android:textStyle="bold" android:layout_marginRight="5dp" /> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Clean" android:layout_weight="1" android:background="@drawable/selector" android:id="@+id/ac" android:textStyle="bold" android:layout_marginRight="5dp" /> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Backspace" android:layout_weight="1" android:background="@drawable/selector" android:id="@+id/bs" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="5dp"> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="7" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num7" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="8" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num8" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="9" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num9" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="÷" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/divide" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:layout_weight="1" android:paddingBottom="5dp"> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="4" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num4" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="5" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num5" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="6" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num6" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="×" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/mul" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:layout_weight="1" android:paddingBottom="5dp"> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="1" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num1" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="2" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num2" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="3" android:layout_weight="1" android:background="@drawable/selector" android:textSize="30sp" android:id="@+id/num3" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="-" android:textSize="35sp" android:layout_weight="1" android:background="@drawable/selector" android:id="@+id/sub" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:layout_weight="1" android:paddingBottom="5dp" > <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="0" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/num0" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="." android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/pot" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="+" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/add" android:textStyle="bold" android:layout_marginRight="5dp"/> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="=" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:id="@+id/equ" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:layout_weight="1" android:paddingBottom="5dp"> <Button android:id="@+id/minus" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="+/-" android:layout_weight="1" android:textSize="30sp" android:background="@drawable/selector" android:textStyle="bold" android:layout_marginRight="5dp"/> </LinearLayout> </LinearLayout> </ScrollView>
Calculator.java
package com.manymore13.calc; import java.math.BigDecimal; import java.util.EmptyStackException; import java.util.Stack; import android.util.Log; // 测试匹配否 // 特殊加减乘除 + - × ÷ // 特殊正负 ﹢﹣ // 普通加减乘除正负 + - * / + - public class Calculator { private static String expression; // 后缀式 private String suffix; // 特殊左括号 final static char LEFT_NORMAL = '﹙'; // 特殊右括号 final static char RIGHT_NORMAL = '﹚'; // 特殊负号 final static char MINUS = '﹣'; // 特殊加号 final static char ADD = '+'; // 特殊乘法 final static char MUL = '×'; // 特殊除法 final static char DIV = '÷'; // 特殊减法 final static char SUB = '-'; // 特殊等于号 final static char equ = '='; public static String getExpression() { return expression; } // 返回后缀 public String getSuffix() { return suffix; } public void setExpression(String equation) { expression = equation; createSuffix(); } public Calculator(String equation) { expression = equation; createSuffix(); } public Calculator() { expression = ""; suffix = ""; } /** * 判断括号有没有匹配 * 匹配方法:遇到左括号进栈,遇到右括号出栈并且比对出栈的括号 * */ public boolean isBalanced() { Stack<Character> store = new Stack<Character>(); store.clear(); char c; for(int i=0; i<expression.length(); i++) { c = expression.charAt(i); switch(c) { case LEFT_NORMAL: { store.push(expression.charAt(i)); break; } case RIGHT_NORMAL: { if(store.isEmpty() || store.pop()!= LEFT_NORMAL) { return false; } break; } } } if(store.isEmpty()) { return true; } else { return false; } } private static boolean isOperator(char ope) { if(ope == ADD || ope==SUB ||ope == MUL || ope == DIV) { return true; } return false; } private static boolean isNum(char c) { if(c>='0' && c<='9') { return true; } return false; } // 中缀式转后缀式 public String createSuffix() { Stack<String> stack = new Stack<String>(); String exp = expression.trim(); String suf = ""; int i = 0; char c; while(i < exp.length()) { c = exp.charAt(i); if(c == LEFT_NORMAL) // 左括号 { stack.push(LEFT_NORMAL+""); } else if(isFit(c)) // 符合数字的一部分 { String num = ""; while(i<exp.length() && isFit(exp.charAt(i)) ) { num+=exp.charAt(i); i++; } suf += (num + " "); //后缀 i--; }else if(c == ADD || c == SUB || c == MUL ||c == DIV) // 运算符 { while(true) { if(stack.isEmpty()) { break; } if(stack.peek().equals(""+LEFT_NORMAL)) { break; } if(compare(stack.peek().charAt(0),c)) { break; } suf += (stack.pop()+" "); // 后缀 } stack.push(c+""); } else if(c == RIGHT_NORMAL) { while(!stack.isEmpty()) { if(stack.peek().equals(""+LEFT_NORMAL)) { stack.pop(); break; } suf += (stack.pop() + " "); // 后缀 } } i++; } while(!stack.isEmpty()) { suf += (stack.pop() + " "); // 后缀 } this.suffix = suf; return suf; } /** * 判断是否符合数字的一部分 * @param digit * @return 符合返回true 否则返回false */ private boolean isFit(char digit) { if(digit>='0' && digit<='9'||digit ==MINUS||digit=='.' ) { return true; } return false; } // 栈中运算符与将要读取的运算符作比较 // 返回true指示栈中运算符优先级大于将要读取运算符 // 其他的低于或等于都返回false private boolean compare(char stackOpe, char nextOpe) { int v1 = value(stackOpe); int v2 = value(nextOpe); if( v1 < v2) { return true; } return false; } // 运算符优先级 private int value(char ope) { if(ope==ADD || ope==SUB) { return 1; } else if(ope==MUL || ope==DIV) { return 2; } else { return 0; } } /** * @param suffix 后缀式 * @return 利用后缀式算出结果 */ public String getResult() { suffix = suffix.replace(MINUS, '-'); String[] str = suffix.split(" "); Stack<String> valueStack = new Stack<String>(); for(int i=0; i<str.length; i++) { // 遇到运算符出栈 if(str[i].equals(ADD+"") || str[i].equals(SUB+"") || str[i].equals(MUL+"") || str[i].equals(DIV+"")) { String rightNum; String leftNum; try { rightNum = valueStack.pop(); leftNum = valueStack.pop(); String result = calc(leftNum,rightNum,str[i]); valueStack.push(result); }catch(EmptyStackException empty) { return "算式出现异常"; } } else { // 遇到数字进栈 valueStack.push(str[i]); } } if(!valueStack.isEmpty()) { return valueStack.pop(); } return "栈为空 ,出现错误!"; } public static String calc(String leftNum, String rightNum, String ope) { BigDecimal bigLeftNum = null; BigDecimal bigRightnum = null; try { bigLeftNum = new BigDecimal(leftNum); bigRightnum = new BigDecimal(rightNum); }catch(NumberFormatException e) { return "算式出现异常"; } switch(ope.charAt(0)) { // 处理加法 case ADD:return bigLeftNum.add(bigRightnum).toString(); // 处理减法 case SUB:return bigLeftNum.subtract(bigRightnum).toString(); // 处理乘法 case MUL:return bigLeftNum.multiply(bigRightnum).toString(); // 处理乘法 case DIV: { if(bigRightnum.doubleValue()==0) { return "除数为零"; } // 20为小数点后的位数 String result = bigLeftNum.divide(bigRightnum,20,BigDecimal.ROUND_DOWN).toString(); int mark = 0; if( (mark = result.indexOf('.'))!=-1) { for(int i=mark; i<result.length(); i++) { if(result.charAt(i)!='0') { mark = i; } } Log.d("mark--1 :", mark+""); if(result.charAt(mark)=='.') { mark -= 1; } Log.d("mark--2 :", mark+""); Log.d("result", result.substring(0,mark+1)); result = result.substring(0,mark+1); return result; } else { return result; } } } return null; } // 测试括号匹配 - — public static void main(String[] s) { String str1 = "﹙5.3+3﹚×﹙3+8﹚"; String str2 = "[{}]{}"; String str3 = "({}{})"; String str4 = "16.2+(6.72-4.25)-3.72"; String str5 = "(((10+7)*(20/30))-(2*40))"; String str6 = "12"; Calculator cal = new Calculator(str1); System.out.println("匹配:"+cal.isBalanced()); System.out.println("后缀:"+cal.getSuffix()); String reult = cal.getResult(); System.out.println("结果: "+reult); } }
MycalcActivity.java
package com.manymore13.calc; import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MyCalcActivity extends Activity { AlertDialog.Builder mBuilder ; private List<Button> buttonList = new ArrayList<Button>(25); private Button[] num = new Button[10]; private Calculator cal = new Calculator(); private TextView tviewPrompt; private boolean legal = true; int[] Idnum = new int[] { R.id.num0, R.id.num1, R.id.num2, R.id.num3, R.id.num4, R.id.num5, R.id.num6, R.id.num7, R.id.num8, R.id.num9 }; private static EditText edit; private Button btnAdd; private Button btnSub; private Button btnMul; private Button btnDiv; private Button btnPot; private Button btnEqu; private Button btnBC; private Button btnAC; private Button btnLeft; private Button btnRight; private Button btnMinus; // 负号 private Button btnMoveLeft; private Button btnMoveRight; public static EditText getEdit() { return edit; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.findView(); // 屏蔽软键盘 这样做有个弊端,就是不能自动换行 // edit.setInputType(InputType.TYPE_NULL); // edit.setInputType(InputType.TYPE_DATETIME_VARIATION_NORMAL); edit.addTextChangedListener(new TextWatcher() { String str; @Override public void onTextChanged(CharSequence s, int start, int before, int count) { str = s.toString(); cal.setExpression(str); if(str.equals("")||(str.indexOf(Calculator.LEFT_NORMAL)==-1 &&str.indexOf(Calculator.RIGHT_NORMAL)==-1)) { legal = true; tviewPrompt.setText(R.string.kong); }else if(cal.isBalanced()) { System.out.println(cal.isBalanced()); legal = true; tviewPrompt.setText(R.string.legal); }else { legal = false; tviewPrompt.setText(R.string.wrongful); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); for(Button current:buttonList) { System.out.println(current.getText()); current.setOnClickListener(new btnOnclickListtenner()); } // 屏蔽软键盘 edit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); edit.setBackgroundColor(0x7f48D1CC); } }); edit.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); edit.setBackgroundColor(0x7f48D1CC); } }); } public void findView() { // 获取算式框的实例 edit = (EditText)findViewById(R.id.editText); // 获取数字按钮的实例 for(int i=0; i<=9; i++) { num[i] = (Button)findViewById(Idnum[i]); } tviewPrompt = (TextView)findViewById(R.id.tv); Collections.addAll(buttonList, num); btnAdd = (Button)findViewById(R.id.add); Collections.addAll(buttonList,btnAdd); btnSub = (Button)findViewById(R.id.sub); Collections.addAll(buttonList,btnSub); btnMul = (Button)findViewById(R.id.mul); Collections.addAll(buttonList,btnMul); btnDiv = (Button)findViewById(R.id.divide); Collections.addAll(buttonList,btnDiv); btnPot = (Button)findViewById(R.id.pot); Collections.addAll(buttonList,btnPot); btnEqu = (Button)findViewById(R.id.equ); Collections.addAll(buttonList,btnEqu); btnBC = (Button)findViewById(R.id.bs); Collections.addAll(buttonList,btnBC); btnAC = (Button)findViewById(R.id.ac); Collections.addAll(buttonList,btnAC); btnLeft = (Button)findViewById(R.id.left); Collections.addAll(buttonList, btnLeft); btnRight = (Button)findViewById(R.id.right); Collections.addAll(buttonList, btnRight); btnMinus = (Button)findViewById(R.id.minus); Collections.addAll(buttonList, btnMinus); } class btnOnclickListtenner implements OnClickListener { @Override public void onClick(View v) { // 获取EditText的编辑版 Editable edtTable = edit.getText(); // 获取光标位置 int where = edit.getSelectionStart(); String inputData = ""; switch(v.getId()) { case R.id.num0: { inputData = "0"; break; } case R.id.num1: { inputData = "1"; break; } case R.id.num2: { inputData = "2"; break; } case R.id.num3: { inputData = "3"; break; } case R.id.num4: { inputData = "4"; break; } case R.id.num5: { inputData = "5"; break; } case R.id.num6: { inputData = "6"; break; } case R.id.num7: { inputData = "7"; break; } case R.id.num8: { inputData = "8"; break; } case R.id.num9: { inputData = "9"; break; } // 全部清除 case R.id.ac: { inputData = ""; edit.setText(""); } // 退格键 case R.id.bs: { if(where >0) { edtTable.delete(where-1, where); } break; } case R.id.add: { inputData = Calculator.ADD+""; break; } case R.id.sub: { inputData = Calculator.SUB+""; break; } case R.id.mul: { inputData = Calculator.MUL+""; break; } case R.id.divide: { inputData = Calculator.DIV+""; break; } case R.id.pot: { inputData = "."; break; } case R.id.left: { inputData = Calculator.LEFT_NORMAL+""; break; } case R.id.right: { inputData = Calculator.RIGHT_NORMAL+""; break; } case R.id.minus: { inputData = Calculator.MINUS+""; break; } // 处理光标左移 //处理等于 case R.id.equ: { inputData = ""; String str = edtTable.toString(); where = str.length(); if(checkLegal(str)) { cal.setExpression(edtTable.toString()); String result = cal.getResult(); inputData = "\n"+Calculator.equ+result; } break; } } edtTable.insert(where, inputData); } // 检查运算式是否合格 public boolean checkLegal(String exp) { if( (legal && (!exp.equals(""))&&(exp.indexOf(Calculator.equ)==-1)) &&(exp.indexOf(Calculator.ADD)!=-1 ||exp.indexOf(Calculator.SUB)!=-1 ||exp.indexOf(Calculator.MUL)!=-1 ||exp.indexOf(Calculator.DIV)!=-1)) { return true; } return false; } } public boolean onCreateOptionsMenu(Menu menu) { menu.add(0,1,0,"关于"); menu.add(1,2,1,"退出"); return true; // 这里要返回true 否则菜单不显示 } @Override public boolean onOptionsItemSelected(MenuItem item) { mBuilder = new AlertDialog.Builder(this); if(item.getItemId()==1) { mBuilder.setMessage(R.string.abount).setTitle("关 于").show().setInverseBackgroundForced(true); } else { finish(); } return super.onOptionsItemSelected(item); } }