为什么我的 while(Scanner.hasNext()) 循环永远不会退出?

问题描述 投票:0回答:2

我正在学习 Java 并构建一个战舰游戏作为学习练习。我创建了一个方法来从用户接收一组坐标,该坐标以两个整数形式输入,并用空格分隔。我已经验证这两个整数是否被正确读取,但是程序继续从键盘获取输入,并且永远不会脱离 while 循环。因此,该方法永远不会返回一组坐标。我已经搜索并阅读了很多有关使用 Scanner 的信息,但我没有看到我的代码有什么问题。你能告诉我我做错了什么吗?

传入的扫描仪是

Scanner(System.in)

public static int[] getCoordinates(Scanner input, String prompt) {
    int[] coordinates = new int[2];
    boolean invalid = false;

    do {
        System.out.println(prompt + ":");
        int index = 0;
        while (input.hasNext()) {
            if (input.hasNextInt() && index < 2) {
                coordinates[index] = input.nextInt();
                index++;
            } else {
                input.next();
            }
        }
            
        if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
            System.out.println("Invalid coordinates. Choose different coordinates.");
            invalid = true;
        }
    } while (invalid);
    
    return coordinates;
}

我期望发生的是用户输入两个整数,然后按 Enter 键,

while(input.hasNext())
循环将退出并继续该方法的其余部分。

更新:我只需执行以下操作即可获得基本功能。我不确定这是否可靠,但现在就可以了。

int index = 0;
while (index < 2) {
    if (input.hasNextInt()) {
        coordinates[index] = input.nextInt();
        index++;
    }
}

这也很有效。感谢@k314159!

String[] answer = input.nextLine().split(" ");
if (answer.length >= 2) {
    coordinates[0] = Integer.parseInt(answer[0]);
    coordinates[1] = Integer.parseInt(answer[1]);
}
java java.util.scanner infinite-loop
2个回答
0
投票

原始

while (input.hasNext())
循环永远不会退出的原因是它等待输入流 (
System.in
) 关闭,这通常在程序终止时发生。它不会仅仅因为用户按下 Enter 键而退出。

如果您想继续使用

while (input.hasNext())
循环并仍然允许用户输入值并按 Enter 键,您可以像这样修改代码:

public static int[] getCoordinates(Scanner input, String prompt) {
    int[] coordinates = new int[2];
    boolean invalid = false;

    do {
        System.out.println(prompt + ":");
        int index = 0;
        while (index < 2) {
            if (input.hasNextInt()) {
                coordinates[index] = input.nextInt();
                index++;
            } else {
                input.next(); // Consume the non-integer token
            }
        }

        if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
            System.out.println("Invalid coordinates. Choose different coordinates.");
            invalid = true;
        } else {
            invalid = false;
        }
    } while (invalid);

    return coordinates;
}

0
投票

“为什么我的 while(Scanner.hasNext()) 循环永远不会退出?...”

正在等待更多输入。
Java 中,这有时被称为 “阻塞”

“...我期望发生的是用户输入两个整数,然后按回车键,

while(input.hasNext())
循环将退出并继续该方法的其余部分。...”

只需调用 nextInt 方法两次。

int[] coordinates;
boolean invalid;

do {
    System.out.println(prompt + ":");
    coordinates = new int[] { input.nextInt(), input.nextInt() };

    invalid = false;
    if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
        System.out.println("Invalid coordinates. Choose different coordinates.");
        invalid = true;
    }
} while (invalid);

return coordinates;

更好的方法是将它们添加到坐标时检查值。

int[] coordinates = new int[2];
boolean invalid = true;

do {
    System.out.println(prompt + ":");
    switch (coordinates[0] = input.nextInt()) {
        case 1, 2, 3, 4 -> {
            switch (coordinates[1] = input.nextInt()) {
                case 1, 2, 3, 4 -> invalid = false;
            }
        }
    }
    if (invalid) {
        System.out.println("Invalid coordinates. Choose different coordinates.");
        input.nextLine();
    }
} while (invalid);

return coordinates;

或者最好使用 Scanner#nextnextLine 方法以及 Integer#parseInt 方法评估输入。

int a = 0, b = 0;
boolean exit = false;
do {
    System.out.println(prompt + ":");
    try {
        a = Integer.parseInt(input.next());
        b = Integer.parseInt(input.next());
        if (Math.min(a, b) > 0 && Math.max(a, b) < 4) exit = true;
        else throw new Exception();
    } catch (Exception e) {
        System.out.println("Invalid coordinates. Choose different coordinates.");
        input.nextLine();
    }
} while (!exit);
return new int[] { a, b };

或者,

int[] coordinates = null;
boolean exit = false;
do {
    System.out.println(prompt + ":");
    try {
        coordinates
            = input.tokens()
                   .limit(2)
                   .mapToInt(Integer::parseInt)
                   .peek(x -> {
                       if (x < 0 || x > 4)
                           throw new RuntimeException(); })
                   .toArray();
        exit = true;
    } catch (RuntimeException e) {
        System.out.println("Invalid coordinates. Choose different coordinates.");
        input.nextLine();
    }
} while (!exit);
return coordinates;
© www.soinside.com 2019 - 2024. All rights reserved.