1. 前言
这是我的第一个安卓app,从界面到算法都是自己写的,期间经历了各种各样的bug,也学到的各种各样的知识,加深了对Java的使用,也了解了如何写一个Android应用。因为我Java也才入门,安卓更不用说(第一行代码第三章都没看完),所以代码写的肯定非常粗糙,望大家谅解。后期我会对其进行改进,也会上传到此博客
2. 准备
1. 编译器:Android Studio
虽说AndroidStudio有很多不如人意的地方(主要还是谷歌是一个404小公司),特别是gradle。但是其作为现在谷歌力推的编译器,还是很值得信赖的。基于Idea,所以界面、插件等方面都不用说,而且从Idea过来简直就是秒适应(毕竟他就相当于一个加强版Idea)。所以我个人推荐AndroidStudio。
2. 所需知识:
- 有一个简单的Java基础。
我也就学到异常和泛型这块,IO、多线程都没学 - 对Android开发有一个简单的了解
我是看第一行代码看到第三章基础空间以及布局就开始写了 - 对计算器算法的大致了解
中缀表达式转后缀表达式,后缀表达式的运算
3. 学会使用百度谷歌等搜索引擎
很多东西书上没讲,你不知道怎么实现,就直接百度或者google,找到别人的博客,然后好好看一遍,就算你看不懂,但是一定要看一遍,对其有一个大致的了解
4. 会使用AndroidStudio
至少懂得如何使用快捷键,懂得编译器界面上各个部分干嘛的
3. 实现效果,截图
1. 实现效果
- 能实现表达式的运算(废话,好歹是个计算器)
- 当你表达式存在问题时,不让你输入,或者不让你按下等号,并且某些情况会提示你
- 能对负数进行计算
- 有些简单的自动补全功能
- 能抛出异常
2. 截图
代码部分
1. 界面
1. 使用百分比布局
我选择的是百分比界面,但是由于百分比布局是新增的布局,所以你得手动添加其相应的依赖
- 打开
app/build.gradle
文件,在dependencies闭包中添加这样一行代码
dependencies {
implementation 'com.android.support:percent:28.0.0-alpha3'
}
-
添加完毕后,编辑面板顶部会出现一行提示,点击Sync now稍等片刻即可
2. button周边的边框
因为Android对button不能通过设置属性来达到显示边框的功能,所以我们只能创建一个图片文件,在图片中设置背景色以及边框的宽度和颜色,然后把button的background属性设置为对应图片
- 首先在
app/src/main/res/drawable
文件夹中新建一个Drawable resource file - 在弹出的窗口中设置文件名,文件名随意,但是要简单易懂,而且编译器不报错,例如我设置的
shape_blue_bg
- 然后切换到text视图,把代码修改为
一定要把下面代码中的注释删掉
//设置背景颜色,也就是你按键想要显示的颜色
//设置边框的颜色
- 然后再在你的布局文件(例如
app/src/main/res/layout/activity_main.xml
)中,对需要显示边框的button中添加设置背景这行代码
一定要把下面代码中的注释删掉
3. 实现button点击变色功能
- 首先在
app/src/main/res/drawable
文件夹中新建一个Drawable resource file,随意起名,例如我的click_blue - 把代码修改为
一定要把下面代码中的注释删掉
//当button被点击时
//当button未被点击时
- 你可以看到他需要两个drawable文件,一个是点击时的显示效果,一个是未点击时的显示效果,而在设置边框时还只创建了一个文件,也就是他不点击时的文件,接下来,我们还得创建一个跟他一样的文件,只是颜色不同而已
- 创建一个边框背景文件,随意命名
- 把代码修改为如下
- 然后再在你的布局文件(例如
app/src/main/res/layout/activity_main.xml
)中,对需要显示边框的button中添加设置背景这行代码
一定要把下面代码中的注释删掉
4. 隐藏app默认自带标题栏
- 在代码中,在onCreate()中,在super.onCreate(savedInstanceState)之后setContentView(R.layout.activity_main)之前添加
// 隐藏标题栏
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
}
5. 隐藏系统通知栏
- 在上面一样的地方,添加
// 隐藏通知栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
6. 修改app名称
- 在
app/src/java/res/values/strings.xml
文件中将第二行(一般默认是第二行,不是第二行的话就在其他地方找,反正编辑器一定会自动创建这行代码的)
小柯基的calculator //“小柯基的calculator”就是我的app名称,你可以换成任何自己想要的名字
7. 修改app图标
因为篇幅文体我就不再这说了,分享博客地址
https://blog.csdn.net/zhangkaidsy/article/details/74852470
8. 将默认字体修改为非衬线字体
由于默认字体我觉得有点粗了,而网上的使用极细字体的方法又太细了,所以我就想到了修改字体的方法,还是在layout设置布局的xml文件中,找到你要修改字体的组件,添加一行android:typeface="sans"
详情见https://blog.csdn.net/l_lhc/article/details/51769245
9. 字体能适应显示框而改变大小
大家在很多app中都看到过一个功能,就是你输入的文字,能随着你输入的文字的数量而快占满显示框的时候,自动缩小字体以适应显示框
- 同样是在显示布局的文件中,在显示组件中添加一行代码
- 但是这种方法存在一个问题,就是它自动适应输入框大小,就是说,你的输入框有多大,他显示的字体就有多大,所以我们得对他做个限制。限制最大字体和最小字体以及每次变化的字体的大小
10. 关于组件之间配色问题
自己百度(手动doge)
11. 代码
layout/activity_main.xml
values/strings.xml
小柯基的calculator
AC
+/-
=
+
-
*
/
.
0
1
2
3
4
5
6
7
8
9
(
)
%
删除
C
values/styles.xml
drawable/click_blue.xml
drawable/click_blue_light.xml
\
drawable/click_white.xml
\
drawable/click_yellow.xml
\
drawable/shape_click_blue_bg.xml
drawable/shape_white_bg.xml
drawable/shape_yellow_bg.xml
活动的代码
1. 异常处理
- 当输出的结果有问题时,抛出异常,然后显示Error
- 当左括号数目等于或者小于右括号时,不然输入右括号,而且按等号不会运算,提示括号不匹配
- 当前面是符号,然后输入减号默认添加'('当负号处理
- 实现输入是'数字(数字'时,当乘法处理
···还有很多功能就不一一列举了
2. 点击时手机震动
- 首先在AndroidManifest.xml中添加震动权限
- 新建class文件,命名为
Vibrate
代码如下
package com.example.calculator;
import android.content.Context;
import android.os.Vibrator;
/**
* Created by littlecorgi_a1203991686 on 2018/08/02 15:56.
*/
public class Vibrate {
private static Vibrator vibrator;
/**
* 简单震动
* @param context 调用震动的Context
* @param millisecond 震动的时间,毫秒
*/
@SuppressWarnings("static-access")
public static void vSimple(Context context, int millisecond) {
vibrator = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
vibrator.vibrate(millisecond);
}
/**
* 停止震动
*/
public static void stop() {
if (vibrator != null) {
vibrator.cancel();
}
}
}
3. MainActivity代码
package com.example.calculator;
import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView textview;
private StringBuilder sb = new StringBuilder();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏标题栏
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
}
// 隐藏通知栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
// 定义控件
Button button0 = findViewById(R.id.button0);
Button button1 = findViewById(R.id.button1);
Button button2 = findViewById(R.id.button2);
Button button3 = findViewById(R.id.button3);
Button button4 = findViewById(R.id.button4);
Button button5 = findViewById(R.id.button5);
Button button6 = findViewById(R.id.button6);
Button button7 = findViewById(R.id.button7);
Button button8 = findViewById(R.id.button8);
Button button9 = findViewById(R.id.button9);
Button buttonC = findViewById(R.id.buttonC);
Button buttonDot = findViewById(R.id.buttonDot);
Button buttonEqual = findViewById(R.id.buttonEqual);
Button buttonAdd = findViewById(R.id.buttonAdd);
Button buttonDec = findViewById(R.id.buttonDec);
Button buttonMulti = findViewById(R.id.buttonMulti);
Button buttonAC = findViewById(R.id.buttonAC);
Button buttonBracketLeft = findViewById(R.id.buttonBracketLeft);
Button buttonBracketRight = findViewById(R.id.buttonBracketRight);
Button buttonDiv = findViewById(R.id.buttonDiv);
textview = findViewById(R.id.text_view);
button0.setOnClickListener(this);
button1.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
button4.setOnClickListener(this);
button5.setOnClickListener(this);
button6.setOnClickListener(this);
button7.setOnClickListener(this);
button8.setOnClickListener(this);
button9.setOnClickListener(this);
buttonAC.setOnClickListener(this);
buttonAdd.setOnClickListener(this);
buttonBracketLeft.setOnClickListener(this);
buttonBracketRight.setOnClickListener(this);
buttonC.setOnClickListener(this);
buttonDec.setOnClickListener(this);
buttonDiv.setOnClickListener(this);
buttonDot.setOnClickListener(this);
buttonEqual.setOnClickListener(this);
buttonMulti.setOnClickListener(this);
}
private int count_negative = 0; //负数标记
private final int vibrate_time = 5; //震动时长
private boolean equals = false;
private int count_bracket_left = 0;
private int count_bracket_right = 0;
@SuppressLint("SetTextI18n")
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button0:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
sb = sb.append("0");
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button1:
if (equals) { //当equals为true,输入数字,清空字符串,在把标志变为false
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*1");
} else {
sb = sb.append("1");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button2:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*2");
} else {
sb = sb.append("2");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button3:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*3");
} else {
sb = sb.append("3");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button4:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*4");
} else {
sb = sb.append("4");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button5:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*5");
} else {
sb = sb.append("5");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button6:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*6");
} else {
sb = sb.append("6");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button7:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*7");
} else {
sb = sb.append("7");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button8:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*8");
} else {
sb = sb.append("8");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.button9:
if (equals) {
sb = sb.delete(0, sb.length());
equals = false;
}
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ')') {
sb = sb.append("*9");
} else {
sb = sb.append("9");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonC: //删除
if (equals) {
equals = false;
}
if (sb.length() != 0) {
sb = sb.deleteCharAt(sb.length() - 1);
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonAC: //清空
if (equals) {
equals = false;
}
sb = sb.delete(0, sb.length());
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonBracketLeft: //左括号
if (equals) {
equals = false;
}
if (sb.length() > 0 && (sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9')) { //当前面是数字是,自动添加为'*('
sb = sb.append("*(");
}
if (sb.length() == 0) { //如果此时字符串是空的,也就是说想在式子最前面添加括号,就添加括号
sb = sb.append("(");
}
if (sb.length() > 0 && (sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/' || sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-')) { //如果当括号前面是符号时添加括号
sb = sb.append("(");
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonBracketRight: //=右括号
if (equals) {
equals = false;
}
int count_num = 0; //数字的数目
count_bracket_left = count_bracket_right = 0;
if (sb.length() != 0) {
for (int i = sb.length() - 1; i >= 0; i--) { //对字符串进行遍历,如果存在左括号且括号中有数字,标记转为真,
if (count_bracket_left == 0 && (sb.charAt(i) >= '0' && sb.charAt(i) <= '9')) {
count_num++;
}
if (sb.charAt(i) == '(') {
count_bracket_left++;
}
if (sb.charAt(i) == ')') {
count_bracket_right++;
}
}
Log.d("count_bracket", String.valueOf(count_bracket_left+" "+count_bracket_right));
if ((count_bracket_left > count_bracket_right) && count_num > 0) { //当标记均为真,也就是存在左括号时且在左括号前面有数字,才让添加括号
sb = sb.append(")");
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonDiv: //除号
if (equals) {
equals = false;
}
if (sb.length() != 0) {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') || sb.charAt(sb.length() - 1) == '.') {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9')) { //如果前一位是数字,就直接添加
// if (count_negative > 0){ //如果前面是负数,就加上括号
// sb = sb.append(")/");
// count_negative = 0;
// } else {
sb = sb.append("/");
// }
}
if (sb.charAt(sb.length() - 1) == '.') { //如果前一位是'.',就先为前一位数字补0
sb = sb.append("0/");
}
}
if ((sb.charAt(sb.length() - 1) == ')')) { //如果前一位是')'也让加上/
sb = sb.append("/");
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonMulti: //乘号
if (equals) {
equals = false;
}
if (sb.length() != 0) {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') || sb.charAt(sb.length() - 1) == '.') {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9')) {//如果前一位是数字,就直接添加
sb = sb.append("*");
}
if (sb.charAt(sb.length() - 1) == '.') {//如果前一位是'.',就先为前一位数字补0
sb = sb.append("0*");
}
}
if ((sb.charAt(sb.length() - 1) == ')')) {
sb = sb.append("*");
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonDec: //减号
if (equals) {
equals = false;
}
if (sb.length() != 0) {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') || sb.charAt(sb.length() - 1) == '.' ||
sb.charAt(sb.length() - 1) == '(') {
if (sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') {//如果前一位是数字,就直接添加
// if (count_negative > 0) { //如果前面是负数,就加上括号
// sb = sb.append(")-");
// count_negative = 0;
// } else {
sb = sb.append("-");
// }
}
if (sb.charAt(sb.length() - 1) == '.') {//如果前一位是'.',就先为前一位数字补0
sb = sb.append("0-");
}
if (sb.charAt(sb.length() - 1) == '(') {
sb = sb.append("-");
count_negative++;
}
} else if ((sb.charAt(sb.length() - 1) == ')')) {
sb = sb.append("-");
} else {
sb = sb.append("(-");
}
} else { //负号
sb = sb.append("(-");
count_negative++;
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonAdd: //加号
if (equals) {
equals = false;
}
if (sb.length() != 0) {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') || sb.charAt(sb.length() - 1) == '.') {
if ((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9')) {//如果前一位是数字,就直接添加
// if (count_negative > 0) { //如果前面是负数,就加上括号
// sb = sb.append(")+");
// count_negative = 0;
// } else {
sb = sb.append("+");
// }
}
if (sb.charAt(sb.length() - 1) == '.') {//如果前一位是'.',就先为前一位数字补0
sb = sb.append("0+");
}
}
if ((sb.charAt(sb.length() - 1) == ')')) {
sb = sb.append("+");
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonDot: //小数点
if (equals) {
equals = false;
}
if (sb.length() != 0) {
int count_dot = 0;
for (int i = sb.length() - 1; i >= 0; i--) {
if (sb.charAt(i) == '.') {
count_dot++;
}
if (!(sb.charAt(i) >= '0' && sb.charAt(i) <= '9')) {
break;
}
}
if (count_dot == 0) {
if (sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/' || sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-') {
// 如果最后一位是符号时,直接输小数点会自动补'0',形成'0.'
sb = sb.append("0.");
} else {
sb = sb.append(".");
}
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
textview.setText(sb.toString());
break;
case R.id.buttonEqual: //等号
if (equals) {
equals = false;
}
count_bracket_right = count_bracket_left = 0;
if (sb.length() != 0) {
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) == '(')
count_bracket_left++;
if (sb.charAt(i) == ')')
count_bracket_right++;
}
if (count_bracket_left != count_bracket_right) {
Toast.makeText(MainActivity.this, "请注意括号匹配", Toast.LENGTH_SHORT).show();
}
if (count_bracket_left == count_bracket_right &&
((sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') || sb.charAt(sb.length() - 1) == ')')) {
equals = true;
count_negative = 0;
try {
textview.setText(InfixToSufix.Cal(InfixToSufix.Suffix(sb)));
sb = sb.delete(0, sb.length());
sb.append(textview.getText().toString());
} catch (Exception e){
textview.setText("Error");
sb = sb.delete(0, sb.length());
}
}
}
Vibrate.vSimple(view.getContext(), vibrate_time);
break;
default:
break;
}
}
}
算法
1. 中缀表达式转后缀表达式
http://www.nowamagic.net/librarys/veda/detail/2307
2. 后缀表达式的计算
http://www.nowamagic.net/librarys/veda/detail/2306
3. 具体代码
在MainActivity同一个包下新建class文件,命名为InfixToSuffix
代码如下
package com.example.calculator;
import android.util.Log;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Created by littlecorgi_a1203991686 on 2018/08/02 15:56.
*/
public class InfixToSuffix {
/**
* 中缀转后缀
* @param str 从键盘读入的String类型的对象,也就是要求的表达式
* @return 返回一个ArrayList类型的对象,也就是一个集合,也即是后缀表达式,让cal方法接收,
*/
public static ArrayList Suffix(StringBuilder str){
/*
* Stack() 构造方法
* void add(int index, Object element) 在此向量的指定位置插入指定的元素
* boolean empty() 测试堆栈是否为空
* Object pop( ) 移除堆栈顶部的对象,并作为此函数的值返回该对象
* Object push(Object element) 把项压入堆栈顶部
*/
for (int i = 1; i < str.length(); i++){ //识别到'(-'自动补0
if (str.charAt(i) == '-' && str.charAt(i - 1) == '('){
str.insert(i, '0');
}
}
StringBuilder temp = new StringBuilder(); // 当做中间字符串,临时存放数字,方便往list中添加
List list = new ArrayList<>(); // 用于存储分割后的数字和符号
ArrayList result = new ArrayList<>(); //作为结果集合,后缀表达式保存在其中
for (int i = 0; i < str.length(); i++){
// if ( i != str.length() - 1 ){ //对不是最后一位数字的
if ((str.charAt(i) >= '0' && str.charAt(i) <= '9') || str.charAt(i) == '.'){ // 判断是不是数字
if (str.charAt(i) == '.' && temp.length() == 0){ //如果此位为'.',且这个时候中间字符串为空,自动补0
temp.append(0); // 添加0,在添加'.'
temp.append(str.charAt(i));
} else {
temp.append(str.charAt(i)); // 是数字,就往中间字符串添加
}
if (i == str.length() - 1){ //对最后一位进行单独判断,如果是字符串最后一位,直接进行添加到list操作
list.add(temp.toString());
}
} else { // 不是数字
if (temp.length() != 0)
list.add(temp.toString()); // 判断中间字符串长度是不是0,不是0就往list中添加
list.add(String.valueOf(str.charAt(i))); // 将符号往list中添加
temp.delete(0, temp.length()); // 清空中间字符串
}
// } else { //单独把最后一个字符拿出来进行判断
// if ((str.charAt(i) >= '0' && str.charAt(i) <= '9') || str.charAt(i) == '.'){ // 下面代码注释参考上面
// temp.append(str.charAt(i));
//
// } else {
// if (temp.length() != 0)
// list.add(temp.toString()); // 判断中间字符串长度是不是0,不是0就往list中添加
// list.add(String.valueOf(str.charAt(i)));
// temp.delete(0, temp.length());
// }
// }
}
// 遍历输出
for (String aList : list) {
System.out.print(aList + " ");
}
System.out.println();
// 定义栈
Stack stack = new Stack<>();
// 定义符号的优先级
Map map = new HashMap<>();
map.put('(', 0);
map.put(')', 0);
map.put('*', 1);
map.put('/', 1);
map.put('+', 2);
map.put('-', 2);
for ( String s : list ) {
// System.out.println("s=" + s);
if ( s.equals("*") || s.equals("/") || s.equals("+") || s.equals("-") || s.equals("(") || s.equals(")") ){ //不为数字
if (stack.size() == 0){ //如果当前栈里面没有元素,不管是啥,直接进栈
stack.push(s);
} else { //如果栈中有元素
if (s.equals(")")) { //如果当前是),那就的往前找(与其对应输出
if (!stack.empty()){ //容错,不然会有EmptyStackException,下面的类似的表达式同理
while (!stack.peek().equals("(")){ //循环,从栈顶开始循环,一直到栈顶为(,退出循环
// System.out.print(stack.pop() + " "); //输出并且把栈顶元素移除
result.add(stack.pop()); //保存到结果集合中,并且把栈顶元素移除
if (stack.empty()){//容错,不然会有EmptyStackException,见上面
break;
}
}
if (!stack.empty()){
if (stack.peek().equals("("))//如果此时栈顶元素为(,就将他移除,原因是后缀表达式不用(,而在之前我们将他压入了栈中,具体见下面第5行
stack.pop();
}
}
} else{
if (s.equals("(")){ //如果是'('将其入栈
stack.push(s);
} else {
if (stack.peek().charAt(0) != '('){
if ( map.get(s.charAt(0)) < map.get(stack.peek().charAt(0)) ){ //栈顶符号的优先级高于元素优先级,也就是数字小,进栈
stack.push(s);
} else { //栈顶符号优先级低于元素优先级,输出并循环
while ((map.get(s.charAt(0)) >= map.get(stack.peek().charAt(0))) && !stack.empty()){
// System.out.print(stack.pop() + " ");
result.add(stack.pop());
if (stack.empty()){
break;
}
if (stack.peek().equals("(")){
break;
}
}
stack.push(s);
}
} else {
stack.push(s);
}
}
}
}
} else { //是数字
result.add(s);
}
}
while (!stack.empty()){ //最后遍历栈,把结果保存到result中,直到栈被清空
result.add(stack.pop());
}
return result;
}
/**
* 用于计算后缀表达式的结果
* @param arrayList 从Suffix传出来的后缀表达式
* @return 返回String类型对象,也就是最后的结果
*/
public static String Cal(ArrayList arrayList){
int length = arrayList.size();
String[] arr = new String[length]; //转为字符串数组,方便模拟栈
for (int i = 0; i < arrayList.size(); i++){
arr[i] = (String)arrayList.get(i);
}
Log.d("asdfg", arrayList.toString());
List list = new ArrayList<>();
for (String anArr : arr) { //此处就是上面说的运算过程,因为list.remove的缘故,所以取出最后一个数个最后两个数 都是size-2
int size = list.size();
switch (anArr) {
case "+":
BigDecimal a = new BigDecimal(list.remove(size - 2)).add(new BigDecimal(list.remove(size - 2)));
// list.add(String.valueOf(a.stripTrailingZeros().toPlainString()));
list.add(a.stripTrailingZeros().toString()); //去掉结果最后的0
break;
case "-":
BigDecimal b = new BigDecimal(list.remove(size - 2)).subtract(new BigDecimal(list.remove(size - 2)));
list.add(b.stripTrailingZeros().toString());
break;
case "*":
BigDecimal c = new BigDecimal(list.remove(size - 2)).multiply(new BigDecimal(list.remove(size - 2)));
list.add(c.stripTrailingZeros().toString());
break;
case "/":
BigDecimal d = new BigDecimal(list.remove(size - 2)).divide(new BigDecimal(list.remove(size - 2)), 10, BigDecimal.ROUND_HALF_UP);
list.add(d.stripTrailingZeros().toString());
break;
default:
list.add(anArr);
break;//如果是数字 直接放进list中
}
}
if (list.size() == 1){
if (list.get(0).length() < 30){ //当结果长度不长时,就直接输出
BigDecimal bd = new BigDecimal(list.get(0));
return bd.toPlainString(); //BigDecimal默认直接输出
} else { //当结果过长时,就用科学计数法输出
double d = Double.valueOf(list.get(0));
return String.valueOf(d); //Double会使用科学计数法输出
}
} else {
return "运算失败";
}
}
}