scanf 系列函数使用的格式字符串

组成部分

这种格式字符串由下列内容组成:

  • 非空白多字节字符,除了 % :每个格式字符串中的这种字符处理来自输入流的准确同一字符,或若它与流的下个字符比较不相等则导致函数失败。
  • 空白符:任何格式字符串中的单个空白符处理所有来自输入的可用连续空白符(如同通过于循环中调用 isspace 确定)。注意格式字符串中 “\n” 、 " " 、 “\t\t” 或其他空白无区别。
  • 转换指定:每个转换指定拥有下列格式:
    • 引入用 % 字符。
    • (可选)赋值抑制字符 * 。若存在此选项,则此函数不将结果赋值给任何接收用参数。
    • (可选)指定最大域宽的整数数字(大于零),即函数进行在当前转换指定所指定的转换时,允许处理的最大字符数。注意若不提供宽度,则 %s 和 %[ 可能导致缓冲区溢出。
    • (可选)指定接收参数大小的长度修饰符,即实际目标类型。这影响转换准确性和溢出规则。默认目标类型对每个转换类型不同(见本文“格式指定符”)。
    • 转换格式指定符。

格式指定符

下列格式指定符可用(注意有些类型1仅在C99标准中):

转换指定符解释备注支持参数类型
%匹配字面 % 。//
c匹配一个字符字符的序列。若使用了宽度指定符,则匹配准确的宽度个字符(该参数必须是指向有充足空间的数组的指针)。不同于 %s 和 %[ ,它不会在数组后附加空字符。char* 和 wchar_t*
s匹配非空白字符的序列(一个字符串)。若使用宽度指定符,则至多匹配宽度个字符,或匹配到首个提前出现的空白符前。总是在匹配的字符后存储一个空字符(故参数数组必须有至少宽度 +1 个字符的空间)。char* 和 wchar_t*
[set]匹配一个来自 set 的字符的非空字符序列。若集合的首字符是 ^ ,则匹配所有不在集合中的字符。若集合以 ] 或 ^] 开始,则 ] 字符亦被包含入集合。在扫描集合的非最初位置的字符 - 是否可以指示范围,如 [0-9] ,是实现定义的。若使用宽度指定符,则最多匹配到宽度。总是在匹配的字符后存储一个空字符(故参数数组必须有至少宽度 +1 个字符的空间)。char* 和 wchar_t*
d匹配一个十进制整数该数的格式同 strtol() 以值 10 为 base 时所期望者。各种整数指针类型2
i匹配一个整数该数的格式同 strtol() 以值 ​0​ 为 base 时所期望者(基底以首个分析的字符确定)。各种整数指针类型2
u匹配一个无符号十进制整数该数的格式同 strtoul() 以值 10 为 base 参数时所期望者。各种整数指针类型2
o匹配一个无符号八进制数该数的格式同 strtoul() 以值 8 为 base 参数时所期望者。各种整数指针类型2
x和X匹配一个无符号十六进制数该数的格式同 strtoul() 以值 16 为 base 参数时所期望者。各种整数指针类型2
n返回迄今读取的字符数。不消耗输出。不增加赋值计数。若此指定符拥有赋值抑制运算符,则行为未定义。各种整数指针类型2
a , A(C99) , e , E , f , F , g 和 G匹配一个浮点数该数的格式同 strtof() 所期望者。float* , double* 和 long double*
p匹配定义一个指针的实现定义的字符序列。printf 系列函数应该用 %p 格式指定符产生同样的序列。void**

对于每个异于 n 的转换指定符,不超过任何指定域宽,且要么是转换指定符所准确期待,要么是其所期待的前缀的最长输入字符序列,即是从流中消耗的内容。此消耗序列后的首个字符若存在,则保持未读取。若被消耗序列长度为零,或被消耗序列不能转换成上面所指定的项目,则发生匹配失败,除非遇到文件尾、编码错误,或阻止从流输入的读取错误,此情况下此为输入失败。
所有异于 [ 、 c 和 n 的转换指定符,在尝试分析输入前消耗并舍弃所有前导空白字符(如同以调用 isspace 来确定)。这些被消耗的字符不计入指定的最大域宽。
转换指定符 lc 、 ls 和 l[ 进行多字节到宽字符转换,如同如同在转换首字符前,通过用初始化到零的 mbstate_t 对象调用 mbrtowc() 。
转换指定符 s 与 [ 始终在匹配字符之后存储一个空字符。目标数组的大小必须至少比指定域宽大一。
定宽整数类型( int8_t 等)的正确的转换指定定义于头文件 <inttypes.h> (虽然 SCNdMAX 、 SCNuMAX 等就是 %jd 、 %ju 等的别名)。
在每个转换指定符后有一个序列点;这允许存储多个域到同一“池”变量中。
在分析以无数字指数为结尾的不完整浮点值,如以转换指定符 %f 分析 “100er” 时,消耗序列 “100e” (可能为合法浮点数的最长前缀),并导致匹配错误(被消耗序列不能转换成浮点数),而留下 “r” 。某些既存实现不遵守此规则并回滚,通过消耗 “100” 而留下 “er” ,例如 glibc 漏洞 1765 。
若转换指定非法,则行为未定义。

参考资料

C++参考手册(英文版)
C++参考手册(中文版)


  1. 在C99中,能输入的类型中这些是只存在于C99中的: signed char* , unsigned char , signed long long* , unsigned long long* , intmax_t , uintmax_t , size_t* 和 ptrdiff_t* 。 ↩︎

  2. 具体指 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* 。 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值