SCANF(3)Linux程序员手册
NAME
scanf, fscanf, sscanf, vscanf, vsscanf, vfscanf - //输入格式转换函数
SYNOPSIS
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
#include <stdarg.h>
int vscanf(const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
vscanf(), vsscanf(), vfscanf():
_XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;
or cc -std=c99
描述
scanf()函数族根据下面描述的格式扫描输入。这种格式可以包含转换规范;这种转换的结果(如果有的话)存储在遵循format的指针参数所指向的位置中。每个指针参数的类型必须适合于相应转换规范返回的值。
如果格式转换规范的数量超过指针参数的数量,则结果是未定义的。如果指针参数的数量超过转换规范的数量,则计算多余的指针参数,但忽略其他参数。
scanf()函数从标准输入流stdin中读取输入,fscanf()从流指针流中读取输入,sscanf()从str指向的字符串中读取输入。
vfscanf()函数类似于vfprintf(3),使用指针的变量参数列表从流指针流读取输入(参见stdarg(3)。vscanf()函数从标准输入扫描变量参数列表,vscanf()函数从字符串扫描变量参数列表;它们分别类似于vprintf(3)和vsprintf(3)函数。
格式字符串由一系列描述如何处理输入字符序列的指令组成。如果指令处理失败,则不再读取进一步的输入,并返回。scanf()“失败”可以是以下两种情况中的一种:输入失败,意味着输入字符不可用,或者匹配失败,意味着输入不合适(见下文)。
指令是下列指令之一:
空白字符序列(空格、制表符、换行符等);看到isspace(3)。该指令匹配输入中的任意数量的空白,包括空白。
普通字符(即空格或'%'之外的字符)。此字符必须与输入的下一个字符完全匹配。
转换规范,以'%'字符开头。输入中的字符序列根据此规范进行转换,并将结果放在相应的指针参数中。如果下一个输入项不匹配转换规范,则转换失败——这是匹配失败。
格式上的每个转换规范都以字符“%”或字符序列“%n$”开头(参见下面的区别),然后是:
可选的'*'赋值抑制字符:scanf()按照转换规范的指示读取输入,但丢弃输入。不需要相应的指针参数,并且该规范不包括在scanf()返回的成功赋值计数中。
一个可选的“m”字符。它用于字符串转换(%s, %c, %[),并且使调用者不再需要分配相应的缓冲区来保存输入:相反,scanf()分配一个足够大的缓冲区,并将该缓冲区的地址分配给相应的指针参数,该参数应该是指向char *变量的指针(在调用之前不需要初始化该变量)。当不再需要该缓冲区时,调用方应随后使用free(3)释放掉该缓冲区。
可选的十进制整数,用于指定字段的最大宽度。当达到最大值或发现不匹配的字符时停止读取字符,无论哪种情况先发生。大多数转换会丢弃初始空白字符(例外情况将在下面说明),这些丢弃的字符不会计入最大字段宽度。字符串输入转换存储一个终止空字节('\0')来标记输入的结束;最大字段宽度不包括此终止符。
可选类型修饰符字符。例如,l类型修饰符用于整型转换(如%d),以指定对应的指针参数指向长整型,而不是指向整型的指针。
指定要执行的输入转换类型的转换说明符。
格式上的转换规范有两种形式,以“%”开头或以“%n$”开头。这两种形式不应该混合在同一个格式字符串中,除了包含“%n$”规范的字符串可以包括%%和%*。如果format包含'%'规范,则这些规范与连续的指针参数顺序对应。在“%n$”形式(在POSIX.1-2001中指定,但不是在C99中指定)中,n是一个十进制整数,它指定转换后的输入应放置在遵循format的第n个指针参数所引用的位置。
转换
以下类型修饰符字符可以出现在转换规范中:
h 指示转换将是d, i, o, u, x, X, n中的一个,并且对应的指针是指向短整型或无符号短整型(而不是int)的指针。
hh 类似h,但对应的指针是指向有符号char或无符号char的指针。
j 类似h,但对应的指针是指向intmax_t或uintmax_t的指针。这个修饰符是在C99引入的。
l 指示转换将是d, i, o, u, x, x或n,对应的指针是指向长整型或无符号长整型(而不是int)的指针,或者转换将是e, f或g,对应的指针是指向double(而不是float)的指针。指定两个l字符相当于l。如果与%c或%s一起使用,相应的参数分别被视为指向宽字符或宽字符字符串的指针。
L 指示转换将是e、f或g,对应的指针是指向长double的指针,或者转换将是d、i、o、u或x,对应的指针是指向长long的指针。
q 这个说明符在ANSI C中不存在。
t 类似h,但是对应的指针是指向ptrdiff_t的指针。这个修饰符是在C99引入的。
z 类似h,但对应的指针是指向size_t的指针。这个修饰符是在C99引入的。
以下转换说明符是可用的:
% 匹配文字'%'。也就是说,格式字符串中的%%匹配单个输入'%'字符。不会进行转换(但会丢弃初始空白字符),也不会进行赋值。
d 匹配可选有符号十进制整数,对应的指针必须是指向int的指针。
D 相当于ld;它的存在只是为了向后兼容。(注:因此仅在libc4中。在libc5和glibc中,%D被默默地忽略,导致旧程序神秘地失败。)
i 匹配一个可选有符号整数,对应的指针必须是指向int的指针。以0x或0x开头的整数以16为底读取,以0开头的整数以8为底读取,否则以10为底读取。只使用与基相对应的字符。
o 匹配无符号八进制整数;下一个指针必须是指向unsigned int的指针。
u 匹配无符号十进制整数;下一个指针必须是指向unsigned int的指针。
x 匹配无符号十六进制整数;下一个指针必须是指向unsigned int的指针。
X 等于x。
f 匹配一个带符号的浮点数;下一个指针必须是指向float的指针。
e 等于f。
g 等于f。
E 等于f。
a (C99) 等于f。.
s 匹配非空白字符序列;对应的指针必须是指向字符数组的初始元素的指针,该元素足够长,可以保存输入序列和自动添加的终止空字节('\0')。输入字符串停止于空白或最大字段宽度处,以先出现者为准。
c 匹配长度由最大字段宽度指定的字符序列(默认为1),对应的必须是指向char的指针,并且必须有足够的空间容纳所有字符(不添加终止空字节)。通常的前导空白跳过被抑制。若要先跳过空白,请在格式中使用显式空格。
[ 从指定的接受字符集中匹配一个非空字符序列,对应的指针必须是一个指向char的指针,并且必须有足够的空间容纳字符串中的所有字符,再加上一个终止空字节。
通常的前导空白跳过被抑制。字符串将由特定集合中的(或不在)字符组成。集合由左方括号[character]和右方括号]字符之间的字符定义。
如果左括号后的第一个字符是回旋字符(^),则集合将排除这些字符。
若要在集合中包含右括号,请将其置于左括号或旋括号之后的第一个字符。任何其他位置将结束集合。
连字符-也是特殊的;当放置在其他两个字符之间时,它将所有插入的字符添加到集合中。若要包含连字符,请将其设置为最后一个右括号前的最后一个字符。例如,[^]0-9-]表示集合“除右括号、0到9和连字符外的所有内容”。
当字段宽度用完时,字符串以不在集合(或带回旋的in)中的字符的外观结束。
p 匹配一个指针值(在printf(3)中由%p打印的值),对应的指针必须是指向void指针的指针。
n 没有期待;相反,从输入到目前为止所消耗的字符数通过对应的指针存储,该指针必须是指向int的指针。这不是转换,也不会增加函数返回的计数。可以使用*赋值抑制字符来抑制赋值,但对返回值的影响是未定义的。因此不应该使用%*n转换。
RETURN VALUE
如果成功,这些函数返回成功匹配和分配的输入项的数量;在早期匹配失败的情况下,这个值可能小于所提供的值,甚至为零。
如果在第一次成功转换或发生匹配失败之前到达输入结束,则返回值EOF。如果发生读错误,也会返回EOF,在这种情况下,将设置流的错误指示器(参见ferror(3)),并设置errno以指示错误。
ERRORS
EAGAIN 底层流的文件描述符被标记为非阻塞,读取操作将阻塞。
EBADF 底层流的文件描述符无效,或未打开以供读取。
EILSEQ 输入字节序列不构成有效字符。
EINTR 读取操作被一个信号中断;看到信号(7)。
EINVAL 没有足够的论据;或format为NULL。
ENOMEM 内存不足。
ERANGE 整数转换的结果将超过可以存储在相应整数类型中的大小。
ATTRIBUTES
有关本节中使用的术语的解释,请参阅attributes(7).。
Interface | Attribute | Value |
scanf(), fscanf(), sscanf(), vscanf(), vsscanf(), vfscanf() | Thread safety | MT-Safe locale |
符合
函数fscanf(), scanf()和sscanf()符合C89和C99和POSIX.1-2001。这些标准没有指定ERANGE错误。
q指示符是表示long long的4.4BSD表示法,而ll或L在整数转换中的使用是GNU表示法。
这些函数的Linux版本基于GNU libio库。请查看GNU libc (glibc-1.08)的信息文档,以获得更简洁的描述。
NOTES
'a'分配修饰符
最初,GNU C库支持通过a字符对字符串输入进行动态分配(作为非标准扩展)。(该特性至少早在glibc 2.0时就存在了。)因此,可以这样写,让scanf()为输入字符串分配一个缓冲区,并在*buf中返回指向该缓冲区的指针:
char *buf;
scanf("%as", &buf);
为此目的使用字母a是有问题的,因为ISO C标准也指定a作为f(浮点输入)的同义词。相反,POSIX.1-2008为分配分配指定了m修饰符(如上面的DESCRIPTION中所述)。
注意,如果用gcc -std=c99或gcc -D_ISOC99_SOURCE编译程序,则a修饰符不可用(除非还指定了_GNU_SOURCE),在这种情况下,a将被解释为浮点数的说明符(见上文)。
从2.7版开始,glibc添加了对m修饰符的支持,新的程序应该使用该修饰符而不是a。
除了被POSIX标准化之外,m修饰符与a相比还有以下优势:
它也可以应用于%c转换说明符(例如,%3mc)。
它避免了关于%a浮点转换说明符的歧义(并且不受gcc -std=c99等的影响)。
BUGS
所有函数都完全符合C89,但提供了额外的说明符q和a,以及L和L说明符的额外行为。后者可能被认为是一个bug,因为它改变了C89中定义的说明符的行为。
ANSI C定义的一些类型修饰符和转换说明符的组合没有意义(例如,%Ld)。虽然它们在Linux上可能具有定义良好的行为,但在其他体系结构上不一定如此。因此,通常最好使用ANSI C根本没有定义的修饰符,也就是说,在d, i, o, u, x和x转换或ll的组合中使用q而不是L。
q的用法与4.4BSD中不一样,因为它可以等效于L的浮点数转换中使用。
EXAMPLE
若要使用动态分配转换说明符,请将m指定为长度修饰符(即%ms或%m[range])。调用方必须释放(3)返回的字符串,如下例所示:
char *p;
int n;
errno = 0;
n = scanf("%m[a-z]", &p);
if (n == 1) {
printf("read: %s\n", p);
free(p);
} else if (errno != 0) {
perror("scanf");
} else {
fprintf(stderr, "No matching characters\n");
}
如上例所示,只有在scanf()调用成功读取字符串时,才有必要调用free(3)。
另请参阅
getc(3), printf(3), setlocale(3), strtod(3), strtol(3), strtoul(3)
版本记录
本页是Linux手册页项目4.04版的一部分。项目的描述,关于报告错误的信息,以及本页的最新版本,可以在这里找到http://www.kernel.org/doc/man-pages/.