事情的严重性
实验六 第一个小项目
实验目的:
1.掌握布局的使用
2.学习事件处理
实验内容:
编写一个计算器程序,尽量多的实现按键功能
1.用GridLayout布局设计界面,如下图
2.设计按钮事件处理程序,实现计算器功能
作业提交:
网络教学平台,把项目包打包到一起上传,打包文件名“学号+姓名”,学号在前,姓名在后
MainActivity.java
package com.lxy.lxy_myapp_sy6;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.lxy.lxy_myapp_sy6.myClass.Calculator;
import com.lxy.lxy_myapp_sy6.myClass.MyKuoHao;
import java.net.IDN;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 推荐测试数据
*/
public class MainActivity extends AppCompatActivity {
// 文本框
private EditText textQuestion; // 显示题目
private EditText textResult; //显示答案
//数字1-9
private Button num1;
private Button num2;
private Button num3;
private Button num4;
private Button num5;
private Button num6;
private Button num7;
private Button num8;
private Button num9;
private Button num0;
//运算符
private Button optPlus; // +
private Button optSubtract; // -
private Button optMultiply; // *
private Button optDivide; // /
private Button optRemainder; // %
private Button optFraction; // 1/x
private Button optEqual; // =
//括号
private Button bntA; // (
private Button bntB; // )
//小数点
private Button symbolPoint; // .
//大操作
private Button mCE; // 清除 清除本次操作 不包括历史记录
private Button mDE; // 删除 删除一个符号 【数字+符号】
private Button mC; // 清除 全部
//小操作存储符号
private Button mClear; // 清除 存到strList中mIndex数字
private Button mRead; // 读取 存到strList中mIndex数字
private Button mSave; // 存储 存到strList中
private Button mPlus; // m+ strList中下一个数
private Button mSubtract; // m- strList中上一个数
// 当前存储、操作、定义数据
private StringBuffer strBufAll = new StringBuffer(); // 记录这一次的全部操作
private Stack<Integer> stSta = new Stack<>();
private String nowAns = "0.0";
private String nowDo = "";
private int leftKuoNum = 0; // 记录左括号
private int rightKuoNum = 0; // 记录右括号
// 小操作
private List<String> strListRes = new ArrayList<>(); // 存储全部结果值
private List<String> strListAll = new ArrayList<>(); // 存储全部操作
private List<Stack<Integer>> stStaAll = new ArrayList<>(); // 记录每一次的状态
private int mIndex = 0; // 记录strList中读取、存储、删除的下标
//关于栈记录的状态说明
// 初始 : 0
// 数字 : 1
// +— : 2
// ( : 3
// ) :4
// . : 5
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定文本
textQuestion = findViewById(R.id.text_question);
textResult = findViewById(R.id.text_result);
//设定textQuestion和textResult框不可编辑
textQuestion.setFocusable(false);
textQuestion.setFocusableInTouchMode(false);
textResult.setFocusable(false);
textResult.setFocusableInTouchMode(false);
//绑定数字按钮
num0 = (Button) findViewById(R.id.num_0);
num1 = (Button) findViewById(R.id.num_1);
num2 = (Button) findViewById(R.id.num_2);
num3 = (Button) findViewById(R.id.num_3);
num4 = (Button) findViewById(R.id.num_4);
num5 = (Button) findViewById(R.id.num_5);
num6 = (Button) findViewById(R.id.num_6);
num7 = (Button) findViewById(R.id.num_7);
num8 = (Button) findViewById(R.id.num_8);
num9 = (Button) findViewById(R.id.num_9);
//绑定小数点
symbolPoint = (Button) findViewById(R.id.symbol_point);
//绑定运算符
optPlus = findViewById(R.id.opr_plus); // +
optSubtract = findViewById(R.id.opt_subtract); // -
optMultiply = findViewById(R.id.opt_multiply); // *
optDivide = findViewById(R.id.opt_divide); // /
optRemainder = findViewById(R.id.opt_remainder); // %
optFraction = findViewById(R.id.opt_fraction); // 1/x
optEqual = findViewById(R.id.opt_equal); // =
// 绑定 左右括号
bntA = findViewById(R.id.bnt_a);
bntB = findViewById(R.id.bnt_b);
// 绑定大操作
mDE = findViewById(R.id.m_de); // de 删除一个符号【数字+符号】
mCE = findViewById(R.id.m_ce); // ce 清除本次操作 不包括历史记录
mC = findViewById(R.id.m_c); // c 清除全部
//绑定小操作存储
mClear = findViewById(R.id.m_clear); // mc
mRead = findViewById(R.id.m_read); // mr
mSave = findViewById(R.id.m_save); // ms
mPlus = findViewById(R.id.m_plus); // m+
mSubtract = findViewById(R.id.m_subtract); // m-
//初始化 显示栏
textQuestion.setText("");
textResult.setText("0.0");
stSta.push(0);
//数字按钮按下后,strBuf写入数字
num0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
textQuestion.setText("");
return;
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
if (strBufAll.charAt(strBufAll.length()-1) == '/' || strBufAll.charAt(strBufAll.length()-1) == '%' ){
Toast.makeText(MainActivity.this, "除数不能为0", Toast.LENGTH_LONG).show();
}
stSta.push(1);
strBufAll.append("0");
textQuestion.setText(strBufAll.toString());
}
});
num1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("1");
textQuestion.setText(strBufAll.toString());
}
});
num2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("2");
textQuestion.setText(strBufAll.toString());
}
});
num3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("3");
textQuestion.setText(strBufAll.toString());
}
});
num4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("4");
textQuestion.setText(strBufAll.toString());
}
});
num5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("5");
textQuestion.setText(strBufAll.toString());
}
});
num6.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("6");
textQuestion.setText(strBufAll.toString());
}
});
num7.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
Toast.makeText(new MainActivity(), "请输入符号", Toast.LENGTH_LONG).show();
return;
}
stSta.push(1);
strBufAll.append("7");
textQuestion.setText(strBufAll.toString());
}
});
num8.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("8");
textQuestion.setText(strBufAll.toString());
}
});
num9.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
if (stSta.peek() == 4) {
myShowToast(stSta.peek());
return;
}
stSta.push(1);
strBufAll.append("9");
textQuestion.setText(strBufAll.toString());
}
});
// 小数点
symbolPoint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() != 1) {
myShowToast(stSta.peek());
// . 前面不能不是数字
return;
}
boolean isPoint = false;
for (int i=strBufAll.length()-1; i>0; i--){
if (strBufAll.charAt(i) == '.'){
isPoint = true;
break;
}
if (strBufAll.charAt(i)>'9' || strBufAll.charAt(i) < '0'){
break;
}
}
if (!isPoint){
strBufAll.append(".");
textQuestion.setText(strBufAll.toString());
stSta.push(5);
}
else{
Toast.makeText(MainActivity.this, "数字不能有两个小数点",Toast.LENGTH_LONG).show();
}
}
});
// 大操作
// 删除一个字符
mDE.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() == 0) {
myShowToast(stSta.peek());
return;
}
// 不为空
strBufAll.deleteCharAt(strBufAll.length() - 1);
textQuestion.setText(strBufAll.toString());
stSta.pop();
}
});
// 删除一组字符 123、32、2、+、%
mCE.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// 删除当前的这个 不清空存储的
textResult.setText("0.0");
textQuestion.setText("");
strBufAll = new StringBuffer("");
stSta = new Stack<>();
stSta.push(0);
nowAns = "0.0";
nowDo = "";
leftKuoNum = 0;
rightKuoNum = 0;
}
});
// 全部清空 包括记录 相当于初始化
mC.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
strBufAll = new StringBuffer("");
stSta = new Stack<>();
textQuestion.setText("");
textResult.setText("0.0");
strListRes = new ArrayList<>();
strListAll = new ArrayList<>();
stStaAll = new ArrayList<>();
mIndex = 0;
leftKuoNum = 0;
rightKuoNum = 0;
nowAns = "0.0";
nowDo = "";
stSta.push(0);
}
});
//小操作
// 删除存储中一次操作全过程 以及 结果 以及 栈
mClear.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (strListAll.size() == 0) {
return;
}
strBufAll = new StringBuffer("");
stSta = new Stack<>();
textResult.setText("0.0");
textQuestion.setText("");
strListRes.remove(mIndex);
strListAll.remove(mIndex);
stStaAll.remove(mIndex);
mIndex = 0;
stSta.push(0);
}
});
//equation
// 效果和m+相同 但是m+会改变mIndex
mRead.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (strListAll.size() == 0) {
return;
}
String qu = strListAll.get(mIndex);
String res = strListRes.get(mIndex);
stSta = stStaAll.get(mIndex);
strBufAll = new StringBuffer(qu);
textQuestion.setText(qu);
textResult.setText(res);
}
});
// 将当前算式+结果存入 无结果的 存""
mSave.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (strBufAll.toString().equals("")) {
strListAll.add(nowDo);
} else {
strListAll.add(strBufAll.toString());
}
mIndex = 0;
strListRes.add(textResult.getText().toString());
stStaAll.add(stSta);
}
});
mPlus.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (strListAll.size() == 0) {
return;
}
mIndex++;
if (mIndex >= strListAll.size()) {
mIndex = 0;
}
String qu = strListAll.get(mIndex);
String res = strListRes.get(mIndex);
stSta = stStaAll.get(mIndex);
strBufAll = new StringBuffer(qu);
textQuestion.setText(qu);
textResult.setText(res);
}
});
mSubtract.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (strListAll.size() == 0) {
return;
}
mIndex--;
if (mIndex < 0) {
mIndex = strListAll.size() - 1;
}
String qu = strListAll.get(mIndex);
String res = strListRes.get(mIndex);
stSta = new Stack<>();
stSta = stStaAll.get(mIndex);
strBufAll = new StringBuffer(qu);
textQuestion.setText(qu);
textResult.setText(res);
}
});
//栈 end ---------
*/
// 括号
bntA.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
System.out.println(stSta);
if (stSta.peek() == 1 || stSta.peek() == 4) {
myShowToast(stSta.peek());
// ( 前面不能为数字 和 ) 必须是*
return;
}
if (stSta.peek() == 0) {
textResult.setText("0.0");
}
stSta.push(3);
leftKuoNum++;
strBufAll.append("(");
textQuestion.setText(strBufAll.toString());
}
});
bntB.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// ) 前面不能是* 也不能是空 也必须有可以匹配的(
if (stSta.peek() == 0 || stSta.peek() == 2 || leftKuoNum <= rightKuoNum) {
myShowToast(stSta.peek());
return;
}
stSta.push(4);
rightKuoNum++;
strBufAll.append(")");
textQuestion.setText(strBufAll.toString());
}
});
//新c类 start 【支持()】 ------------
///*
// 加 符号前面不能是 空 |(
optPlus.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
myShowToast(stSta.peek());
return;
}
stSta.push(2);
strBufAll.append("+");
textQuestion.setText(strBufAll.toString());
}
});
//减
optSubtract.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
myShowToast(stSta.peek());
return;
}
stSta.push(2);
strBufAll.append("-");
textQuestion.setText(strBufAll.toString());
}
});
//乘
optMultiply.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
myShowToast(stSta.peek());
return;
}
stSta.push(2);
strBufAll.append("*");
textQuestion.setText(strBufAll.toString());
}
});
//除
optDivide.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
myShowToast(stSta.peek());
return;
}
stSta.push(2);
strBufAll.append("/");
textQuestion.setText(strBufAll.toString());
}
});
// 余
optRemainder.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (stSta.peek() == 0 || stSta.peek() == 3 || stSta.peek() == 2 || stSta.peek() == 5) {
myShowToast(stSta.peek());
return;
}
stSta.push(2);
strBufAll.append("%");
textQuestion.setText(strBufAll.toString());
}
});
//等于
optEqual.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("====start====");
System.out.println(nowDo);
System.out.println(stSta);
int iss = stSta.peek();
if (stSta.peek() == 0 || stSta.peek() == 2 || stSta.peek() == 3 || stSta.peek() == 5 ) {
myShowToast(iss);
return;
}
if (leftKuoNum != rightKuoNum){
Toast.makeText(MainActivity.this, "括号没完", Toast.LENGTH_LONG).show();
return;
}
try {
nowAns = myKuoHaoTest();
} catch (Exception e) {
Toast.makeText(MainActivity.this,"!警告 有问题!",Toast.LENGTH_LONG).show();
Toast.makeText(MainActivity.this,""+e,Toast.LENGTH_LONG).show();
System.out.println(e);
//e.printStackTrace();
}
nowDo = strBufAll.toString();
textResult.setText(nowAns);
leftKuoNum = 0;
rightKuoNum = 0;
stSta = new Stack<>();
stSta.push(0);
strBufAll = new StringBuffer("");
System.out.println("=====end====");
}
});
//新c类 end ---------
//*/
}
// c类
public String myKuoHaoTest() throws Exception {
MyKuoHao myKuoHao = new MyKuoHao();
String ans = myKuoHao.getAnsKuoHao(strBufAll.toString());
return ans;
}
public void myShowToast(int preSta) {
switch (preSta) {
case 0:
Toast.makeText(MainActivity.this, "请先输入数字", Toast.LENGTH_LONG).show();
break;
case 1:
Toast.makeText(MainActivity.this, "不可以在数字后直接输入括号", Toast.LENGTH_LONG).show();
break;
case 2:
Toast.makeText(MainActivity.this, "注意格式", Toast.LENGTH_LONG).show();
break;
case 3:
Toast.makeText(MainActivity.this, "前面是左括号", Toast.LENGTH_LONG).show();
break;
case 4:
Toast.makeText(MainActivity.this, "前面是右括号", Toast.LENGTH_LONG).show();
break;
case 5:
Toast.makeText(MainActivity.this, "小数点后只能是数字", Toast.LENGTH_LONG).show();
break;
default:
}
}
}
MyKuoHao.java
package com.lxy.lxy_myapp_sy6.myClass;
import java.util.Stack;
public class MyKuoHao {
public MyKuoHao() {
}
public String getAnsKuoHao(String str) throws Exception {
//String s = "(1 + 2^3!-4)*(5!-(6-( 7-(89-0!))))#";// 2013
//strBufAll.append("#");
String ans;
String s = str + "#";
StringBuffer rpn = new StringBuffer();
//try {
float ansNum = calcExpression(s, rpn);
System.out.println("结果:" + calcExpression(s, rpn));
System.out.println("逆波兰表达式:" + rpn);
System.out.println("\n计算逆波兰表达式:");
calcExpressionRpn(rpn.toString());
ans = String.valueOf(ansNum);
return ans;
//textResult.setText(String.valueOf(ans));
//} catch (Exception e) {
// e.printStackTrace();
//}
//return "";
}
private Stack<Character> optr = new Stack<Character>();// 操作符栈
private Stack<Float> opnd = new Stack<Float>();// 操作数栈
private final Character END_Character = '#';// 输入表达式的结束字符
public final int ADD = 0, SUB = 1, MUL = 2, DIV = 3, MOD = 4, POW = 5, FAC = 6, L_P = 7, R_P = 8, EOF = 9;
public final char[][] PRI = {//运算符优先等级 [栈顶]'levle'[当前]
// |----------------当前运算符----------------|
// + - * / % ^ ! ( ) #(结束字符)
/* + */ {'>','>','<','<','<','<','<','<','>','>'},
/* - */ {'>','>','<','<','<','<','<','<','>','>'},
/* 栈 * */ {'>','>','>','>','>','<','<','<','>','>'},
/* 顶 / */ {'>','>','>','>','>','<','<','<','>','>'},
/* 运 % */ {'>','>','>','>','>','<','<','<','>','>'},
/* 算 ^ */ {'>','>','>','>','>','>','<','<','>','>'},
/* 符 ! */ {'>','>','>','>','>','>','>',' ','>','>'},
/* ( */ {'<','<','<','<','<','<','<','<','=',' '},
/* ) */ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/* # */ {'<','<','<','<','<','<','<','<',' ','='}
};
/**
* 中缀表达式计算,程序核心部分
* @param expression
* 输入的有效中缀表达式
* @param RPN
* 输出的逆波兰表达式(Reverse Polish Notation)
* @return
*/
public float calcExpression(String expression, StringBuffer RPN) throws Exception {
// 初始时操作符栈压入开始标识符,与结束字符对应
optr.push(END_Character);
// 剔除表达式中的空格
expression = removeSpace(expression);
int i = 0;// 表示读取表示式的位置
while (!optr.empty()) {
char currenSymbol = expression.charAt(i);// 当前扫描到的表达式符号
if (Character.isDigit(currenSymbol)) {
i = readNumber(expression, i, opnd);// 读入(可能多位的)操作数
RPN.append(opnd.peek() + " ");// 计入逆波兰表达式
} else {
switch (orderBetween(optr.peek(), currenSymbol)) {
case '>':// 栈顶运算符的优先级大于当前运算符,则1.取出操作符栈顶运算符,2.取出数据栈中的一个或多个数据(取决于运算符的类型),3.运算并把结果压入数据栈中
char op = optr.pop();// 取出栈顶操作符
RPN.append(op + " ");// 当操作符可以计算时计入逆波兰表达式,与逆波兰表达式的计算过程恰好吻合
Calculator ca = new Calculator();// 基本计算操作对象
if ('!' == op) {// 一元运算符的计算
float number = opnd.pop();// 取出操作数栈顶数值
System.out.println("计算过程:" + "[" + number + "]" + "" + op + "=" + "[" +ca.calcu(number, op) +"]" );
opnd.push(ca.calcu(number, op));// 计算并将结果入栈
} else {// 二元运算符的计算
float number2 = opnd.pop();// 取出操作数栈顶数值
float number1 = opnd.pop();// 取出操作数栈顶数值
System.out.println("计算过程:" + "[" + number1 + "]" + "" + op + "" + "[" + number2 + "]" + "=" + "[" +ca.calcu(number1, op, number2) + "]");
opnd.push(ca.calcu(number1, op, number2));// 计算并将结果入栈
}
break;
case '<':// 栈顶运算符的优先级小于当前运算符,计算推迟,当前运算符入栈
optr.push(currenSymbol);
i++;
break;
case '=':// 栈顶运算符的优先级等于当前运算符,脱括号并接收下一个字符
optr.pop();
i++;
break;
case ' ':
throw new Exception("ERROR");
}
}
}
return opnd.pop();// 操作数栈的最后一个元素即为需要的结果
}
/**
* 只关注于求中缀表达式的接口
* @param expression
* @return
* @throws Exception
*/
public float calcExpression(String expression) throws Exception {
return calcExpression(expression, new StringBuffer());
}
/**
* 对逆波兰表达式进行计算
* @param rpn
* @return
* @throws Exception
*/
public float calcExpressionRpn(String rpn) throws Exception{
String[] chs = rpn.split(" ");
int i = 0;
int chLength = chs.length;
while(i < chLength) {
Calculator ca = new Calculator();// 基本计算操作对象
if( convertStrToDigit(chs[i]) != null ) {// 操作数直接入栈
opnd.push(convertStrToDigit(chs[i]));
} else {
char op = chs[i].charAt(0);
if("!".equals( chs[i] )) {
float number = opnd.pop();
opnd.push(ca.calcu(number, op));
System.out.println("计算过程:" + "[" + number + "]" + "" + op + "=" + "[" +ca.calcu(number, op) +"]" );
} else {
float number2 = opnd.pop();// 取出操作数栈顶数值
float number1 = opnd.pop();// 取出操作数栈顶数值
System.out.println("计算过程:" + "[" + number1 + "]" + "" + op + "" + "[" + number2 + "]" + "=" + "[" +ca.calcu(number1, op, number2) + "]");
opnd.push(ca.calcu(number1, op, number2));// 计算并将结果入栈
}
}
i++;
}
return opnd.pop();
}
/**
* 将字符串转化为浮点数
* @param str
* @return
*/
private Float convertStrToDigit(String str) {
try{
float num = Float.valueOf(str);
return num;
} catch(Exception e){
return null;
}
}
/**
* 将char型的数字字符转为浮点型数据
* @param ch
* @return
*/
private float CharToFloat(char ch) {
return Float.valueOf("" + ch);
}
/**
* 将起始为i的子串解析为数值,并存入操作数栈中
* @param expression 表达式
* @param i 开始解析的位置
* @param stk 将解析完毕的数值存入此栈中
* @return 该数值解析完毕后,返回表达式需要解析的下一个位置
* @throws Exception 解析错误
*/
private int readNumber(String expression, int i, Stack<Float> stk) throws Exception {
stk.push(CharToFloat(expression.charAt(i++)));// 当前数位对应的数值进栈
char op = expression.charAt(i); // 读取下一个字符
while (Character.isDigit(op)) {// 只要后续还有紧邻的数字
stk.push(stk.pop() * 10 + CharToFloat(op));// 弹出原操作数并追加新数位后,新数值重新入栈
op = expression.charAt(++i);// 下一个字符
}
if ('.' != op)
return i;// 如果最后一个数字后面不是小数点,说明解析完成,则返回当前位置
op = expression.charAt(++i);
float fraction = 1;
while (Character.isDigit(op)) {
stk.push(stk.pop() + CharToFloat(op) * (fraction /= 10));
op = expression.charAt(++i);
}
if ('.' == op)
throw new Exception("ERROR");// 如果还有小数点则错误
return i;// 返回当前解析字符的位置
}
/**
* 根据运算符获取在优先级表中的秩(RANK)
* @param op
* @return
* @throws Exception
*/
private int getOperRank(char op) throws Exception {
switch (op) {
case '+':
return ADD;
case '-':
return SUB;
case '*':
return MUL;
case '/':
return DIV;
case '%':
return MOD;
case '^':
return POW;
case '!':
return FAC;
case '(':
return L_P;
case ')':
return R_P;
case '#':
return EOF;
default:
throw new Exception("ERROR");
}
}
/**
* 比较栈顶和当前字符的优先级
* @param peekOptr 栈顶运算符
* @param currenOptr 当前扫描到的运算符
* @return 优先级表中的数据项
* @throws Exception
*/
private Character orderBetween(Character peekOptr, char currenOptr) throws Exception {
return PRI[getOperRank(peekOptr)][getOperRank(currenOptr)];
}
/**
* 剔除字符串之间的空格
* @param str
* @return
*/
public String removeSpace(String str) {
char[] chs = str.toCharArray();
StringBuffer newStr = new StringBuffer();
int i = 0;
while (i < str.length()) {
if (' ' != chs[i]) {
newStr.append(chs[i]);
}
i++;
}
return newStr.toString();
}
}
Calculator.java
package com.lxy.lxy_myapp_sy6.myClass;
public class Calculator {
public float calcu(float n, char op) throws Exception {
return fact(n);// 这里只有阶乘一个一元运算符
}
/**
* 二元运算符
*
* @param a
* 操作数1
* @param op
* 操作符
* @param b
* 操作数2
* @return 结果浮点型
* @throws Exception
*/
public float calcu(float a, char op, float b) throws Exception {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return div(a, b);
case '%':
return mod(a, b);
case '^':
return (float) Math.pow(a, b);
default:
throw new Exception("ERROR");
}
}
private float div(float a, float b) throws Exception {
if (b == 0)
throw new Exception("除数不能为0!");
return a / b;
}
// 取余
private float mod(float a, float b) throws Exception {
if (b == 0)
throw new Exception("除数不能为0!");
return a % b;
}
// 阶乘 n!(n<=20)
private float fact(float n) throws Exception {
if (n < 0)
throw new Exception("阶乘运算数不能为负数!");
if (n > 34)
throw new Exception("阶乘数不能超过34,否则越界!");// 可以考虑改进以使计算更大数值的阶乘
if (n == 0)
return 1;// 0!=1
int num = (int) n;
if (num == n) {// n为整数
float result = 1;
while (num > 0) {
result *= num--;
}
return result;
} else
throw new Exception("阶乘运算数必须为整数!");
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="30dp">
<EditText
android:id="@+id/text_question"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@null"
android:textSize="15pt"
android:layout_marginTop="10dp"
android:gravity="end"
/>
<EditText
android:id="@+id/text_result"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginTop="10dp"
android:background="@null"
android:textSize="43dp"
android:gravity="end"
/>
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:columnCount="5"
android:orientation="horizontal"
android:rowCount="6">
<Button
android:id="@+id/m_clear"
style="@style/bnt_3"
android:text="@string/mc" />
<Button
android:id="@+id/m_read"
style="@style/bnt_3"
android:text="@string/mr" />
<Button
android:id="@+id/m_save"
style="@style/bnt_3"
android:text="@string/ms" />
<Button
android:id="@+id/m_plus"
style="@style/bnt_3"
android:text="@string/m_plus" />
<Button
android:id="@+id/m_subtract"
style="@style/bnt_3"
android:text="@string/m_subtract" />
<Button
android:id="@+id/m_de"
style="@style/bnt_1"
android:text="DE" />
<Button
android:id="@+id/m_ce"
style="@style/bnt_1"
android:text="@string/ce" />
<Button
android:id="@+id/m_c"
style="@style/bnt_1"
android:text="@string/c" />
<Button
android:id="@+id/bnt_a"
style="@style/bnt_1"
android:text="(" />
<Button
android:id="@+id/bnt_b"
style="@style/bnt_1"
android:text=")" />
<Button
android:id="@+id/num_7"
style="@style/bnt_2"
android:text="7"
android:textSize="20dp" />
<Button
android:id="@+id/num_8"
style="@style/bnt_2"
android:text="8" />
<Button
android:id="@+id/num_9"
style="@style/bnt_2"
android:text="9" />
<Button
android:id="@+id/opt_divide"
style="@style/bnt_2"
android:text="/" />
<Button
android:id="@+id/opt_remainder"
style="@style/bnt_2"
android:text="%" />
<Button
android:id="@+id/num_4"
style="@style/bnt_2"
android:text="4" />
<Button
android:id="@+id/num_5"
style="@style/bnt_2"
android:text="5" />
<Button
android:id="@+id/num_6"
style="@style/bnt_2"
android:text="6" />
<Button
android:id="@+id/opt_multiply"
style="@style/bnt_2"
android:text="*" />
<Button
android:id="@+id/opt_fraction"
style="@style/bnt_2"
android:textSize="20dp"
android:text="/x" />
<Button
android:id="@+id/num_1"
style="@style/bnt_2"
android:text="1" />
<Button
android:id="@+id/num_2"
style="@style/bnt_2"
android:text="2" />
<Button
android:id="@+id/num_3"
style="@style/bnt_2"
android:text="3" />
<Button
android:id="@+id/opt_subtract"
style="@style/bnt_2"
android:text="-" />
<Button
android:id="@+id/opt_equal"
android:layout_width="64dp"
android:layout_height="126dp"
android:layout_rowSpan="2"
android:textSize="25dp"
android:layout_margin="3dp"
android:text="=" />
<Button
android:id="@+id/num_0"
android:layout_height="60dp"
android:layout_columnSpan="2"
android:layout_gravity="fill_horizontal"
android:layout_margin="3dp"
android:text="0"
android:textSize="25dp" />
<Button
android:id="@+id/symbol_point"
style="@style/bnt_2"
android:text="." />
<Button
android:id="@+id/opr_plus"
style="@style/bnt_2"
android:text="+" />
</GridLayout>
</LinearLayout>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#D2C8FF</color>
<color name="purple_500">#BEB0FF</color>
<color name="purple_700">#2D00F8</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
strings.xml
<resources>
<string name="app_name">lxy计算器</string>
<string name="m_subtract">M-</string>
<string name="m_plus">M+</string>
<string name="ms">MS</string>
<string name="mr">MR</string>
<string name="mc">MC</string>
<string name="delete">back</string>
<string name="ce">CE</string>
<string name="c">C</string>
</resources>
style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="bnt_1">
<!--<item name=""-->
<item name="android:layout_height">60dp</item>
<item name="android:layout_width">64dp</item>
<item name="android:layout_margin">3dp</item>
</style>
<!--number-->
<style name="bnt_2">
<item name="android:layout_height">60dp</item>
<item name="android:layout_width">64dp</item>
<item name="android:layout_margin">3dp</item>
<item name="android:textSize">25dp</item>
</style>
<style name="bnt_3">
<item name="android:layout_height">45dp</item>
<item name="android:layout_width">64dp</item>
<item name="android:layout_margin">3dp</item>
<item name="android:textSize">15dp</item>
</style>
</resources>
安卓计算机-sy6
参考
安卓布局方面
https://blog.csdn.net/qq_29656961/article/details/77977361
https://blog.csdn.net/wintershii/article/details/81663455
算法方面
https://blog.csdn.net/wj1243008609/article/details/82348654