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

2022-09-04 02:45:26

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

while (!StdIn.isEmpty())

附带了一些读取用户输入的代码,但我似乎无法打破循环。根据我的理解,如果我在没有输入任何文本的情况下按Enter键,这应该意味着标准输入是空的,while循环应该被打破。我查找了 isEmpty 的代码,但它没有澄清任何内容:

public static boolean isEmpty() {
    return !scanner.hasNext();
}

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


答案 1

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

因此实际上是.isEmptyisCtrl-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);
     }
 } 

,标准输入流在首次决定条件时弹出,而不是 。如果随后键入一些数字,返回它们,导致标准输入流不为空,则程序将跳入 while 主体内部。我通过测试发现这是这种情况while (!StdIn.isEmpty)StdIn.readDouble()

> java Average
 [DrJava Input Box] (And I hit Ctrl+D here)
Average is NaN

NaN表示n = 0,这意味着身体没有接触。


答案 2

我认为在Mac上,您可以使用()来标记shell输入的结束。请参见: https://www.jetbrains.com/help/idea/debug-tool-window-console.htmlCMD+D⌘+D

键盘快捷键

⌘D 组合键允许您发送 EOF(文件末尾),即发出信号,表明无法从数据源读取更多数据。

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

while (!StdIn.isEmpty()) {
     int p = StdIn.readInt();
     int q = StdIn.readInt();

     if (!uf.connected(p, q)) {
         uf.union(p, q);
         StdOut.println(p + " " + q);
     }
}

以下是我所做的:

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

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

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

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

以下是我对这个问题的快速和肮脏的方法:

package com.algorithms;

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.UF;

import java.util.Scanner;

public class Week1 {
    private static UF uf;

    public static void main(String[] args)
    {
        StdOut.println("Enter the total number of objects: ");
        int N = StdIn.readInt();

        StdOut.println("Enter the unions between any of those objects...");

        Week1.uf = new UF(N);
        while (true) {

            int p = StdIn.readInt();
            int q = StdIn.readInt();

            if (!uf.connected(p, q)) {
                Week1.uf.union(p, q);
                StdOut.println(p + " " + q);
            }

            if(p==0 && q==0) break;
        }
        checkIfConnected();
    }

    private static void checkIfConnected()
    {
        StdOut.println("Check if 2 objects are connected: ");
        try {
            Scanner reader = new Scanner(System.in);  // Reading from System.in
            System.out.println("Enter first object: ");
            int n = reader.nextInt(); // Scans the next token of the input as an int.
            System.out.println("Enter second object: ");
            int m = reader.nextInt(); // Scans the next token of the input as an int.
            StdOut.println(Week1.uf.connected(n, m) ? "Connected" : "Not Connected");
        } catch(Exception e) {}
    }
}