scanf:“%”跳过第二个输入,但“%”不跳过。 为什么?

请考虑以下代码:

#include  int main (void) { char str1[128], str2[128], str3[128]; printf ("\nEnter str1: "); scanf ("%[^\n]", str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf ("%[^\n]", str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf ("%[^\n]", str3); printf ("\nstr3 = %s", str3); printf ("\n"); return 0; } 

执行时,只有第一个scanf停止提示。 该程序不会停止下一次scanf 。 但是如果格式字符串从"%[^\n]"更改为" %[^\n]" (请注意%之前的空格),那么它可以正常工作。 是否会自动接受上一个输入缓冲区中的某些现有换行符? 但是冲洗stdin并不能解决这个问题。

造成这种情况的原因是什么。

在阅读完所需内容之后,您只需要“消费” '\n'字符。 使用以下格式指令:

 "%[^\n]%*c" 

哪个会将新行中的所有内容读入您传入的字符串中,然后将使用单个字符(换行符)而不将其分配给任何内容( '*'是’赋值抑制’)。

否则,换行符将保留在输入流中,等待立即终止后续的"%[^\n]"格式指令。

向格式指令( " %[^\n]" )添加空格字符的问题是空格将匹配任何空格。 因此,它将从前一个输入结束时吃掉换行符,但它也会吃掉任何其他空格(包括多个换行符)。

更新您的示例:

  char* fmt = "%[^\n]%*c"; printf ("\nEnter str1: "); scanf (fmt, str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf (fmt, str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf (fmt, str3); printf ("\nstr2 = %s", str3); printf ("\n"); 

当您使用scanf()读取字符串时,您的格式字符串( %[^\n] )告诉函数读取每个不是'\n'字符。 这会在输入缓冲区中留下'\n'字符。 因此,当您尝试读取str2str3scanf() str3发现缓冲区中的第一个内容是'\n'并且由于格式字符串,它不会将其从输入缓冲区中删除。 你需要的是你从输入缓冲区读取的时间之间的getchar() (通常紧接在scanf() )。 由于缓冲区中已经存在'\n' ,因此您的程序似乎不会挂起,因为它不必等待getchar()输入接收。 试试吧。 🙂

对于那些不知道scanf()修饰符是什么的人,这里是http://linux.die.net/man/3/scanf的相关摘录 –

[

匹配指定的一组接受字符的非空字符序列; 下一个指针必须是指向char的指针,并且字符串中的所有字符必须有足够的空间,加上一个终止的空字节。 通常跳过前导空格被抑制。 该字符串由特定集合中的字符组成(或不在其中); 该集合由open括号[character和close bracket]字符之间的字符定义。 如果开括号后面的第一个字符是旋音(^),则该集合将排除这些字符。 要在组中包含一个近括号,请将其作为开括号或旋转后的第一个字符; 任何其他位置将结束该集。 连字符 – 也很特别; 当放置在两个其他字符之间时,它会将所有插入字符添加到集合中。 要包含连字符,请将其设置为最后一个关闭括号之前的最后一个字符。 例如,[^] 0-9-]表示设置“除了近括号,从零到九,连字符的所有内容”。 字符串以字符的外观结束,而不是(或者,使用旋转,in)设置或字段宽度用完时。

另外:要读取字符串:

 scanf("%[^\n]\n", a); 

//它意味着读到你遇到’\ n’,然后删除’\ n’

🙂

只需在scanf()函数后使用getchar()。

只需在上面添加一些答案 – 如果我们想要删除一些特定的模式,假设数字0-9,从输入流,那么我们将不得不使用getchar()来刷新缓冲区。

 scanf("%[^0-9\n]", str1); while(getchar() != '\n'); // this approach is much better bcz it will // remove any number of left characters in buffer. scanf("%c", &ch); 

所以这里如果你传递ashish019那么只有ashish将被复制到str并且019将被留在缓冲区中,以便清除你需要多次getchar()。

读取每个输入后,使用fflush(stdin)清除输入缓冲区。