【问题标题】:Code after while loop never executeswhile循环之后的代码永远不会执行
【发布时间】:2018-07-31 13:40:48
【问题描述】:

显然,我的真实代码更复杂,但这里有一个例子:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in).useDelimiter("\n");
        String[] cmdSplit = null; 
        while (true) {
            while (input.hasNext()) {
                cmdSplit = input.next().split("\\s+");
                System.out.println("stuff");
            }
            for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
        }
    }
}

在上面的示例中,代码从System.in 获取输入,将其拆分,并应输出每一部分。但是,由于某种原因,内部while 循环之后的代码永远不会执行。如果我用if 替换while,它就可以工作。如果你测试它,你会发现它不会无限运行,因为它只打印一次“stuff”,显示循环运行一次。 while 循环有什么问题?

【问题讨论】:

    标签: java while-loop


    【解决方案1】:

    System.in 读取不同于从文件或其他固定大小的输入源读取。输入在您创建之前不一定存在,因此尝试读取它需要block 直到输入实际到达(即您输入它)。尝试输入另一行 - 您将再次看到 stuff 消息;这将允许.hasNext() 返回,因为现在有输入。

    要让.hasNext() 返回false,需要关闭输入源。对于命令行应用程序,您可以通过发送EOF signal(Linux 上的 Ctrl+D)来执行此操作,它告诉进程 stdin 没有更多输入。但是,这通常不是您希望程序工作的方式,因此,如果您的意图是只读取一行然后继续,您实际上应该使用 if 而不是 while,因为您已经尝试过做。稍后如果您需要阅读更多输入,您将再次调用.hasNext(),您的程序将在那里阻塞,直到用户传递更多输入。


    正如@user7 提到的,您的外部while (true)while(input.hasNext()) 结合使用是多余的。如果您只想阅读一次,请摆脱while (true) 并使用if (input.hasNext())。否则,如果您想永远阅读,只需将两个循环结合起来:

    while (input.hasNext()) {
      cmdSplit = input.next().split("\\s+");
      System.out.println("stuff");
      for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
    } // Loop will terminate once stdin is closed, e.g. by the user sending EOF.
    

    【讨论】:

    • 想在此处添加一个点 - 外部无限循环没有用处,因为 input.hasNext() 此后不会返回 true(此处它将继续打印上次看到的内容)
    • 有什么方法可以检测结束而不发送EOF?
    • 在发送 EOF 之前没有结束 :) 在发送 EOF 之前,程序可以无限期地继续读取用户的输入。相反,您通常希望阅读您期望的输入,然后在阅读足够多后停止这样做。交互式程序通常会添加某种“转义”,例如在输入字符串为空时跳出循环。您想要的确切行为取决于您的具体用例。
    • 我可能会使用 if 和 splits 什么的。我正在试图读到用户输入的结尾,但我想这是有道理的,为什么你不能直到他们说它结束了。
    【解决方案2】:

    是的,您的代码不会进入 for 循环,因为 Scanner.hasNext() 将始终监听控制台的输入。

    你必须打破循环才能出来并进入 for 循环。

       Scanner input = new Scanner(System.in).useDelimiter("\n");
        String[] cmdSplit = null;
        while (true) {
          while (input.hasNext()) {
            cmdSplit = input.next().split("\\s+");
            System.out.println("stuff");
            break;
          }
          for (String element : cmdSplit) {
            System.out.println(element);
          }
        }
    

    【讨论】:

    • 如果您的意图是在通过while 循环后简单地中断(如在while (...) { ...; break; } 中,您可以只使用if 代替(if (...) { ...; })。
    【解决方案3】:

    它只打印一次“东西”的原因是 hasNext() 返回 false。

    让我解释一下我观察到的情况。

    要无限期地打印“东西”,必须删除分配。这意味着一旦您分配了输入,扫描仪就没有更多的令牌

    The java.util.Scanner.hasNext() method Returns true if this scanner has another token in its input.
    

    这将无限期打印

     while (input.hasNext()) {
                // cmdSplit = input.next().split("\\s+");
                System.out.println("stuff");
            }
    

    【讨论】:

    • 休息时怎么能无限打印
    • 是的,这是正确的。没看到。其实我是从错误的来源复制的。我现在正在编辑它
    猜你喜欢
    • 1970-01-01
    • 2011-01-20
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多