最近刚开始接触安卓编程,移动应用开发可以使用Java或者Kotlin语言,因为没有学过Kotlin,所以计算器的实现采用Java语言。要实现计算器的功能就需要将我们输入的算式(中缀式)转化为后缀式。这样方便计算。关于如何将中缀式转化为后缀式,大家可以参考其他文章。
Java代码
package com.example.caculate;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView textView; // 文本框
StringBuilder content = new StringBuilder(); //获取TextView里的内容
StringBuilder stringBuilder = new StringBuilder();
Stack<String> sta = new Stack<String>(); //符号栈
List<String> stack = new ArrayList<String>(); //后缀式的集合
Map<String, Integer> priority = new HashMap<String, Integer>(); //设置符号优先级
//数字0-9
private Button number_zero;
private Button number_one;
private Button number_two;
private Button number_three;
private Button number_four;
private Button number_five;
private Button number_six;
private Button number_seven;
private Button number_eight;
private Button number_nine;
//操作符
private Button operator_mod;
private Button operator_add;
private Button operator_back; //退一格
private Button operator_point;
private Button operator_equal;
private Button operator_clear; //清除
private Button operator_remove;
private Button operator_subtract;
private Button operator_multiply;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置符号优先级
priority.put("+", 1);
priority.put("-", 1);
priority.put("*", 0);
priority.put("/", 0);
priority.put("%", 0);
//TextView
textView = findViewById(R.id.textView);
//数字键
number_zero = findViewById(R.id.number_zero);
number_zero.setOnClickListener(this);
number_one = findViewById(R.id.number_one);
number_one.setOnClickListener(this);
number_two = findViewById(R.id.number_two);
number_two.setOnClickListener(this);
number_three = findViewById(R.id.number_three);
number_three.setOnClickListener(this);
number_four = findViewById(R.id.number_four);
number_four.setOnClickListener(this);
number_five = findViewById(R.id.number_five);
number_five.setOnClickListener(this);
number_six = findViewById(R.id.number_six);
number_six.setOnClickListener(this);
number_seven = findViewById(R.id.number_seven);
number_seven.setOnClickListener(this);
number_eight = findViewById(R.id.number_eight);
number_eight.setOnClickListener(this);
number_nine = findViewById(R.id.number_nine);
number_nine.setOnClickListener(this);
//算数符号
operator_mod =findViewById(R.id.operator_mod);
operator_mod.setOnClickListener(this);
operator_add =findViewById(R.id.operator_add);
operator_add.setOnClickListener(this);
operator_back = findViewById(R.id.operator_back);
operator_back.setOnClickListener(this);
operator_equal =findViewById(R.id.operator_equal);
operator_equal.setOnClickListener(this);
operator_clear =findViewById(R.id.operator_clear);
operator_clear.setOnClickListener(this);
operator_remove =findViewById(R.id.operator_remove);
operator_remove.setOnClickListener(this);
operator_subtract =findViewById(R.id.operator_subtract);
operator_subtract.setOnClickListener(this);
operator_multiply =findViewById(R.id.operator_multiply);
operator_multiply.setOnClickListener(this);
operator_point = findViewById(R.id.operator_point);
operator_point.setOnClickListener(this);
}
//重写按钮点击的click方法
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.number_zero:
content.append("0");
textView.setText(content);
break;
case R.id.number_one:
content.append("1");
textView.setText(content);
break;
case R.id.number_two:
content.append("2");
textView.setText(content);
break;
case R.id.number_three:
content.append("3");
textView.setText(content);
break;
case R.id.number_four:
content.append("4");
textView.setText(content);
break;
case R.id.number_five:
content.append("5");
textView.setText(content);
break;
case R.id.number_six:
content.append("6");
textView.setText(content);
break;
case R.id.number_seven:
content.append("7");
textView.setText(content);
break;
case R.id.number_eight:
content.append("8");
textView.setText(content);
break;
case R.id.number_nine:
content.append("9");
textView.setText(content);
break;
case R.id.operator_add:
inpu("+");
break;
case R.id.operator_subtract:
inpu("-");
break;
case R.id.operator_multiply:
inpu("*");
break;
case R.id.operator_remove:
inpu("/");
break;
case R.id.operator_mod:
inpu("%");
break;
case R.id.operator_point:
inpu(".");
break;
case R.id.operator_back: // 输入的内容后退一格
if (content.length()!=0){
content.deleteCharAt(content.length()-1); //删除最后一个字符
textView.setText(content);
}
break;
case R.id.operator_clear:
textView.setText(content.delete(0,content.length()));
break;
case R.id.operator_equal:
if (stack.size()!=0||sta.size()!=0){
sta.clear();
stack.clear();
}
String str ;
String first;
String primary = content.toString();
if(primary.length()==1){ // 当用户输入的字符串仅为一个运算符或者没有注入
if (!Character.isDigit(primary.charAt(0))){
textView.setText("");
break;
}
str = primary;
} else if(primary.length()==0){
str = primary;
break;
} else{
first = String.valueOf(primary.charAt(0));
if(first.equals("+")||first.equals("*")||first.equals("/")||first.equals("%")||first.equals(".")){
str = primary.substring(1,primary.length());
if (!Character.isDigit(primary.charAt(primary.length()-1))){ //判断字符串的结尾是否为数字
str = str.substring(0,str.length()-1);
}
} else{
if (!Character.isDigit(primary.charAt(primary.length()-1))){
str = primary.substring(0,primary.length()-1);
}else{
str = primary;
}
}
}
//将中缀表达式转换为后缀表达式
for (int i = 0; i < str.length(); i++) {
if (Character.isDigit(str.charAt(i))||String.valueOf(str.charAt(i)).equals(".")) {
stringBuilder.append(str.charAt(i));
if (i == str.length() - 1) {
stack.add(stringBuilder.toString());
stringBuilder.delete(0, stringBuilder.length());
}
} else {
stack.add(stringBuilder.toString());
stringBuilder.delete(0, stringBuilder.length());
if (!sta.empty()) {
for (int k = 0; k < sta.size(); k++) {
if (priority.get(String.valueOf(str.charAt(i))) >= priority.get(sta.peek())) {
stack.add(sta.pop());
if (sta.isEmpty()) {
sta.push(String.valueOf(str.charAt(i)));
break;
} else {
k--;
}
} else {
sta.push(String.valueOf(str.charAt(i)));
break;
}
}
} else {
sta.push(String.valueOf(str.charAt(i)));
}
}
if (i == str.length() - 1) {
while (!sta.isEmpty()) {
stack.add(sta.pop());
}
}
}
for (int p=0; p<stack.size(); p++){
if (stack.get(p).equals("")){
stack.remove(p);
}
}
for (int i = 0; i < stack.size(); i++) {
if (stack.get(i).equals("+") || stack.get(i).equals("-") || stack.get(i).equals("*")|| stack.get(i).equals("/") || stack.get(i).equals("%")) {
switch (stack.get(i)) {
case "*":
String sum = String.valueOf(Double.valueOf(stack.get(i - 2))* Double.valueOf(stack.get(i - 1)).intValue());
simplify(stack, i, sum);
i = 0;
break;
case "/":
if(Integer.parseInt(stack.get(i - 1))==0) { //被除数为零
stack.clear();
stack.add("格式错误");
break;
}
String a = String.valueOf(Double.valueOf(stack.get(i - 2))/ Double.valueOf(stack.get(i - 1)));
simplify(stack, i, a);
i = 0;
break;
case "+":
String b = String.valueOf(Double.valueOf(stack.get(i - 2)) + Double.valueOf(stack.get(i - 1)));
simplify(stack, i, b);
i = 0;
break;
case "-":
if(i==1) { //负号前面只有一个数
String minus = "-"+ stack.get(i - 1);
stack.remove(stack.get(i));
stack.remove(stack.get(i-1));
stack.add(0, minus);
break;
}
String c = String.valueOf(Double.valueOf(stack.get(i - 2)) - Double.valueOf(stack.get(i - 1)));
simplify(stack, i, c);
i = 0;
break;
case "%":
String d = String.valueOf(Double.valueOf(stack.get(i - 2)).intValue() % Double.valueOf(stack.get(i - 1)).intValue());
simplify(stack, i, d);
i = 0;
break;
}
}
}
content.delete(0,content.length());
content.append(stack.get(0));
textView.setText(content);
break;
}
}
//判断最后一个字符是否为算数运算符,并且算术运算符前不能为point :点;
public boolean check(String string){
if (string.equals("+")||string.equals("-")||string.equals("*")||string.equals("/")||string.equals("%")||string.equals(".")){
return true;
}else {
return false;
}
}
//计算后缀式的时候合并算数符号在内的所占的位置
public String simplify(List<String> list, int index, String para) {
list.remove(list.get(index));
list.remove(list.get(index - 1));
list.remove(list.get(index - 2));
list.add(index - 2, para);
return " ";
}
//数字后面只能加一个算数符号或者点
public View inpu(String operator){
if (content.length()==0){
content.append(operator);
textView.setText(content);
}else {
if (check(String.valueOf(content.charAt(content.length() - 1)))) {
content.replace(content.length() - 1, content.length(), operator);
textView.setText(content);
} else {
content.append(operator);
textView.setText(content);
}
}
return textView;
}
}
布局文件
UI界面主要采用了约束布局与线性布局结合的方式,可以提高开发效率。计算器按钮采用网格式布局,更方便实现。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
//将线性布局填充到整个界面
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
>
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" //权重是1,TextView占屏幕的1/4
android:gravity="center_vertical|end"
android:text="应该没有BUG"
android:textSize="50sp" />
<GridLayout
android:id="@+id/gridLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" //权重是1,TextView占屏幕的3/4
//创建一个5行4列的网格布局
android:rowCount="5"
android:columnCount="4"
>
<Button
android:id="@+id/operator_clear"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="C"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_back"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="De"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_mod"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="%"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_remove"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="÷"
android:textSize="50sp"/>
<Button
android:id="@+id/number_seven"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="7"
android:textSize="50sp"/>
<Button
android:id="@+id/number_eight"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="8"
android:textSize="50sp"/>
<Button
android:id="@+id/number_nine"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="9"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_multiply"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="x"
android:textSize="50sp"/>
<Button
android:id="@+id/number_four"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="4"
android:textSize="50sp"/>
<Button
android:id="@+id/number_five"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="5"
android:textSize="50sp"/>
<Button
android:id="@+id/number_six"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="6"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_subtract"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="—"
android:textSize="50sp"/>
<Button
android:id="@+id/number_one"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="1"
android:textSize="50sp"/>
<Button
android:id="@+id/number_two"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="2"
android:textSize="50sp"/>
<Button
android:id="@+id/number_three"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="3"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_add"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="+"
android:textSize="50sp"/>
<Button
android:id="@+id/number_zero"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="0"
android:layout_columnSpan="2"
android:textSize="50sp"/>
<Button
android:id="@+id/operator_point"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="."
android:textSize="50sp"/>
<Button
android:id="@+id/operator_equal"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="="
android:textSize="50sp"/>
</GridLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
运行截图
[外链图片转存中…(img-VrCBhL2f-1588467324713)]