vfscanf

vscanf, vfscanf, vsscanf, vscanf_s, vfscanf_s, vsscanf_s

Defined in header
​int vscanf( const char *restrict format, va_list vlist ​(1)(since C99)
int vfscanf( FILE *restrict stream, const char *restrict format, va_list vlist (2)(since C99)
int vsscanf( const char *restrict buffer, const char *restrict format, va_list vlist (3)(since C99)
int vscanf_s(const char *restrict format, va_list vlist(4)(since C11)
int vfscanf_s( FILE *restrict stream, const char *restrict format, va_list vlist(5)(since C11)
int vsscanf_s( const char *restrict buffer, const char *restrict format, va_list vlist(6)(since C11)

从各种来源读取数据,根据其解释并将format结果存储到由其定义的位置vlist

1)从中读取数据 stdin

2)从文件流中读取数据 stream

3)从以空字符结尾的字符串读取数据buffer。到达字符串的末尾等同于达到文件结束条件fscanf

4-6)与(1-3)相同,不同之处在于%c%s%[转换说明符每个都需要两个参数(通常的指针和rsize_t表示接收数组大小的类型值,当使用%c读取时可能为1成一个字符),除了在运行时检测到以下错误并调用当前安装的约束处理函数:

  • 指针类型的任何参数都是空指针

由于所有的边界检查功能,vscanf_s,vfscanf_s,和vsscanf_s仅保证可供如果__STDC_LIB_EXT1__由实现所定义,并且如果用户定义__STDC_WANT_LIB_EXT1__的整数常数1,包括之前<stdio.h>。

参数

-输入文件流从中读取
缓冲-指向以null结尾的字符串读取的指针
格式-指向以空字符结尾的字符串的指针,指定如何读取输入。
格式字符串由。
非空白多字节字符除外%:格式字符串中的每个这样的字符只消耗输入流中的一个完全相同的字符,或者如果流中的下一个字符不相等,则会导致函数失败。
空白字符:格式字符串中的任何单个空白字符都会消耗输入中所有可用的连续空白字符(如同通过调用isspace循环来确定)。请注意,有没有什么区别"\n"," ","\t\t"在格式字符串或其他空白。
转换规格。每个转换规范具有以下格式:
介绍%人物
(可选)分配抑制字符*。如果存在此选项,则函数不会将转换结果分配给任何接收参数。
(可选)指定最大字段宽度的整数数字(大于零),即该函数在执行由当前转换规范指定的转换时允许使用的最大字符数。请注意,如果未提供宽度,%s和%[可能会导致缓冲区溢出。
(可选) 长度修饰符,用于指定接收参数的大小,即实际的目标类型。这会影响转换精度和溢出规则。每种转换类型的默认目标类型都不相同(请参阅下表)。
转换格式说明符
以下格式说明符可用:
转换
说明符
长度修饰符
%
c
s
[组]
d
i
u
o
x, X
n
a,A(C99) ,
e,,E
fF
gG
p
对于每个转换说明符以外的n,最长的输入字符序列不超过任何指定的字段宽度,或者正是转换说明符所期望的或者是期望序列的前缀,是流中消耗的内容。在消耗序列之后的第一个字符(如果有的话)仍然未读。如果消耗的序列长度为零或消费的序列无法如上所述进行转换,则会发生匹配失败,除非文件结束,编码错误或读取错误阻止来自流的输入,在这种情况下,它是输入失败。
在尝试解析输入之前,除了[,,之外的所有转换说明符都会消耗并放弃所有前导空白字符(如同通过调用一样确定)。这些消耗的字符不会计入指定的最大字段宽度。cnisspace
转换说明符lc,ls并l[执行多字节到宽字符转换,就好像通过在第一个字符转换之前使用初始化为零mbrtowc()的mbstate_t对象调用一样。
除了匹配的字符之外,转换说明符s并[始终存储空终止符。目标数组的大小必须至少比指定的字段宽度大1。在不指定目标数组大小的情况下,使用%s或%[不安全gets。
为正确的转换规格固定宽度整数类型(int8_t等)都在头中定义<inttypes.h>还(虽然SCNdMAX,SCNuMAX等是同义词%jd,%ju等)。
每个转换说明符的操作之后都有一个序列点 ; 这允许将多个字段存储在相同的“汇”变量中。
在解析指数中不包含数字的不完整浮点值时(例如"100er"使用转换说明符进行解析),会消耗%f序列"100e"(可能有效的浮点数的最长前缀),从而导致匹配错误(消耗的序列不能转换为浮点数),"r"剩余的。现有的实现不遵循此规则并仅回滚消耗"100",只留下"er"例如glibc错误1765。
VLIST-包含接收参数的变量参数列表

  • 非空白多字节字符除外%:格式字符串中的每个这样的字符只消耗输入流中的一个完全相同的字符,或者如果流中的下一个字符不相等,则会导致函数失败。

以下格式说明符可用:

Conversion

说明符说明参数类型长度修饰符 hh(C99)。

h (none) l ll (C99).

j (C99).

z (C99).

t (C99).

L % 匹配字面% N / AN / AN / AN / AN / AN / AN / AN / AN / A c 一个匹配字符或序列字符如果使用宽度说明,完全匹配宽度字符(参数必须是一个指针数组有足够的空间)。与%s和%[不同,不会将空字符追加到数组。

N/A N/A char*

wchar_t*

N / AN / AN / AN / AN / A s 匹配非空白字符序列(字符串)如果使用宽度说明符,则匹配宽度或直到第一个空白字符,以先出现者为准。除了匹配的字符外,总是存储一个空字符(所以参数数组必须至少有宽度+ 1个字符的空间)。

`[`set`]` matches a non-empty sequence of character from set of characters. If the first character of the set is `^`, then all characters not in the set are matched. If the set begins with `]` or `^]` then the `]` character is also included into the set. It is implementation-defined whether the character `-` in the non-initial position in the scanset may be indicating a range, as in `[0-9]`. If width specifier is used, matches only up to _width_. Always stores a null character in addition to the characters matched (so the argument array must have room for at least _width+1_ characters).

`d` matches a **decimal integer**. The format of the number is the same as expected by [`strtol()`](../string/byte/strtol) with the value `10` for the `base` argument.

`signed char*` or `unsigned char*`

`signed short*` or `unsigned short*`

`signed int*` or `unsigned int*`

`signed long*` or `unsigned long*`

`signed long long*` or `unsigned long long*`

[`intmax_t`](../types/integer)`*` or [`uintmax_t`](../types/integer)`*`

size_t*

ptrdiff_t*

N / A i 匹配整数。数的格式是相同的通过按预期strtol()与值​0​base参数(基部由解析的第一字符确定)。

`u` matches an unsigned **decimal integer**. The format of the number is the same as expected by [`strtoul()`](../string/byte/strtoul) with the value `10` for the `base` argument.

`o` matches an unsigned **octal integer**. The format of the number is the same as expected by [`strtoul()`](../string/byte/strtoul) with the value `8` for the `base` argument.

`x`, `X` matches an unsigned **hexadecimal integer**. The format of the number is the same as expected by [`strtoul()`](../string/byte/strtoul) with the value `16` for the `base` argument.

`n` returns the **number of characters read so far**. No input is consumed. Does not increment the assignment count. If the specifier has assignment-suppressing operator defined, the behavior is undefined.

`a`, `A`(C99)

e, E

f, F

gG 匹配一个浮点数。数字的格式与预期的相同strtof()

N/A N/A float*

double*

N/A N/A N/A N/A long double*

`p` matches implementation defined character sequence defining a **pointer**. `printf` family of functions should produce the same sequence using `%p` format specifier.

N/A N/A void**

n不适用不适用不适用不适用不适用不适用不适用不适用于任何指定字段宽度的最长输入字符序列的 每个转换说明符,或者正是转换说明符所期望的或者是它期望的顺序是从流中消耗的。在消耗序列之后的第一个字符(如果有的话)仍然未读。如果消耗的序列长度为零或消费的序列不能如上所述进行转换,则会发生匹配失败,除非文件结束,编码错误或读取错误阻止了来自流的输入,在这种情况下,它是输入失败。

在尝试解析输入之前,除了[,,之外的所有转换说明符都会消耗并放弃所有前导空白字符(如同通过调用一样确定)。这些消耗的字符不会计入指定的最大字段宽度。cnisspace

转换说明符lclsl[执行多字节到宽字符转换,就好像通过在第一个字符转换之前使用初始化为零mbrtowc()mbstate_t对象调用一样。

除了匹配的字符之外,转换说明符s[始终存储空终止符。目标数组的大小必须至少比指定的字段宽度大1。在不指定目标数组大小的情况下,使用%s%[不安全gets

对于固定宽度的整数类型(正确的转换规格int8_t<inttypes.h>还(虽然,等等)都在头定义SCNdMAX,SCNuMAX等是同义词%jd,%ju等)。

每个转换说明符的操作之后都有一个序列点; 这允许将多个字段存储在相同的“汇”变量中。

在解析指数中不包含数字的不完整浮点值时(例如"100er"使用转换说明符进行解析),会消耗%f序列"100e"(可能有效的浮点数的最长前缀),从而导致匹配错误(消耗的序列不能转换为浮点数),"r"剩余的。现有的实现不遵循此规则并仅回滚消耗"100",只留下"er"例如glibc错误1765。

vlist - variable argument list containing the receiving arguments

返回值

1-3)成功分配的接收参数数目,或者EOF在分配第一个接收参数前发生读取失败。

4-6)与(1-3)相同,但是EOF如果存在运行时约束冲突,也会返回。

注意

所有这些函数va_arg至少调用一次,arg返回后的值是不确定的。这些函数不会调用va_end,并且它必须由调用者完成。

#include <stdio.h> #include <stdbool.h> #include <stdarg.h> bool checked_sscanf(int count, const char* buf, const char *fmt, ...) { va_list ap; va_start(ap, fmt int rc = vsscanf(buf, fmt, ap va_end(ap return rc == count; } int main(void) { int n, m; printf("Parsing '1 2'..." if(checked_sscanf(2, "1 2", "%d %d", &n, &m)) puts("success" else puts("failure" printf("Parsing '1 a'..." if(checked_sscanf(2, "1 a", "%d %d", &n, &m)) puts("success" else puts("failure" }

输出:

Parsing '1 2'...success Parsing '1 a'...failure