【问题标题】:How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner如何使用 Scanner 处理由无效输入(InputMismatchException)引起的无限循环
【发布时间】:2018-07-13 14:34:57
【问题描述】:

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

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;
    }
}

这是我的输出:

插入一个整数:
值无效!
插入一个整数:
值无效!
...

【问题讨论】:

  • 请考虑去掉变量 loop 和 num 而是使用 while (true) { try { ....; return reader.nextInt(); } catch {....} }

标签: java java.util.scanner infinite-loop


【解决方案1】:

根据扫描仪的javadoc

当扫描仪抛出一个 InputMismatchException,扫描仪 不会传递导致 例外,因此它可能是 通过其他方式检索或跳过 方法。

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

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

【讨论】:

  • +1 读者注意:根据具体情况,您可能希望使用nextLine() 而不是next(),这样this has spaces in it 这样的输入就不会触发多个异常。
【解决方案2】:

我要做的是使用 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;
    }

这样,您就拥有一台扫描仪来获取输入并验证输入,这样您就不必担心读者是否会关心他们是否输入了正确的输入形式。

【讨论】:

    【解决方案3】:

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

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

    当抛出异常时,'loop' 变量的值为 'true',但您的代码会跳转到 catch 块,然后重复 while-do。这个 while-do 永远不会停止,因为下一次迭代会再次抛出异常,再次跳转到 catch 块等等。

    要终止这个 while-do,你需要用另一个逻辑的东西来保护你的 while-do,例如:

    1. 阅读器获取非整数字符时退出
    2. EOF 时退出

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

    【讨论】:

      【解决方案4】:

      你也可以试试这个:

         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;
          }
      

      【讨论】:

        【解决方案5】:
        package nzt.nazakthul.app;
        
        import java.util.*;
        
        public class NztMainApp {
        
            public static void main(String[] args) {
            ReadNumber readObj = new ReadNumber();
            readObj.readNumber();
            }
        
        }
        
        class ReadNumber {
        int no;
        
            int readNumber() {
            Scanner number = new Scanner(System.in);
            int no=0;
            boolean b=true;
            do {
        
                try {
                    System.out.print("Enter a number:\t");
                    no = number.nextInt();
                } catch (InputMismatchException e) {
                    System.out.println("No Number");
                    //e.printStackTrace();
        
                    b=false;
                }
        
            }
        
            while (b);
            return no;
        
            }
        
        }
        

        我个人使用 BufferedReader 和 InputStreamReader 来读取字符串并检查是否是数字,但使用扫描仪的代码更少。代码检查并运行正常。

        【讨论】:

          猜你喜欢
          • 2011-04-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多