Java 如何使用Scanner处理无效输入(InputMismatchException)导致的无限循环

Java 如何使用Scanner处理无效输入(InputMismatchException)导致的无限循环,java,java.util.scanner,infinite-loop,Java,Java.util.scanner,Infinite Loop,所以,我被这段代码困住了: import java.util.InputMismatchException; import java.util.Scanner; public class ConsoleReader { Scanner reader; public ConsoleReader() { reader = new Scanner(System.in); //reader.useDelimiter(System.getPropert

所以,我被这段代码困住了:

import java.util.InputMismatchException;
import java.util.Scanner;

public class ConsoleReader {

    Scanner reader;

    public ConsoleReader() {
        reader = new Scanner(System.in);
        //reader.useDelimiter(System.getProperty("line.separator"));
    }

    public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                num = reader.nextInt();

                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");
            } 
        }
        return num;
    }
}
这是我的输出:

插入整数:
无效值
插入整数:
无效值

根据扫描仪的说明:

当扫描器抛出 输入不匹配异常,扫描仪 不会传递导致错误的令牌 例外情况,以便 通过其他方式检索或跳过 方法

这意味着,如果下一个令牌不是
int
,它将抛出
inputmaschException
,但该令牌将保留在那里。因此,在循环的下一次迭代中,
reader.nextInt()
再次读取相同的令牌并再次抛出异常。你需要的是用完它。在您的
catch
中添加
reader.next()
以使用令牌,该令牌无效,需要丢弃

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 
根据扫描仪的说明:

当扫描器抛出 输入不匹配异常,扫描仪 不会传递导致错误的令牌 例外情况,以便 通过其他方式检索或跳过 方法

这意味着,如果下一个令牌不是
int
,它将抛出
inputmaschException
,但该令牌将保留在那里。因此,在循环的下一次迭代中,
reader.nextInt()
再次读取相同的令牌并再次抛出异常。你需要的是用完它。在您的
catch
中添加
reader.next()
以使用令牌,该令牌无效,需要丢弃

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 

我要做的是使用Scanner.nextLine()读取整行内容。然后创建另一个扫描程序来读取返回的字符串

String line = reader.nextLine();
Scanner sc = new Scanner(line);
这将使您的示例函数如下所示:

  public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                String line = reader.nextLine();
                Scanner sc = new Scanner(line);
                num = sc.nextInt();   
                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");

            } 
        }
        return num;
    }

这样,您就有了一个扫描仪来获取输入,还有一个对输入进行验证,这样您就不必担心读者会关心他们是否输入了正确形式的输入

我要做的是使用Scanner.nextLine()读取整行内容。然后创建另一个扫描程序来读取返回的字符串

String line = reader.nextLine();
Scanner sc = new Scanner(line);
这将使您的示例函数如下所示:

  public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                String line = reader.nextLine();
                Scanner sc = new Scanner(line);
                num = sc.nextInt();   
                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");

            } 
        }
        return num;
    }

这样,您就有了一个扫描仪来获取输入,还有一个对输入进行验证,这样您就不必担心读者会关心他们是否输入了正确形式的输入

while do的保护是“循环”变量

在代码到达赋值循环之前引发的异常本身=false; 准确地说,异常是在前面的语句num=reader.nextInt()中抛出的

当抛出异常时,“loop”变量的值为“true”,但您的代码跳转到catch块,然后在执行时重复该操作。这个whiledo永远不会停止,因为下一次迭代将再次抛出异常,再次跳转到catch块,等等

要终止此while do,您需要使用另一个逻辑对象来保护您的while do,例如:

  • 读卡器获取非整型字符时退出
  • EOF时退出

  • 这可以在catch block或其他行中完成。但精确的解决方案取决于您的规格。

    while do的保护是“循环”变量

    在代码到达赋值循环之前引发的异常本身=false; 准确地说,异常是在前面的语句num=reader.nextInt()中抛出的

    当抛出异常时,“loop”变量的值为“true”,但您的代码跳转到catch块,然后在执行时重复该操作。这个whiledo永远不会停止,因为下一次迭代将再次抛出异常,再次跳转到catch块,等等

    要终止此while do,您需要使用另一个逻辑对象来保护您的while do,例如:

  • 读卡器获取非整型字符时退出
  • EOF时退出
  • 这可以在catch block或其他行中完成。但精确的解决方案取决于您的规格。

    您也可以尝试以下方法:

       public int readInt(String msg) {
            int num = 0;
            try {
                System.out.println(msg);
                num = (new Scanner(System.in)).nextInt();
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");
                num = readInt(msg);
            } 
            return num;
        }
    
    您也可以尝试以下方法:

       public int readInt(String msg) {
            int num = 0;
            try {
                System.out.println(msg);
                num = (new Scanner(System.in)).nextInt();
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");
                num = readInt(msg);
            } 
            return num;
        }
    
    就我个人而言,我使用BufferedReader和InputStreamReader来读取字符串并检查是否为数字,但使用scanner的代码更少。代码已检查并运行正常


    就我个人而言,我使用BufferedReader和InputStreamReader来读取字符串并检查是否为数字,但使用scanner的代码更少。代码检查并运行OK。请考虑删除变量循环和NUM,而使用<代码>(TRUE){True {…;返回Reader。NExtTeNe();} catch {…} }/Cord>请考虑去掉变量环和Num,而使用<代码>(TRUE){True {…;ReadReader .nExtTeNe();} catch {…}+1读者注意事项:根据具体情况,您可能希望使用
    nextLine()
    而不是
    next()
    ,以便像
    这样的输入中有空格
    不会触发多个异常。+1读者注意事项:根据具体情况,您可能希望使用
    nextLine()
    而不是
    next()
    这样,像
    这样有空格的输入不会触发多个异常。