如何使 StdIn.isEmpty() 返回 true?

RB3*_*B34 10 java eclipse algorithm stdin

我正在使用算法 Coursera 算法课程中提供的普林斯顿库中的 StdIn.isEmpty() 方法,但对其工作方式感到困惑。我有声明

while (!StdIn.isEmpty())
Run Code Online (Sandbox Code Playgroud)

包含一些读取用户输入的代码,但我似乎无法跳出循环。根据我的理解,如果我在没有输入任何文本的情况下按 Enter 键,这应该意味着标准输入为空并且 while 循环应该被破坏。我查找了 isEmpty 的代码,但没有说明任何内容:

public static boolean isEmpty() {
    return !scanner.hasNext();
}
Run Code Online (Sandbox Code Playgroud)

有人可以澄清标准输入的工作原理并帮助我解决我对这种方法的误解吗?

小智 8

在读取每个数字之前,程序使用方法 StdIn.isEmpty() 来检查输入流中是否还有更多数字。我们如何发出信号表明我们没有更多的数据可以输入?按照惯例,我们键入一个特殊的字符序列,称为文件结束序列。不幸的是,我们通常在现代操作系统上遇到的终端应用程序对这个至关重要的序列使用不同的约定。在本书中,我们使用 Ctrl-D... 计算机科学 Sedgewick

所以isEmpty其实是isCtrl-D

此外,StdIn.isEmpty()在没有任何事先准备的终端应用程序中尝试将使您没有布尔值,而是一个请求输入的标准输入流。所以当像下面这样的程序运行时:

public class Average
  {
     public static void main(String[] args)
     {  // Average the numbers on standard input.
        double sum = 0.0;
        int n = 0;
        while (!StdIn.isEmpty())
        {  // Read a number from standard input and add to sum.
           double value = StdIn.readDouble();
           sum += value;
           n++;
        }
        double average = sum / n;
        StdOut.println("Average is " + average);
     }
 } 
Run Code Online (Sandbox Code Playgroud)

, 标准输入流while (!StdIn.isEmpty)在第一次决定条件时弹出而不是StdIn.readDouble(). 如果然后输入一些数字,返回它们,导致标准输入流非空,程序将跳转到 while 主体内。我通过测试发现情况确实如此

> java Average
 [DrJava Input Box] (And I hit Ctrl+D here)
Average is NaN
Run Code Online (Sandbox Code Playgroud)

NaN 意味着 n = 0,这意味着没有触及 while 主体。


Rui*_*lho 6

我认为在 Mac 上您可以使用CMD+D( \xe2\x8c\x98+D) 来标记 shell 输入的结束。请参阅:https://www.jetbrains.com/help/idea/debug-tool-window-console.html

\n\n
\n

键盘快捷键

\n\n

\xe2\x8c\x98D 组合键允许您发送 EOF(文件结束),即\n 表示无法从数据源读取更多数据。

\n
\n\n

关于 Coursera 课程中的算法 - 第 1 部分中提供的普林斯顿库的问题,您可以稍微玩一下他们的代码,特别是在课堂上import edu.princeton.cs.algs4.StdIn;。他们使用该代码的实现可能不是最复杂的概念:

\n\n
while (!StdIn.isEmpty()) {\n     int p = StdIn.readInt();\n     int q = StdIn.readInt();\n\n     if (!uf.connected(p, q)) {\n         uf.union(p, q);\n         StdOut.println(p + " " + q);\n     }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这就是我所做的:

\n\n
    \n
  1. 在 IntelliJ 中创建新的 Java 项目
  2. \n
  3. 创建新的java包(将在src下)
  4. \n
  5. 为他们的示例创建新类,该类将有一个 main 方法
  6. \n
  7. 在项目中创建libs文件夹
  8. \n
  9. 从http://algs4.cs.princeton.edu/code/algs4.jar下载他们的代码并将该 jar 放在 libs 文件夹中
  10. \n
  11. 将该库添加到项目中 - 在 IntelliJ 的项目选项卡上,右键单击项目 > 打开模块设置 > 单击依赖项选项卡 > 单击 \'+\' > JAR 或目录... > 从上面的 libs 文件夹中选择 jar
  12. \n
  13. 我更改了上面 while 循环中的代码,以便在 shell 上实现更好的用户交互(这里要有创意 - 例如,不要使用 isEmpty(),而是使用检查 p 和 q 都为 0 来标记输入结束。
  14. \n
\n\n

现在要运行它,只需右键单击具有主静态方法的类的代码,然后选择“运行”(CTRL+SHIFT+R)。

\n\n

如果您想在 while 循环后编写更多代码,这将避免可怕的 CMD+D 以及随之而来的一些问题 - 例如,我添加了代码来检查 2 个对象是否已连接:

\n\n
StdOut.println("Check if 2 objects are connected: ");\ntry {\n    Scanner reader = new Scanner(System.in);  // Reading from System.in\n    System.out.println("Enter first object: ");\n    int n = reader.nextInt(); // Scans the next token of the input as an int.\n    System.out.println("Enter second object: ");\n    int m = reader.nextInt(); // Scans the next token of the input as an int.\n    StdOut.println(uf.connected(n, m) ? "Connected" : "Not Connected");\n} catch(Exception e) {\n    // whatever...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我解决问题的快速而肮脏的方法:

\n\n
package com.algorithms;\n\nimport edu.princeton.cs.algs4.StdIn;\nimport edu.princeton.cs.algs4.StdOut;\nimport edu.princeton.cs.algs4.UF;\n\nimport java.util.Scanner;\n\npublic class Week1 {\n    private static UF uf;\n\n    public static void main(String[] args)\n    {\n        StdOut.println("Enter the total number of objects: ");\n        int N = StdIn.readInt();\n\n        StdOut.println("Enter the unions between any of those objects...");\n\n        Week1.uf = new UF(N);\n        while (true) {\n\n            int p = StdIn.readInt();\n            int q = StdIn.readInt();\n\n            if (!uf.connected(p, q)) {\n                Week1.uf.union(p, q);\n                StdOut.println(p + " " + q);\n            }\n\n            if(p==0 && q==0) break;\n        }\n        checkIfConnected();\n    }\n\n    private static void checkIfConnected()\n    {\n        StdOut.println("Check if 2 objects are connected: ");\n        try {\n            Scanner reader = new Scanner(System.in);  // Reading from System.in\n            System.out.println("Enter first object: ");\n            int n = reader.nextInt(); // Scans the next token of the input as an int.\n            System.out.println("Enter second object: ");\n            int m = reader.nextInt(); // Scans the next token of the input as an int.\n            StdOut.println(Week1.uf.connected(n, m) ? "Connected" : "Not Connected");\n        } catch(Exception e) {}\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n