vsscanf_s
Defined in header <stdio.h>  |   |   | 
|---|---|---|
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成一个字符),除了在运行时检测到以下错误并调用当前安装的约束处理函数:   
- 指针类型的任何参数都是空指针
 format,stream或者buffer是空指针- %c,%s或%[,加上终止空字符,将会超过为每个转换说明符提供的第二个(rsize_t)参数所写的字符数
 - 可选地,还有任何其他可检测到的错误,例如未知的转换说明符
 
  由于所有的边界检查功能,vscanf_s,vfscanf_s,和vsscanf_s仅保证可供如果__STDC_LIB_EXT1__由实现所定义,并且如果用户定义__STDC_WANT_LIB_EXT1__的整数常数1,包括之前<stdio.h>。  
参数
流  | -  | 输入文件流从中读取  | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
缓冲  | -  | 指向以null结尾的字符串读取的指针  | ||||||||||
格式  | -  | 指向以空字符结尾的字符串的指针,指定如何读取输入。  | ||||||||||
格式字符串由。  | ||||||||||||
非空白多字节字符除外%:格式字符串中的每个这样的字符只消耗输入流中的一个完全相同的字符,或者如果流中的下一个字符不相等,则会导致函数失败。  | ||||||||||||
空白字符:格式字符串中的任何单个空白字符都会消耗输入中所有可用的连续空白字符(如同通过调用isspace循环来确定)。请注意,有没有什么区别"\n"," ","\t\t"在格式字符串或其他空白。  | ||||||||||||
转换规格。每个转换规范具有以下格式:  | ||||||||||||
介绍%人物  | ||||||||||||
(可选)分配抑制字符*。如果存在此选项,则函数不会将转换结果分配给任何接收参数。  | ||||||||||||
(可选)指定最大字段宽度的整数数字(大于零),即该函数在执行由当前转换规范指定的转换时允许使用的最大字符数。请注意,如果未提供宽度,%s和%[可能会导致缓冲区溢出。  | ||||||||||||
(可选) 长度修饰符,用于指定接收参数的大小,即实际的目标类型。这会影响转换精度和溢出规则。每种转换类型的默认目标类型都不相同(请参阅下表)。  | ||||||||||||
转换格式说明符  | ||||||||||||
以下格式说明符可用:  | ||||||||||||
转换  | 说明  | 参数类型  | ||||||||||
说明符  | ||||||||||||
长度修饰符  | hh  | h  | (没有)  | l  | ll  | j  | z  | t  | L  | |||
(C99)。  | (C99)。  | (C99)。  | (C99)。  | (C99)。  | ||||||||
%  | 匹配文字 %  | N / A  | N / A  | N / A  | N / A  | N / A  | N / A  | N / A  | N / A  | N / A  | ||
c  | 匹配一个字符或一系列字符  | N / A  | N / A  | char*  | wchar_t*  | N / A  | N / A  | N / A  | N / A  | N / A  | ||
如果使用宽度说明符,则完全匹配宽度字符(参数必须是指向具有足够空间的数组的指针)。与%s和%[不同,不会将空字符追加到数组。  | ||||||||||||
s  | 匹配一系列非空白字符(一个字符串)  | |||||||||||
如果使用宽度说明符,则匹配宽度或直到第一个空白字符(以先出现者为准)。除了匹配的字符外,总是存储一个空字符(所以参数数组必须至少有宽度+ 1个字符的空间)。  | ||||||||||||
[组]  | 匹配一组字符中的非空字符序列。  | |||||||||||
如果该集合的第一个字符是^,则不匹配该集合中的所有字符。如果集合以该字符开头]或者^]该]字符也包含在集合中。它是实现定义的-,即扫描集中非初始位置的字符是否可以指示范围,如in [0-9]。如果使用宽度说明符,则只匹配宽度。除了匹配的字符外,总是存储一个空字符(所以参数数组必须至少有宽度+ 1个字符的空间)。  | ||||||||||||
d  | 匹配一个十进制整数。  | signed char* 要么 unsigned char*  | signed short*要么 unsigned short*  | signed int* 要么 unsigned int*  | signed long* 要么 unsigned long*  | signed long long*要么 unsigned long long*  | intmax_t*要么 uintmax_t*  | size_t*  | ptrdiff_t*  | N / A  | ||
数的格式是相同的通过按预期strtol()与值10的base参数。  | ||||||||||||
i  | 匹配一个整数。  | |||||||||||
数的格式是相同的通过按预期strtol()与值0的base参数(基部由解析的第一字符确定)。  | ||||||||||||
u  | 匹配一个无符号的十进制整数。  | |||||||||||
数的格式是相同的通过按预期strtoul()与值10的base参数。  | ||||||||||||
o  | 匹配一个无符号的八进制整数。  | |||||||||||
数的格式是相同的通过按预期strtoul()与值8的base参数。  | ||||||||||||
x, X  | 匹配一个无符号的十六进制整数。  | |||||||||||
数的格式是相同的通过按预期strtoul()与值16的base参数。  | ||||||||||||
n  | 返回到目前为止读取的字符数。  | |||||||||||
没有输入被消耗。不增加分配计数。如果说明符具有定义的分配抑制运算符,则行为未定义。  | ||||||||||||
a,A(C99) ,  | 匹配一个浮点数。  | N / A  | N / A  | float*  | double*  | N / A  | N / A  | N / A  | N / A  | long double*  | ||
e,,E  | 数字的格式与预期的相同strtof()。  | |||||||||||
fF  | ||||||||||||
gG  | ||||||||||||
p  | 匹配定义指针的实现定义的字符序列。  | N / A  | N / A  | void**  | N / A  | N / A  | N / A  | N / A  | N / A  | N / A  | ||
printf函数族应该使用%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  | -  | 包含接收参数的变量参数列表  | ||||||||||
返回值
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本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com

