【问题标题】:Data Validation and Scanners in JavaJava 中的数据验证和扫描器
【发布时间】:2015-06-11 02:12:39
【问题描述】:

我有一个关于数据验证和扫描仪的问题。以下代码检查用户输入。不允许使用除整数以外的任何内容,并要求用户重新输入值。我的问题是代码仅在以下情况下才有效扫描器在 while 循环中声明。如果扫描器在外部声明,程序将无限执行。为什么会这样?谢谢。

int UserInp;
    boolean dataType=false;
    while(dataType==false)
    {
        Scanner sc=new Scanner(System.in);
        try
        {

    System.out.print("\nEnter a number: ");
    UserInp=sc.nextInt();

    dataType=true;
        }
        catch(Exception JavaInputMismatch)
        {

            System.out.println("Option not available.Try again.");

        }

    }

【问题讨论】:

  • 不,它没有。我让它工作正常。您确定您所做的唯一更改是将Scanner sc = new Scanner(System.in); 移动到循环之前吗?
  • 能够重现他的问题,我现在正在调查它。
  • @TimBiegeleisen 你是怎么做到的?
  • 我将他的代码作为 IntelliJ 的控制台应用程序运行。我确定这是某种神器……只是想弄清楚到底是什么。
  • 附带说明,尽管while(dataType==false) 在技术上是正确的语法,但将其表示为while(!dataType) 被认为更优雅。此外,您可以使用do-while 循环来强制执行至少一次迭代。

标签: java java.util.scanner validation


【解决方案1】:

有趣的问题!

扫描器试图将非整数转换为整数,但意识到它不能 - 所以它抛出了 InputMismatchException。但是,只有在翻译成功的情况下,它才会超越令牌。

意思是,无效字符串仍在输入缓冲区中,每次循环并尝试调用nextInt()时,它都会导致翻译失败。您从未将 dataType 设置为 true,因此您会无限循环。

要查看实际情况,您可以抓取 catch 块中的任意内容并将其打印出来:

catch(Exception JavaInputMismatch){
    System.out.println( sc.next() );
    System.out.println("Option not available.Try again.");
}

确实,输入无效后,我们得到如下:

Enter a number: hello
hello
Option not available.Try again.

Enter a number:

而且我们不会无限循环。这是因为对next() 的调用从输入缓冲区中获取了值,并将扫描仪的指针推进到该缓冲区中的下一个槽,该槽现在是空的。所以nextInt() 在这种情况下会等待输入。

哦,如果你在循环中初始化它工作正常的原因是扫描仪总是会开始读取新的输入;扫描器不会跨实例共享状态,因此由于重新初始化,上一次迭代的缓冲区中的“hello”不在下一次迭代的缓冲区中。

技术上,它仍在标准输入缓冲区中,但扫描仪指向该缓冲区的指针超出了无效字符串,因为它将开始读取任何 输入,不存在输入。

【讨论】:

    【解决方案2】:

    要添加到Purag 的答案,您也可以使用nextLine() 将扫描仪推进到当前行。

    所以你的 catch 块将如下所示:

    catch(Exception JavaInputMismatch)
        {
            System.out.println("Option not available.Try again.");
            sc.nextLine();
        }
    

    【讨论】:

      【解决方案3】:

      棘手的问题。

      你可能会得到它!

      答案很简单。 Scanner object 一直保持到执行结束,因为它在 while loop 之外声明。在内存层面看这个问题。

      Scanner 对象保持活动状态,因此在下次进入循环时,值(字符串值)仍将存在于 Scanner 对象中,并且它不会监听键盘,因为已经抛出异常。所以循环继续进行。

      注意:Scanner 类中的next() 方法将接受所有类型的键盘输入,但不接受其余方法,例如nextInt(), nextFloat() 等,

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多