我正在学习Java,而且我一直在编写计算器类。目前,它仅用于使用两个数字进行简单操作,例如2 + 2.以下是我的代码的一小部分:
public static void start()
{
System.out.println("Calculator. Type \"exit\" to quit.");
System.out.print("> ");
Scanner scan = new Scanner(System.in);
String entry = scan.nextLine();
while (! (entry.equals("exit")))
{
String [] values = entry.replaceAll("(^\\s+|\\s+$)", "").split("\\s+");
num1 = new Double(values[0]);
operand = values[1];
num2 = new Double(values[2]);
...
}
...
}
...
之后出现一个switch语句,它是while循环的一部分。 switch语句测试operand
的值,调用适当的方法,打印结果,然后重新启动while循环。
我自己并没有对正则表达式部分进行编码,但是通过阅读之前的StackOverlfow帖子,我了解到它会忽略任何空白字符之前,中间和之后我想要的值。
代码正常,但空格字符不分隔num1
,operand
和num2
的情况除外。
例如:
> 2 + 2
4.0
>2 + 2
4.0
但是:
>2+2
Exception in thread "main" java.lang.NumberFormatException: For input string: "2+2"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.valueOf(Double.java:504)
at java.lang.Double.<init>(Double.java:597)
at calc.Calc.start(Calc.java:24)
at calc.CalcClient.main(CalcClient.java:8)
Java Result: 1
并且:
>2+ 2
Exception in thread "main" java.lang.NumberFormatException: For input string: "2+"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.valueOf(Double.java:504)
at java.lang.Double.<init>(Double.java:597)
at calc.Calc.start(Calc.java:24)
at calc.CalcClient.main(CalcClient.java:8)
Java Result: 1
并且:
>2 +2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at calc.Calc.start(Calc.java:26)
at calc.CalcClient.main(CalcClient.java:8)
Java Result: 1
我的错误在哪里?它是数组的问题,我解析字符串的方式,或者其他可能的东西?我想对它进行编码,以便用户可以根据需要输入具有尽可能多的空白的内容,或者根本不输入内容。
感谢您的帮助!
答案 0 :(得分:1)
答案仅作为示例提供:
// extract the operands and operator
String[] operandsArrStr = "22+ 2".replaceAll("\\s+", "").split("[\\+\\-\\/\\*]"); // {"22", "2"}
String operator = "22+ 2".replaceAll("(\\s+|\\d+|\\.)", ""); // "+"
// convert the values to doubles
Double[] operands = new Double[operandsArrStr.length];
for (int i=0; i < operandsArrStr.length; i++) {
operands[i] = new Double(operandsArrStr[i]);
}
Double res = null;
// calc
if ("+".equals(operator)) {
res = operands[0] + operands[1]; // assuming only two operands and one operator!
}
else if ("-".equals(operator)) {
res = operands[0] - operands[1];
}
else if ("/".equals(operator)) {
res = operands[0] / operands[1];
}
else if ("*".equals(operator)) {
res = operands[0] * operands[1];
}
System.out.println("res = " + res); // prints 24.0
答案 1 :(得分:0)
这是一个正则表达式问题,实际上是:)
您应该替换该行:
String [] values = entry.replaceAll("(^\\s+|\\s+$)", "").split("\\s+");
... by:
String [] values = entry.trim().split("\\s*");
<强> 说明: 强>
String#trim
会删除String
开头和结尾处的所有最终空格。我相信你正在尝试使用.replaceAll("(^\\s+|\\s+$)", "")
\s+
表示“至少有一个空白字符”,而\s*
表示“任何序列白色空格字符“(包括没有空白区域,这对您来说是有效的案例;)但是,我实际上建议你尝试不同的方法。请考虑下面的工作代码示例:
private static final Pattern SIMPLE_OPERATION = Pattern.compile("(?<num1>\\d*\\.?\\d+)(?<operand>[+-/*])(?<num2>\\d*\\.?\\d+)");
public static void start() {
System.out.println("Calculator. Type \"exit\" to quit.");
try (final Scanner scan = new Scanner(System.in)) {
Double num1, num2;
String operand;
String entry;
do {
System.out.print("> ");
entry = scan.nextLine();
final Matcher m = SIMPLE_OPERATION.matcher(entry.replaceAll("\\s+", ""));
if (m.matches()) {
num1 = Double.valueOf(m.group("num1"));
num2 = Double.valueOf(m.group("num2"));
operand = m.group("operand");
System.out.println(String.format("'%s', '%s', '%s'", num1, operand, num2));
}
} while (!(entry.equalsIgnoreCase("exit")));
}
}
这可以在将来轻松增强,并且可以处理以下任何事情:
2+2
2 * 2
2 - 2
2 / 2
...还有十进制数字:
88 + 65.005555
.5*2
我希望这会帮助你开始;)
答案 2 :(得分:0)
以下代码可以在独立的可执行文件中使用并附带测试用例:
import java.util.*;
import java.util.regex.*;
class Foo {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\s*(\\d+)\\s*(\\D)\\s*(\\d+)");
String[] tests = {"2+2", "2 + 2", " 2 + 2", "2 +2", "2 +2", "2+ 2"};
for (String entry : tests) {
System.out.println("testing entry: " + entry);
Matcher matcher = pattern.matcher(entry);
if (matcher.matches()) {
Double num1 = new Double(matcher.group(1));
String operand = matcher.group(2);
Double num2 = new Double(matcher.group(3));
System.out.printf("num1: %s, operand: %s, num2: %s\n", num1, operand, num2);
}
}
}
}
然而,这段代码相当脆弱,因为它仅适用于您指定的确切格式,即带整数的二进制运算。如果您想要获得更高级的功能,您可能要么使用扫描仪,要么考虑使用像ANTLR这样的完整解析器。 ANTLR在这种情况下非常容易使用,事实上我认为ANTLR教程涵盖了创建计算器。
编辑:此代码无法处理浮点数,即使它将它们存储在双打中。