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'
字符。 因此,当您尝试读取str2
和str3
, scanf()
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)
清除输入缓冲区。