一、前言
写这篇文章,是为了整理下思路,记录下自己的学习记录,Java小白一枚,代码仅供参考,如有不合理之处,请谅解。
二、计算器具体要求
1.实现输入表达式完成计算(仅支持加减乘除)。
2.支持正负数小数等运算。
3.设计计算器界面。
4.基本错误处理完成。
三、核心思路
1.表达式处理
使用正则表达式判断表达式是否合理,算数表达式的规律,就是一个数后面接着一个运算符然后再接一个数,先暂时不考虑括号的出现问题,例如:1+3/4*3,分离开来就是1+,3/,4*,3。最后一个数字是不跟运算符的所以由这样的思考,我们用正则表达式来写,现在我们来考虑括号问题,我们目前这个部分的目的是实现检测输入的表达式是否合理,所以要考虑括号的位置和数量,但由于我的技术有限,我就采用了很朴素的方法来验证,就是想到什么情况就写什么情况的检测代码,如下图:
public static Boolean kh_pp(String str){
try {
int zkh = 0;
int ykh = 0;
for (int i =0;i<str.length();i++){
if (String.valueOf(str.charAt(i)).equals("(")){
zkh++;
} else if (String.valueOf(str.charAt(i)).equals(")")) {
ykh++;
}
}
return zkh == ykh;
}catch (Throwable e2){
jLabel.setText("括号匹配错误,未知异常!");
return false;
}
}
public static boolean str_pd(String str){
//先是去掉空格
//(-1)+4-(-2)
//表达式处理规则,思路:
//1.去掉里面所有的左右括号
//2.表达式一个数字后面必定有个运算符,除了最后一个数后没有运算符,其他都有
//3.括号数量相同
//功能要求
//1.实现多位正或负数的匹配,支持小数
//2.不允许出现数字以及运算符外的字符
//3.除数不能为0
try {
boolean flag1 = kh_pp(str); // 这里还有个方法是kh_pp用来判断括号的数量是否相等
boolean flag = false; //先定义表达式为不合理
if (str.matches(".*(\\-?\\d+(\\.\\d+)?)?\\(\\).*")){
return flag; // 检测如:1(),()这种情况
} else if (str.matches(".*\\-?\\d+(\\.\\d+)?\\(.*")) {
return flag; //检测如:1(3+2)这种情况
} else if (str.matches(".*\\-\\(\\d+(\\.\\d+)?\\).*")) {
return flag; //检测如:-(5) 这种写法,应写为(-5)
}
str = str.replace(" ",""); // 去掉空格
str = str.replace("(",""); // 将左右括号全部去掉,例如:(-1)+4-(-2) 变成 -1+4--2
str = str.replace(")",""); //
for (int i =0;i<str.length();i++){
String now = String.valueOf(str.charAt(i));
if (!now.matches("[0-9\\+\\-\\*\\/\\(\\)\\.]")){
jLabel.setText("表达式错误,含有未知字符!");
return flag; // 检测是否有不符合算术表达式的字符
}
}
if (str.matches("(\\-?\\d+(\\.\\d+)?[\\+\\-\\*\\/])+\\-?\\d+(\\.\\d+)?")){ //常规检测 一个数后面跟着一个运算符,最后一个数不跟运算符
if (str.matches(".*\\/0.*")){ // 检测除数是否为零
jLabel.setText("除数不能为0!");
}else {
if (flag1)flag = true; //如果前面的检测和现在的检测都是true 则将flag改为真
}
}
return flag;
}catch (Throwable e2){ //检测一切异常,如果出粗就返回false
jLabel.setText("表达式判断错误,未知异常!");
return false;
}
}
2.把表达式当成字符串处理,先将表达式中的数字和运算符分离。
这个部分完成的目的是表达式的分割,就是将表达式的数字和运算符分离,需要注意的是:正负数的多位数判断以及小数位数判断,使用while遍历拼接(小数点前后小数点后原理一样,就是遍历)。负数和正数为两种检测情况,所以分开写(其实是一开始没想到,后面写的OvO),此功能模块的返回值是一个分割后的列表,比如:(-6)/(-6)+(3-5)/2 ——》》["-6","/","-6","+","(","3","-","5",")","/","2"],为什么“(-6)”的括号不见了,是因为在代码最后做了处理,去掉了包裹着负数的括号,因为这些括号并不是优先级的括号,所以去掉。
具体代码如下:
public static List<String> str_fg(String str1){
//创建一个字符列表用来存储分割后的字符串表达式
//防止用书输入诸如(-1)+(-4)-5+((-6)/(-6)) 无用括号太多 去掉非优先级括号 也就是负数旁的括号
String str = str1;