为什么不是scanf(“%* [^ \ n] \ n");和scanf(“%* [^ \ n]%* c");清除挂起的换行符? [英] Why aren't scanf("%*[^\n]\n"); and scanf("%*[^\n]%*c"); clearing a hanging newline?
问题描述
在调用scanf("%d", &variable);
之后,我们在 stdin 上保留了换行符,应该在调用fgets
之前清除该换行符,否则我们最终将其换行并生成它会过早返回.
After a call to scanf("%d", &variable);
we are left with a newline hanging at the stdin, which should be cleared before a call to fgets
, or we end up feeding it a newline and making it return prematurely.
在第一次调用scanf
放弃换行符后,我已经找到建议使用scanf("%*[^\n]%*c");
的答案,而其他建议使用scanf("%*[^\n]\n");
的答案.从理论上讲,两者都应该起作用:第一个将使用所有不是换行符的内容(但不包括换行符本身),然后完全使用 个字符(换行符).第二个会消耗掉所有不是换行符的内容(不包括换行符),然后\n
(一个空白字符)将指示scanf
读取每个空白字符,直到第一个非空白字符为止.
I've found answers suggesting using scanf("%*[^\n]%*c");
after the first call to scanf
to discard the newline and others suggesting using scanf("%*[^\n]\n");
. Theoretically, both should work: The first would consume everything that isn't a newline (but not including the newline itself) and then consume exactly one character (the newline). The second would consume everything that isn't a newline (not including it) and then \n
, a whitespace character, would instruct scanf
to read every whitespace characters up to the first non-whitespace character.
但是,就我所知,这些方法在某些答案中确实奏效,但我无法在这里使它们奏效(下面的代码).
However, as much as I've seem those approaches working in some answers, I couldn't get them to work here (codes below).
为什么scanf
方法都不起作用?
Why neither of the scanf
approaches worked?
经过以下测试:
Ubuntu Linux-gcc
5.4.0
Tested on:
Ubuntu Linux - gcc
5.4.0
#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]\n");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
输出:
$ ./bug
Write number:
2
Write phrase:
You wrote:2 and "
"
scanf("%*[^\n]%*c");
方法:
scanf("%*[^\n]%*c");
approach:
#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]%*c");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
输出:
$ ./bug2
Write number:
3
Write phrase:
You wrote:3 and "
"
以下方法是唯一按预期方式工作的方法:
The following approach was the only one that worked the way it was expected to:
#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin!
int c;
while((c = getchar()) != '\n' && c != EOF){
//Discard up to (and including) newline
}
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
输出:
$ ./notbug
Write number:
4
Write phrase:
phrase :D
You wrote:4 and "phrase :D
"
推荐答案
基本问题是scanf模式%[^\n]
与不是换行符的一个或多个字符匹配.因此,如果下一个字符是换行符,则模式将失败并且scanf
将立即返回而不会读取任何内容.添加*
不会更改该基本事实.因此,事实证明您不能仅凭一个电话就可以做到这一点,您需要两个:
The basic problem is that the scanf pattern %[^\n]
matches ONE OR MORE characters that are not newlines. So if the next character is a newline, the pattern will fail and scanf
will return immediately without reading anything. Add a *
doesn't change that basic fact. So it turns out you can't do this with only one call, you need two:
scanf("%*[^\n]"); scanf("%*c");
请注意,将空白的换行符放在扫描模式中几乎总是无用的-它导致scanf读取并丢弃所有空白,直到看到一个非空白字符(它将留在输入缓冲区中).尤其是如果您尝试在交互式程序中使用它,它将显示为挂起状态,直到您输入非空白行为止.
Note that putting a bare newline into the scan pattern is almost always not useful -- it causes scanf to read and discard all whitespace until it sees a non-whitespace character (which will be left in the input buffer). Particularly if you try to use it in an interactive program, it will appear to hang until you enter a non-blank line.
这篇关于为什么不是scanf(“%* [^ \ n] \ n");和scanf(“%* [^ \ n]%* c");清除挂起的换行符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!