提问人:Sergey Zolotarev 提问时间:12/19/2022 最后编辑:Sergey Zolotarev 更新时间:3/17/2023 访问量:95
Java 可以在没有明确分隔符的情况下“分隔输入本身”吗?
Can Java "delimit input itself", without explicit delimiters?
问:
我的计算器,我需要为我的测试任务申请 Java 课程,运行良好。但是我想解决一个问题。例如,如果您输入“5+3”而不是“5 + 3”,则不起作用。我的计算器是否足够智能,可以在没有明确分隔符(如空格)的情况下分隔输入?
换句话说,例如,如何使扫描仪的输入拆分为五个标记:、、、和?如果我不必彻底修改我的整个代码,那就更好了!5+32 *2
5
+
32
*
2
import java.util.Scanner;
import java.io.IOException;
import java.text.DecimalFormat;
public class Introduction {
private static double firstNum;
private static double secondNum;
private static double result;
private static boolean dontKnow;
private static String firstNumS;
private static String secondNumS;
private static String operationS;
private static final DecimalFormat df = new DecimalFormat("#.##");
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
firstNumS = scanner.next();
operationS = scanner.next();
secondNumS = scanner.next();
if(firstNumS.compareTo(operationS) > 15){
switch(firstNumS){
case "I":
firstNum = 1;
break;
case "II":
firstNum = 2;
break;
case "III":
firstNum = 3;
break;
case "IV":
firstNum = 4;
break;
case "V":
firstNum = 5;
break;
case "VI":
firstNum = 6;
break;
case "VII":
firstNum = 7;
break;
case "VIII":
firstNum = 8;
break;
case "IX":
firstNum = 9;
break;
case "X":
firstNum = 10;
break;
default:
System.out.println("I don't know the first number!");
dontKnow = true; }}
else {
firstNum = Integer.decode(firstNumS);
if(firstNum > 10){
System.out.println("It appears, the first number is too big for me!");
dontKnow = true;
}
}
if(secondNumS.compareTo(operationS) > 15) {
switch(secondNumS){
case "I":
secondNum = 1;
break;
case "II":
secondNum = 2;
break;
case "III":
secondNum = 3;
break;
case "IV":
secondNum = 4;
break;
case "V":
secondNum = 5;
break;
case "VI":
secondNum = 6;
break;
case "VII":
secondNum = 7;
break;
case "VIII":
secondNum = 8;
break;
case "IX":
secondNum = 9;
break;
case "X":
secondNum = 10;
break;
default:
System.out.println("I don't know the second number!");
dontKnow = true; }}
else {
secondNum = Integer.decode(secondNumS);
if(secondNum > 10) {
System.out.println("It appears, the second number is too big for me!");
dontKnow = true; }}
if(operationS.equals("+")) {
result = firstNum + secondNum; }
else if(operationS.equals("-")) {
result = firstNum - secondNum; }
else if(operationS.equals("*")){
result = firstNum * secondNum; }
else if(operationS.equals("/")){
result = firstNum / secondNum; }
else {
System.out.println("I don't know such an operation!");
dontKnow = true; }
if(!(operationS.equals("/") && secondNum == 0)) {
if(!dontKnow) {
if(result / (int)result != 1) {
if(String.valueOf(result).equals(df.format(result))) {
System.out.println("It's " + result + "!"); }
else {
System.out.println("It's approximately " + df.format(result) + "!"); }}
else {
System.out.println("It's " + (int)result + "!"); }}}
else {
if(!dontKnow) {
System.out.println("Gosh! I tried to divide it by zero, as you requested, but my virtual head nearly exploded! I need to recover..."); }
else {
System.out.println("Besides, you can't even divide by zero, I'm so told!"); }}
}
}
答:
2赞
rzwitserloot
12/19/2022
#1
假设您使用的是扫描仪,是的,它可以。扫描程序的操作基于正则表达式用作分隔符的概念:正则表达式的每个匹配都会进行分隔,并且正则表达式匹配的任何内容都会被扔掉(因为没有人“关心”读取空格或逗号或其他什么)。然后,扫描程序会在分隔符之间为您提供内容。
因此,要最终得到扫描仪流“5”、“+”和“3”,您需要一个分隔符来分隔“5”/“+”和“+”/“3”之间的空间,同时匹配 0 个字符,否则这些字符将被抛出。
您可以使用正则表达式 lookahead/lookbehind 来做到这一点。您希望在左边有一个数字,在右边有一个运算符,反之亦然:
String test = "53 + 2*35- 8";
Scanner s = new Scanner(test);
s.useDelimiter("\\s+|(?:(?<=\\d)(?=[-+/*]))|(?:(?=\\d)(?<=[-+/*]))");
while (s.hasNext()) {
System.out.println("NEXT: '" + s.next() + "'");
}
要打破这个复杂的正则表达式,请执行以下操作:
A|B|C
表示:A 或 B 或 C。这是这个正则表达式的“最外层”部分,我们正在寻找 3 个不同的事物之一来拆分。\\s+
表示:1 个或多个空格字符。因此,输入将拆分为 和 。空格被消耗掉(即被扔掉,而不是你的代币的一部分)。"5 20"
5
20
- 或者,正向后看(意思是:如果向后看,你会看到 X),则匹配),X 在这里 - 一个数字。然后,我们还有一个积极的展望:意味着:检查 X 是否在这里,但不要消耗它(否则它会被抛出,请记住,正则表达式描述分隔符,并且分隔符被抛出)。我们展望其中一个符号。
(?<=X)
\\d
(?=X)
- 或者,那个,但翻转了(首先是运算符,然后是数字)。
注意:如果你想避免正则表达式的复杂性,你可以遍历每个字符,但你要构建一个小的状态机,并且必须处理连续的、非空格分隔的数字:你需要把它们组合起来(不是、、、、、——它是)。10 + 20
1
0
+
2
0
10
+
20
NB2:如果你也想支持,你可以适当地编辑正则表达式(它们本质上是“运算符”,并进入运算符列表),但是,在某些时候,你基本上是在描述一种形式语言的语法,应该开始研究解析器生成器。但这比任何一个都要复杂得多。(
)
评论
0赞
rzwitserloot
12/24/2022
它不完全相同;唯一的区别在于 VS . 只是把东西组合在一起,就像.有十亿个关于正则表达式的教程,包括在线工具,可以让你写一些文本,写一个正则表达式,用花哨的颜色向你显示哪些部分与什么匹配。(?=)
(?<)
(?:X)
(5 + 2)
0赞
Sergey Zolotarev
1/14/2023
\\s 和 \s 的意思一样吗?🤔
0赞
rzwitserloot
1/15/2023
是的。Java 本身使用反斜杠作为转义机制,因此直接编写不会编译:与正则表达式不同(程序员奇怪的选择,例如转义不需要转义的东西,只是猜测),java 在它认为它或你感到困惑时会出错(这样做是正确的,更快的错误修复很重要)。 因此生成一个包含 2 个字符的字符串。将其发送到您的正则表达式解析器,您最终会得到一个表示“空格字符”的正则表达式。"\s"
"\\s"
评论