我正在使用算法 Coursera 算法课程中提供的普林斯顿库中的 StdIn.isEmpty() 方法,但对其工作原理感到困惑。我有声明
while (!StdIn.isEmpty())
附带一些读取用户输入的代码,但我似乎无法跳出循环。根据我的理解,如果我按回车键而不输入任何文本,则意味着标准输入为空,并且 while 循环应该被打破。我查找了 isEmpty 的代码,但它没有澄清任何内容:
public static boolean isEmpty() {
return !scanner.hasNext();
}
有人可以澄清标准输入的工作原理并帮助我纠正我对此方法的误解吗?
在读取每个数字之前,程序使用 StdIn.isEmpty() 方法检查输入流中是否还有更多数字。我们如何表明我们没有更多数据可输入?按照惯例,我们键入一个特殊的字符序列,称为文件结尾序列。不幸的是,我们在现代操作系统上通常遇到的终端应用程序对这个极其重要的序列使用不同的约定。在本书中,我们使用 Ctrl-D... 计算机科学塞奇威克
因此
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);
}
}
,第一次决定条件
while (!StdIn.isEmpty)
而不是StdIn.readDouble()
时会弹出标准输入流。如果您随后输入一些数字并返回它们,导致标准输入流非空,则程序将跳转到 while 体内。我通过测试发现是这样的
> java Average
[DrJava Input Box] (And I hit Ctrl+D here)
Average is NaN
NaN 表示 n = 0,这意味着当身体没有被触摸时。
我认为在 Mac 上您可以使用
CMD+D
(⌘+D
) 来标记 shell 输入的结束。请参阅:https://www.jetbrains.com/help/idea/debug-tool-window-console.html
键盘快捷键
⌘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);
}
}
这就是我所做的:
现在要运行它,只需右键单击具有主静态方法的类的代码,然后选择“运行”(CTRL+SHIFT+R)。
如果您想在 while 循环后编写更多代码,这将避免可怕的 CMD+D 以及随之而来的一些问题 - 例如,我添加了代码来检查 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) {}
}
}