scanf:";%[^\n]";跳过第二个输入,但“跳过%[^\n]";没有。为什么?

scanf:";%[^\n]";跳过第二个输入,但“跳过%[^\n]";没有。为什么?,c,scanf,C,Scanf,考虑以下代码: #include <stdio.h> 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 ("\ns

考虑以下代码:

#include <stdio.h>

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;
}
#包括
内部主(空)
{
字符str1[128],str2[128],str3[128];
printf(“\n输入str1:”);
scanf(“%[^\n]”,str1);
printf(“\nstr1=%s”,str1);
printf(“\n输入str2:”);
scanf(“%[^\n]”,str2);
printf(“\nstr2=%s”,str2);
printf(“\n输入str3:”);
scanf(“%[^\n]”,str3);
printf(“\nstr3=%s”,str3);
printf(“\n”);
返回0;
}
执行时,只有第一个
scanf
停止提示。程序不会在下一个
scanf
s停止。但是如果格式字符串从<代码>“%[^ \n]”< /代码>改为<代码> %[^ \n] (请注意<代码> %之前的空白),那么它可以正常工作。是否自动接受上一个输入缓冲区中的某些现有换行符?但是刷新stdin不能解决这个问题

原因是什么。

当您使用
scanf()
读取字符串时,您的格式字符串(
%[^\n]
)告诉函数读取不是
'\n'
的每个字符。这将在输入缓冲区中保留
'\n'
字符。因此,当您尝试读取
str2
str3
时,
scanf()
每次都会在缓冲区中找到第一个对象是
'\n'
,并且由于格式字符串的原因,不会将其从输入缓冲区中删除。您需要的是在从输入缓冲区读取的时间之间的
getchar()
(通常紧跟在
scanf()
之后)。由于缓冲区中已经有一个
'\n'
,因此您的程序不会出现挂起的情况,因为它不必等待输入以接收
getchar()
。试试看。:)

对于那些不知道该
scanf()
修饰符的作用的人,这里是-

[

匹配一个非空的 来自指定集合的字符 接受的字符;下一个指针 必须是指向char的指针,并且 必须有足够的空间容纳所有的人 字符串中的字符,加上 终止空字节。通常跳过 前导空白的宽度被抑制。 这根绳子是由四根绳子组成的 特定字符(或非特定字符)中的字符 集合;集合由 括号中的字符[ 字符和右括号] 字符。集合不包括这些字符 如果第一个字符 后开口支架是一个旋臂 (^)。将右括号包括在 设置,使其成为后面的第一个字符 开放式支架或回旋支架; 任何其他位置都将结束设置。 连字符-也是 特殊的;当放置在两个其他物体之间时 字符,它添加了所有中间字符 字符集。要包括 连字符,让它成为最后一个字符 在最后一个闭合括号之前。用于 实例,[^]0-9-]表示集合 “除右括号外的所有内容均为零 通过九和连字符”。弦 以一个字母的外观结束 字符不在(或,带有 扬抑,in)设置或当字段 宽度耗尽


阅读完所需内容后,只需“使用”
“\n”
字符即可。使用以下格式指令:

"%[^\n]%*c"
它将把直到换行符的所有内容都读入您传入的字符串中,然后将使用单个字符(换行符),而不将其分配给任何内容(即
“*”
是“分配抑制”)

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

将空格字符添加到format指令(
“%[^\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");
读取每个输入后,使用
fflush(stdin)
清除输入缓冲区。

另外: 要读取字符串,请执行以下操作:

scanf("%[^\n]\n", a);
//意思是读到遇到“\n”,然后扔掉“\n”


:)

只是对上面的答案再补充一点- 若我们想从输入流中删除一些特定的模式,假设数字为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()。

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

同样的问题:那么后面的空格在“%[^\n]”中表示什么呢。这将正常工作。当您向格式字符串添加前导空格时,它将被计算为函数
isspace()
将返回真实值的任何字符,包括
'\n'
'
'\t'
,等等。这意味着忽略格式字符串中下一个非空格字符之前的空格字符。请注意,C99标准实际上没有指定
“%[”
@Chris的行为-什么意思C99没有指定
“%[”
?它在17.9.6.2“fscanf函数”中@Chris:有些部分是实现定义的,比如使用
'-'
来指定一个范围。这不是一个答案,但如果你研究
fgets
,你的生活会容易得多。我通常建议在大多数情况下避免使用
scanf
,但在这里,尤其是你使用的是一个非常强大且难以使用的函数对于一个非常简单的任务。这没关系,在我的末尾输入字符串没有问题,但是对行为或此功能的好奇。赋值抑制是一个很好的解决方案,实际上这是我第一次看到它有很好的用途……我刚刚用了上个月的时间使用“%*1[\n]”为此;+1,谢谢。这实际上是一种比调用
getchar
来使用尾随换行符更好的方法吗