为什么我的 scanf while 循环在使用换行符时不退出?

Why does my scanf while loop not exit when consuming newline characters?

// Some initialization code

dup2(fd[0], fileno(stdin));

// This process is receiving the output of "ls -1"

while (scanf("%[^\n]s", someCharArray) > 0) {
    scanf("%*c");
    printf("%s\n", someCharArray);
}

这将成功打印所有文件。但是,循环永远不会退出。如果我拿走 scanf("%*c"),它会退出,但只打印第一个文件名。

我希望换行符的消耗将使外部 scanf 准备好扫描下一个文件名,这似乎是它正在做的。但是在扫描最终文件名之后,我希望嵌套的 scanf 不会扫描任何内容。然后外部 scanf 也不扫描任何东西。 while 循环退出。

Why is this happening?

循环没有退出,因为它正在等待更多输入。

你可以

  1. 发送一对 \n\n 所以 scanf("%[^\n]... returns 0 因为它无法扫描第二个 \n

  2. 关闭stdin(以特定实现方式)所以scanf()returnEOF,一个负数。

最好使用 fgets() 虽然还不清楚你希望循环在什么条件下结束(除了 stdin 闭包)。

while (fgets(someCharArray, sizeof someCharArray, stdin)) {
  // Lop off potential trailing \n if desired
  someCharArray[strcspn(someCharArray, "\n")] = '[=10=]';

  printf("%s\n", someCharArray);
}

注意:scanf("%[^\n]s", someCharArray) 中的 "s" 没有任何作用 - 删除它。此外,这种没有宽度的格式不会限制扫描到 someCharArray 的最大字符数,不应在质量代码中使用。


I would expect the consuming of the newline character will prepare the outer scanf to scan the next filename, which is what it seems to be doing.

是的 - 没错。较早的 scanf("%[^\n]... 对扫描的字符数没有限制,这可能会导致未定义的行为 (UB),那么为什么要期望其余代码的行为呢?

But after the final filename is scanned, I expect the nested scanf to not scan anything.

如果最终文件名后面有 '\n'scanf("%*c"); 将使用它。如果最终文件名缺少任何后续字符,scanf("%*c"); 将耐心等待一个字符。如果输入流已经关闭,它将return EOF 而不是等待。代码没有 report/test scanf("%*c"); 的结果,所以我们只能猜测。

Then the outer scanf to not scan anything either. And the while loop exits.

正确,如果要扫描的第一个字符是 '\n',它将保留在 stdin 中,而 scanf() 将 return 0。如果 stdin关闭时,scanf() 将 return 负数 EOF.