fscanf
在标题中定义 <stdio.h> | |
---|---|
int scanf( const char *format, ... ); | (until C99) |
int scanf( const char *restrict format, ... ); | (since C99) |
int fscanf( FILE *stream, const char *format, ... ); | (until C99) |
int fscanf( FILE *restrict stream, const char *restrict format, ... ); | (since C99) |
int sscanf( const char *buffer, const char *format, ... ); | (until C99) |
int sscanf( const char *restrict buffer, const char *restrict format, ... ); | (since C99) |
int scanf_s(const char *restrict format, ...); | (since C11) |
int fscanf_s(FILE *restrict stream, const char *restrict format, ...); | (since C11) |
int sscanf_s(const char *restrict buffer, const char *restrict format, ...); | (since C11) |
从各种来源读取数据,根据其解释并将format
结果存储到给定位置。
1)从中读取数据 stdin
2)从文件流中读取数据 stream
3)从空终止的字符串中读取数据buffer
。到达字符串的末尾等同于达到文件结束条件fscanf
4-6)与(1-3)相同,不同之处在于%c
,%s
和%[
转换说明符每个都需要两个参数(通常的指针和rsize_t
表示接收数组大小的类型值,当使用%c读取时可能为1成一个字符),除了在运行时检测到以下错误并调用当前安装的约束处理函数:
- 指针类型的任何参数都是空指针
format
,stream
或者buffer
是空指针- %c,%s或%[,加上终止空字符,将会超过为每个转换说明符提供的第二个(rsize_t)参数所写的字符数
- 可选地,还有任何其他可检测到的错误,例如未知的转换说明符
由于所有的边界检查功能,scanf_s
,fscanf_s
,和sscanf_s
仅保证可供如果__STDC_LIB_EXT1__
由实现所定义,并且如果用户定义__STDC_WANT_LIB_EXT1__
的整数常数1
,包括之前<stdio.h>
。
参数
转换说明符 | 说明 | 参数类型 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
长度修饰符 | hh(C99) | h | (没有) | l | ll(C99) | j(C99) | z(C99) | t(C99) | L | |
% | 匹配文字 % | N / A | N / A | N / A | N / A | N / A | N / A | N / A | N / A | N / A |
c | 匹配一个字符或一系列字符如果使用宽度说明符,则完全匹配宽度 字符(参数必须是指向具有足够空间的数组的指针)。与%s和%[不同,不会将空字符追加到数组。 | N / A | N / A | char * | wchar_t * | N / A | N / A | N / A | N / A | N / A |
s | 匹配一系列非空白字符(一个字符串)如果使用宽度说明符,则匹配宽度或直到第一个空白字符(以先出现者为准)。除了匹配的字符外,总是保存一个空字符(所以参数数组必须至少有宽度+ 1个字符的空间) | |||||||||
[set] | 匹配一组字符中的非空字符序列。如果该集合的第一个字符是^,则不匹配该集合中的所有字符。如果集合以该字符开头]或者^]该]字符也包含在该集合中。它是实现定义的-,即扫描集中非初始位置的字符是否可以指示范围,如in [0-9]。如果使用宽度说明符,则只匹配宽度。除了匹配的字符外,总是保存一个空字符(所以参数数组必须至少有宽度+ 1个字符的空间) | |||||||||
d | 匹配一个十进制整数。数的格式是如预期由相同的()strtol将具有值10的base参数 | signed char *或unsigned char * | 签署 短*或无符号 短* | 有符号 int *或unsigned int * | 签署 长*或无符号 长* | 签订 长期 长*或无符号 长的 长* | intmax_t *或uintmax_t * | size_t * | ptrdiff_t * | N / A |
i | 匹配一个整数。数的格式是相同的预期通过与strtol()具有值0的参数(基部由解析的第一个字符所确定的) base | |||||||||
u | 匹配一个无符号的十进制整数。数的格式是如预期由相同的()strtoul将具有值10的base参数。 | |||||||||
o | 匹配一个无符号的八进制整数。数的格式是如预期由相同的()strtoul将具有值8为base参数 | |||||||||
x, X | 匹配一个无符号的十六进制整数。数的格式是如预期由相同的()strtoul将具有值16的base参数 | |||||||||
n | 返回到目前为止读取的字符数。没有输入被消耗。不增加分配计数。如果说明符具有定义的分配抑制运算符,则行为未定义 | |||||||||
a, A(C99) e, E f, F g, G | 匹配一个浮点数。数字的格式与strtof()的预期相同 | N / A | N / A | 浮动* | 双* | N / A | N / A | N / A | N / A | 长 双* |
p | 匹配定义指针的实现定义的字符序列。printf函数族应该使用%p格式说明符 产生相同的序列 | N / A | N / A | 无效** | N / A | N / A | N / A | N / A | N / A | N / A |
对于每个转换说明符以外的n
,最长的输入字符序列不超过任何指定的字段宽度,或者正是转换说明符所期望的或者是期望序列的前缀,是流中消耗的内容。在消耗序列之后的第一个字符(如果有的话)仍然未读。如果消耗的序列长度为零或消费的序列无法如上所述进行转换,则会发生匹配失败,除非文件结束,编码错误或读取错误阻止来自流的输入,在这种情况下,它是输入失败。
在尝试解析输入之前,除了[
,,之外的所有转换说明符c
并n
消耗并放弃所有前导空白字符(如同调用isspace一样确定)。这些消耗的字符不会计入指定的最大字段宽度。
转换说明符lc
,ls
并l[
执行多字节到宽字符的转换,就好像通过调用mbrtowc()并在转换第一个字符之前将mbstate_t对象初始化为零一样。
除了匹配的字符之外,转换说明符s
并[
始终存储空终止符。目标数组的大小必须至少比指定的字段宽度大1。使用%小号或%[,而不指定目的地的阵列大小,是为不安全作为得到
为正确的转换规格固定宽度整数类型(int8_t
等)都在头中定义<inttypes.h>还(虽然SCNdMAX,SCNuMAX等是同义词%jd
,%ju
等)。
每个转换说明符的操作之后都有一个序列点 ; 这允许将多个字段存储在相同的“汇”变量中。
当解析一个不带数字的指数结束的不完整浮点值时,例如用转换说明符%f解析“100er”时,会消耗序列“100e”(可能有效的浮点数的最长前缀) ,导致匹配错误(消耗的序列不能转换为浮点数),并保留“r”。现有的实现不遵循这个规则并回滚到只消耗“100”,留下“er”,例如glibc bug 1765
如果转换规范无效,则行为未定义。
... | - | 接收参数 |
---|
返回值
1-3)成功分配的接收参数数量(EOF
如果在分配第一个接收参数之前发生匹配故障,则可能为零),或者在分配第一个接收参数前发生输入故障。
4-6)与(1-3)相同,但是EOF
如果存在运行时约束冲突,也会返回。
注意
由于大多数转换说明符首先消耗所有连续的空白,所以代码如。
scanf("%d", &a);
scanf("%d", &b);
将读取在不同行上输入的两个整数(第二个%d将使用第一个剩下的换行符)或在同一行上,由空格或制表符分隔(第二个%d将使用空格或制表符)。不使用前导空格的转换说明符(如%c)可以通过在格式字符串中使用空格字符来完成:
scanf("%d", &a);
scanf(" %c", &c); // ignore the endline after %d, then read a char
例
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stddef.h>
#include <locale.h>
int main(void)
{
int i, j;
float x, y;
char str1[10], str2[4];
wchar_t warr[2];
setlocale(LC_ALL, "en_US.utf8");
char input[] = "25 54.32E-1 Thompson 56789 0123 56ß水";
/* parse as follows:
%d: an integer
%f: a floating-point value
%9s: a string of at most 9 non-whitespace characters
%2d: two-digit integer (digits 5 and 6)
%f: a floating-point value (digits 7, 8, 9)
%*d: an integer which isn't stored anywhere
' ': all consecutive whitespace
%3[0-9]: a string of at most 3 decimal digits (digits 5 and 6)
%2lc: two wide characters, using multibyte to wide conversion */
int ret = sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
&i, &x, str1, &j, &y, str2, warr);
printf("Converted %d fields:\ni = %d\nx = %f\nstr1 = %s\n"
"j = %d\ny = %f\nstr2 = %s\n"
"warr[0] = U+%x warr[1] = U+%x\n",
ret, i, x, str1, j, y, str2, warr[0], warr[1]);
#ifdef __STDC_LIB_EXT1__
int n = sscanf_s(input, "%d%f%s", &i, &x, str1, (rsize_t)sizeof str1);
// writes 25 to i, 5.432 to x, the 9 bytes "thompson\0" to str1, and 3 to n.
#endif
}
输出:
Converted 7 fields:
i = 25
x = 5.432000
str1 = Thompson
j = 56
y = 789.000000
str2 = 56
warr[0] = U+df warr[1] = U+6c34
参考
- C11标准(ISO / IEC 9899:2011):
- 7.21.6.2 fscanf函数(p:317-324)
- 7.21.6.4 scanf函数(p:325)
- 7.21.6.7 sscanf函数(p:326)
- K.3.5.3.2 fscanf_s函数(p:592-593)
- K.3.5.3.4 scanf_s函数(p:594)
- K.3.5.3.7 sscanf_s函数(p:596)
- C99标准(ISO / IEC 9899:1999):
- 7.19.6.2 fscanf函数(p:282-289)
- 7.19.6.4 scanf函数(p:290)
- 7.19.6.7 sscanf函数(p:291)
- C89 / C90标准(ISO / IEC 9899:1990):
- 4.9.6.2 fscanf函数
- 4.9.6.4 scanf函数
- 4.9.6.6 sscanf函数
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com