scanf() 语句中的格式字符串“%*[^\n]” 指示什么?赋值抑制器 (*) 和取反扫描集 ([^) 如何协同工作?
What does the format string "%*[^\n]" in a scanf() statement instruct? How do assignment suppressor (*) and negated scanset ([^) work together?
我知道引入带有 [
转换说明符的扫描集,它随后指示要匹配或不匹配的字符,并额外插入 ^
符号。
为此,在 ISO/IEC 9899/1999 (C99) 中规定:
The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.
因此,表达式 [^\n]
意味着它正在扫描字符,直到在相应的流中找到 \n
个字符,此处为 scanf()
、stdin
。 \n
不是取自 stdin
并且 scanf()
继续处理下一个格式字符串(如果有),否则它会跳到下一个 C 语句。
接下来是赋值抑制运算符*
:
为此,在 ISO/IEC 9899/1999 (C99) 中规定:
Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result.
f.e 情况下的含义。 scanf("%*100s",a);
从 stdin
中取出 100 个字符的序列,除非找到尾随的白色字符 space 但如果 a
是正确的,则不会分配给 a
-定义 char
101 个元素的数组 (char a[101];
).
但是现在 scanf() 语句中的格式字符串 "%*[^\n]"
实现了什么?
\n
是否留在stdin
?
赋值抑制器 *
和否定扫描集 [^
如何协同工作?
这是否意味着:
- 通过使用
*
所有与此格式字符串匹配的字符都取自 stdin
,但确定没有分配?,并且
\n
不是取自 stdin
但它用于确定相应格式字符串的扫描操作?
我知道 [^
和 *
每个人单独做什么,但不知道一起做什么。问题是这两者混合在一起的结果是什么,并结合了 \n
.
的否定扫描集
我知道 Stack Overflow 上有一个类似的问题,它只涵盖了对 %[^\n]
的理解,这里是:What does %[^\n] mean in a scanf() format string。但是那里的答案对我的问题没有帮助。
%[^\n]
读取到但不包括下一个 \n
字符。在简单的英语中,它读取一行文本。通常,该行将存储在 char *
字符串变量中。
char line[SIZE];
scanf("%[^\n]", line);
*
修饰符抑制该行为。该行在读取后被简单地丢弃,不需要变量。
scanf("%*[^\n]");
*
不会改变输入的处理方式。在任何一种情况下,从标准输入读取直到但不包括下一个 \n
的所有内容。假设没有 I/O 错误,可以保证下一次从 stdin 读取时会看到 \n
或 EOF
.
Which scanf()
statement should I use if I want to read and thereafter discard every character in stdin
including the \n
character?
添加 %*c
以同时消耗 \n
。
scanf("%*[^\n]%*c");
为什么 %*c
而不是 \n
?如果您使用 \n
它不会只消耗一个换行符,它会消耗任意数量的空格、制表符和换行符。 \n
匹配任意数量的空格。最好使用 %*c
正好消耗 1 个字符。
// Incorrect
scanf("%*[^\n]\n");
另请参阅:
- How to skip a line when fscanning a text file?
Could I use fflush()
instead?
不,不要。 fflush(stdin)
is undefined.
Isn't the negated scanset of [\n]
completely redundant because scanf()
terminate the scan process of the according format string at first occurrence of a white space character by default?
对于%s
,是的,它将在第一个空白字符处停止读取。 %s
只读一个字。 %[^\n]
,相比之下,读取整行。它不会停在空格或制表符处,只会停在换行符处。
更一般地说,只有方括号中列出的确切字符才相关。空格没有特殊行为。与 %s
不同,它不会跳过前导空格,也不会在遇到空格时提前停止处理。
Does \n
remain in stdin
?
是的,确实如此。
But what does now the format string "%*[^\n]"
in a scanf()
-statement achieve?
它从输入流中读取所有字符,直到到达换行符并丢弃它们,而不从输入流中删除换行符。
By using *
all characters matching to this format string are taken from stdin
, but are not assigned?
正确。
\n
isn't taken from stdin
but it is used to determine the scan-operation for the according format string?
没错。当达到 \n
时,大多数 scanf
使用 ungetc
将字符推回输入流。
I know what each of those [^
and *
do alone, but not together.
将 *
放在 [^
之前与 [^
完全相同,除了它不会将输入读入参数而是将其丢弃。
如果之后要丢弃 \n
,请使用此格式字符串:
"%*[^\n]%*c"
由于它似乎没有被覆盖,所以读取换行符之前的所有内容,然后是换行符的工作方式是:
scanf("%*[^\n]%*c");
%*[^\n]
读取并丢弃直到下一个字符为换行符
%*c
只读取并丢弃一个字符,上面的字符将是换行符
你也可以用 %c
读取换行符到一个变量,看看你是否真的成功获得换行符,但你也可以直接检查 EOF 或直接错误,而不必为此烦恼。
%[^\n]
告诉 scanf
读取所有内容直到换行符 ('\n'
) 并将其存储在相应的参数中。
%*[^\n]
告诉 scanf
读取所有内容直到换行符 ('\n'
) 并丢弃它而不是存储它。
示例:
- 将
Hi there\n
输入scanf("%[^\n]", buffer);
得到buffer
内容Hi there
和剩下的stdin
内容\n
- 将
Hi there\n
输入 scanf("%*[^\n]");
导致 Hi there
被扫描并从 stdin
和剩余的 stdin
内容 \n
中丢弃。
请注意,如果遇到的第一个字符是 \n
字符,%[^\n]
和 %*[^\n]
都会失败。一旦失败,stdin
保持不变,scanf
returns 导致格式字符串的其余部分被忽略。
如果您希望使用 scanf
清除一行 stdin
直到并包括换行符,请使用
scanf("%*[^\n]"); /* Read and discard everything until a newline character */
scanf("%*c"); /* Discard the newline character */
我知道引入带有 [
转换说明符的扫描集,它随后指示要匹配或不匹配的字符,并额外插入 ^
符号。
为此,在 ISO/IEC 9899/1999 (C99) 中规定:
The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.
因此,表达式 [^\n]
意味着它正在扫描字符,直到在相应的流中找到 \n
个字符,此处为 scanf()
、stdin
。 \n
不是取自 stdin
并且 scanf()
继续处理下一个格式字符串(如果有),否则它会跳到下一个 C 语句。
接下来是赋值抑制运算符*
:
为此,在 ISO/IEC 9899/1999 (C99) 中规定:
Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result.
f.e 情况下的含义。 scanf("%*100s",a);
从 stdin
中取出 100 个字符的序列,除非找到尾随的白色字符 space 但如果 a
是正确的,则不会分配给 a
-定义 char
101 个元素的数组 (char a[101];
).
但是现在 scanf() 语句中的格式字符串 "%*[^\n]"
实现了什么?
\n
是否留在stdin
?
赋值抑制器 *
和否定扫描集 [^
如何协同工作?
这是否意味着:
- 通过使用
*
所有与此格式字符串匹配的字符都取自stdin
,但确定没有分配?,并且 \n
不是取自stdin
但它用于确定相应格式字符串的扫描操作?
我知道 [^
和 *
每个人单独做什么,但不知道一起做什么。问题是这两者混合在一起的结果是什么,并结合了 \n
.
我知道 Stack Overflow 上有一个类似的问题,它只涵盖了对 %[^\n]
的理解,这里是:What does %[^\n] mean in a scanf() format string。但是那里的答案对我的问题没有帮助。
%[^\n]
读取到但不包括下一个 \n
字符。在简单的英语中,它读取一行文本。通常,该行将存储在 char *
字符串变量中。
char line[SIZE];
scanf("%[^\n]", line);
*
修饰符抑制该行为。该行在读取后被简单地丢弃,不需要变量。
scanf("%*[^\n]");
*
不会改变输入的处理方式。在任何一种情况下,从标准输入读取直到但不包括下一个 \n
的所有内容。假设没有 I/O 错误,可以保证下一次从 stdin 读取时会看到 \n
或 EOF
.
Which
scanf()
statement should I use if I want to read and thereafter discard every character instdin
including the\n
character?
添加 %*c
以同时消耗 \n
。
scanf("%*[^\n]%*c");
为什么 %*c
而不是 \n
?如果您使用 \n
它不会只消耗一个换行符,它会消耗任意数量的空格、制表符和换行符。 \n
匹配任意数量的空格。最好使用 %*c
正好消耗 1 个字符。
// Incorrect
scanf("%*[^\n]\n");
另请参阅:
- How to skip a line when fscanning a text file?
Could I use
fflush()
instead?
不,不要。 fflush(stdin)
is undefined.
Isn't the negated scanset of
[\n]
completely redundant becausescanf()
terminate the scan process of the according format string at first occurrence of a white space character by default?
对于%s
,是的,它将在第一个空白字符处停止读取。 %s
只读一个字。 %[^\n]
,相比之下,读取整行。它不会停在空格或制表符处,只会停在换行符处。
更一般地说,只有方括号中列出的确切字符才相关。空格没有特殊行为。与 %s
不同,它不会跳过前导空格,也不会在遇到空格时提前停止处理。
Does
\n
remain instdin
?
是的,确实如此。
But what does now the format string
"%*[^\n]"
in ascanf()
-statement achieve?
它从输入流中读取所有字符,直到到达换行符并丢弃它们,而不从输入流中删除换行符。
By using
*
all characters matching to this format string are taken fromstdin
, but are not assigned?
正确。
\n
isn't taken fromstdin
but it is used to determine the scan-operation for the according format string?
没错。当达到 \n
时,大多数 scanf
使用 ungetc
将字符推回输入流。
I know what each of those
[^
and*
do alone, but not together.
将 *
放在 [^
之前与 [^
完全相同,除了它不会将输入读入参数而是将其丢弃。
如果之后要丢弃 \n
,请使用此格式字符串:
"%*[^\n]%*c"
由于它似乎没有被覆盖,所以读取换行符之前的所有内容,然后是换行符的工作方式是:
scanf("%*[^\n]%*c");
%*[^\n]
读取并丢弃直到下一个字符为换行符%*c
只读取并丢弃一个字符,上面的字符将是换行符
你也可以用 %c
读取换行符到一个变量,看看你是否真的成功获得换行符,但你也可以直接检查 EOF 或直接错误,而不必为此烦恼。
%[^\n]
告诉scanf
读取所有内容直到换行符 ('\n'
) 并将其存储在相应的参数中。%*[^\n]
告诉scanf
读取所有内容直到换行符 ('\n'
) 并丢弃它而不是存储它。
示例:
- 将
Hi there\n
输入scanf("%[^\n]", buffer);
得到buffer
内容Hi there
和剩下的stdin
内容\n
- 将
Hi there\n
输入scanf("%*[^\n]");
导致Hi there
被扫描并从stdin
和剩余的stdin
内容\n
中丢弃。
请注意,如果遇到的第一个字符是 \n
字符,%[^\n]
和 %*[^\n]
都会失败。一旦失败,stdin
保持不变,scanf
returns 导致格式字符串的其余部分被忽略。
如果您希望使用 scanf
清除一行 stdin
直到并包括换行符,请使用
scanf("%*[^\n]"); /* Read and discard everything until a newline character */
scanf("%*c"); /* Discard the newline character */