如何使用Scanner处理由无效输入(InputMismatchException)引起的无限循环

时间:2010-08-26 04:57:10

标签: 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.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;
    }
}

这是我的输出:

  

插入整数:
   价值无效!
  插入整数:
   价值无效!
  ...

5 个答案:

答案 0 :(得分:54)

根据扫描仪的javadoc

  

当扫描仪抛出时   InputMismatchException,扫描程序   不会传递导致的令牌   例外,这样可能   通过其他方式检索或跳过   方法

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

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

答案 1 :(得分:0)

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

通过这种方式,您可以使用一个获取输入的扫描仪和一个可以验证输入的扫描仪,这样如果输入正确的输入形式,您就不必担心读者的关怀。

答案 2 :(得分:0)

你所做的守卫是'循环'变量。

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

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

要终止这段时间,你需要用其他合乎逻辑的东西来保护你的行为,例如:

  1. 当读者获得非int字符时退出
  2. EOF时退出
  3. 这可以在catch块或其他一些行中完成。但精确的解决方案取决于您的规格。

答案 3 :(得分:0)

你也可以试试这个:

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

答案 4 :(得分:0)

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来读取String并检查是否是数字,但扫描器代码较少。检查代码并运行正常。