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

发布于 2024-11-09 01:46:32 字数 645 浏览 0 评论 0原文

考虑以下代码:

#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;
}

执行时,仅第一个 scanf 停止提示。程序不会在接下来的 scanf 中停止。但如果格式字符串由"%[^\n]"改为"%[^\n]"(注意%<前面的空格) /code>),然后就可以正常工作了。是否自动接受先前输入缓冲区中的某些现有换行符?但刷新 stdin 并不能解决这个问题。

这是什么原因呢。

Consider the following code:

#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;
}

When it is executed only the first scanf stops for the prompt. The program does not stop for the next scanf s. But if the format string is changed from "%[^\n]" to " %[^\n]" (note the blank space before %), then it works okay. Does some existing newline character from the previous input buffer is automatically accepted ? But flushing stdin does not solve this.

What is the cause of this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜夜流光相皎洁 2024-11-16 01:46:32

您只需在阅读完所需内容后“使用”'\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");

You just need to 'consume' the '\n' character after you've read what you want. Use the following format directive:

"%[^\n]%*c"

Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').

Otherwise,the newline is left in the input stream waiting to immediately terminate the the subsequent "%[^\n]" format directives.

The problem with adding a space character to the format directive (" %[^\n]") is that the space will match any white space. So, it will eat the newline from the end of the previous input, but it will also eat any other whitespace (including multiple newlines).

Update to your example:

  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");
孤寂小茶 2024-11-16 01:46:32

当您使用 scanf() 读取字符串时,您的格式字符串 (%[^\n]) 会告诉函数读取除 ' 之外的每个字符\n'。这会将 '\n' 字符留在输入缓冲区中。因此,当您尝试读取 str2str3 时,scanf() 会发现缓冲区中的第一个内容是 '\n'< /code> 每次,由于格式字符串的原因,不会将其从输入缓冲区中删除。您需要的是从输入缓冲区读取数据的时间之间的 getchar()(通常紧接在 scanf() 之后)。由于缓冲区中已经存在 '\n',因此您的程序不会出现挂起的情况,因为它不必等待 getchar() 的输入收到。尝试一下。 :)

对于那些不知道 scanf() 修饰符的作用的人,这里是来自 http://linux.die.net/man/3/scanf -

[

匹配非空序列
指定集合中的字符
接受的字符;下一个指针
必须是一个指向 char 的指针,并且有
必须有足够的空间容纳所有
字符串中的字符,加上一个
终止空字节。平常的跳过
前导空白被抑制。
该字符串由以下组成
特定中(或不存在)的字符
放;该集合定义为
开括号 [ 之间的字符
字符和右括号]
特点。该集合不包括那些
如果第一个字符是字符
左括号后是抑扬符
(^)。要在中包含右括号
设置,使其成为之后的第一个字符
左括号或扬抑符;
任何其他位置都将结束该组。
连字符 - 也是
特别的;当放置在另外两个之间时
字符,它添加所有干预
字符集。要包括一个
连字符,使其成为最后一个字符
在最后一个右括号之前。为了
例如,[^]0-9-]表示集合
“除了右括号之外的所有内容,零
到九和连字符”。字符串
以a的出现结束
字符不在(或者,带有
扬抑符,在)设置或当字段
宽度用完。

When you use scanf() to read the strings, your format string (%[^\n]) tells the function to read every character that is not '\n'. That leaves the '\n' character in the input buffer. So when you try to read str2 and str3, scanf() finds the first thing in the buffer is '\n' each time and, because of the format string, doesn't remove it from the input buffer. What you need is a getchar() between the times that you read from the input buffer (often placed immediately after scanf()). Since there is already a '\n' in the buffer, your program won't appear to hang because it won't have to wait for input for getchar() to receive. Try it. :)

For those who haven't a clue what that scanf() modifier does, here is a relevant excerpt from http://linux.die.net/man/3/scanf -

[

Matches a nonempty sequence of
characters from the specified set of
accepted characters; the next pointer
must be a pointer to char, and there
must be enough room for all the
characters in the string, plus a
terminating null byte. The usual skip
of leading white space is suppressed.
The string is to be made up of
characters in (or not in) a particular
set; the set is defined by the
characters between the open bracket [
character and a close bracket ]
character. The set excludes those
characters if the first character
after the open bracket is a circumflex
(^). To include a close bracket in the
set, make it the first character after
the open bracket or the circumflex;
any other position will end the set.
The hyphen character - is also
special; when placed between two other
characters, it adds all intervening
characters to the set. To include a
hyphen, make it the last character
before the final close bracket. For
instance, [^]0-9-] means the set
"everything except close bracket, zero
through nine, and hyphen". The string
ends with the appearance of a
character not in the (or, with a
circumflex, in) set or when the field
width runs out.

没有你我更好 2024-11-16 01:46:32

还:
读取字符串:

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

// 这意味着读取直到遇到 '\n',然后丢弃该 '\n'

:)

ALSO:
To read a string:

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

// it means read until you meet '\n', then trash that '\n'

:)

她说她爱他 2024-11-16 01:46:32

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

Just use a getchar() after the scanf() function.

堇年纸鸢 2024-11-16 01:46:32

只是在上面的答案的基础上进一步添加一点——
如果我们想从输入流中删除一些特定的模式,假设数字 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() 。

Just adding a bit further to above answer-
If we want to remove some specific pattern, suppose numbers 0-9, from input stream then we will have to use getchar() for flushing buffer.

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);

So here if you pass ashish019 then only ashish will be copied to str and 019 would be left in buffer so for clearing that you need getchar() multiple times.

笑红尘 2024-11-16 01:46:32

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

use fflush(stdin) to clear the input buffer after reading each input.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文