为什么不是scanf(“%* \ n”); 和scanf(“%* %* c”); 清除挂线?

调用scanf("%d", &variable); 我们留下了一个挂在stdin的换行符,它应该在调用fgets之前清除,或者我们最终将它换成换行符并使其过早返回。

我找到了建议使用scanf("%*[^\n]%*c");答案scanf("%*[^\n]%*c"); 在第一次调用scanf以丢弃换行符后,其他人建议使用scanf("%*[^\n]\n"); 。 从理论上讲,两者都应该有效:第一个会消耗所有非换行符(但不包括换行符本身),然后只消耗一个字符(换行符)。 第二个将消耗所有非换行符(不包括它),然后\n ,一个空白字符,将指示scanf读取每个空白字符直到第一个非空白字符。

然而,尽管我看起来这些方法在某些答案中起作用,但我无法让它们在这里工作(下面的代码)。

为什么scanf方法都scanf

测试:Ubuntu Linux – gcc 5.4.0

scanf("%*[^\n]\n"); 做法:

 #include  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"); 做法:

 #include  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 " " 

以下方法是唯一一种按预期方式工作的方法:

工作方式:

 #include  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将立即返回而不读取任何内容。 添加*不会改变那个基本事实。 事实certificate,只有一次通话你不能这样做,你需要两个:

 scanf("%*[^\n]"); scanf("%*c"); 

请注意,将裸线换入扫描模式几乎总是没用 – 它会导致scanf读取并丢弃所有空格,直到它看到非空白字符(将留在输入缓冲区中)。 特别是如果您尝试在交互式程序中使用它,它将一直挂起,直到您输入非空白行。