错误说明

EAGAIN
流下的文件描述符被标记为非阻塞,并且读取操作将阻塞。
EBADF
底层流的文件描述符无效,或未打开以供读取。
EILSEQ
输入字节序列不构成有效字符。
EINTR
读取操作被信号中断;参见signal(7)。
EINVAL
论据不足;或格式为NULL。
ENOMEM
内存不足。
ERANGE
整数转换的结果将超出可以存储在相应整数类型中的大小。

另外参见

getc(3),printf(3),setlocale(3),strtod(3),strtol(3),strtoul(3)

名称

scanf,fscanf,sscanf,vscanf,vsscanf,vfscanf-输入格式转换

遵循规范

函数fscanf(),scanf()和sscanf()符合C89和C99和POSIX.1-2001。这些标准未指定ERANGE错误。

q指示符是long long long的4.4BSD表示法,而ll或L在整数转换中的使用是GNU表示法。

这些功能的Linux版本基于GNU libio库。查看GNU libc的信息文档(glibc-1.08),以获得更简洁的描述。

SCANF - Linux手册页

Linux程序员手册 第3部分
更新日期: 2020-08-13

示例

要使用动态分配转换说明符,请将m指定为长度修饰符(因此%ms或%m [range])。调用者必须free(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)。

备注

The 'a' assignment-allocation modifier

最初,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(除非也指定_GNU_SOURCE)编译程序,则a修饰符不可用,在这种情况下,a被解释为浮点数的指定符(请参见上文) 。

从2.7版开始,对g修饰符的支持已添加到glibc中,新程序应使用该修饰符而不是a。

除了可以通过POSIX进行标准化之外,与使用a相比,m修饰符还具有以下优点:

*
它也可以应用于%c转换说明符(例如%3mc)。
*
它避免了%a浮点转换说明符的歧义(并且不受gcc -std = c99等的影响)。

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
scanf(),fscanf(),
sscanf(),vscanf(),
vsscanf(),vfscanf()
Thread safetyMT-Safe locale

说明

scanf()系列函数根据如下所述的格式扫描输入。此格式可能包含转换规范;这些转换的结果(如果有)存储在格式后面的指针参数所指向的位置。每个指针参数的类型必须适合于相应转换规范返回的值。

如果格式转换规范的数量超过了指针参数的数量,则结果是不确定的。如果指针参数的数量超过转换规范的数量,则将评估多余的指针参数,否则将被忽略。

scanf()函数从标准输入流stdin中读取输入,fscanf()从流指针流中读取输入,sscanf()从str指向的字符串中读取输入。

vfscanf()函数类似于vfprintf(3),并使用指针的可变参数列表从流指针流中读取输入(请参见stdarg(3)。vscanf()函数从标准输入和指针扫描变量列表)。 vsscanf()函数从字符串扫描它;它们分别类似于vprintf(3)和vsprintf(3)函数。

格式字符串由一系列指令组成,这些指令描述了如何处理输入字符的序列。如果指令处理失败,则不会再读取任何输入,并且scanf()返回。 "失败"可以是以下之一:输入失败(表示输入字符不可用)或匹配失败(表示输入不合适)(请参阅下文)。

指令是以下之一:

*
一系列空格字符(空格,制表符,换行符等;请参见isspace(3))。此伪指令匹配输入中任何数量的空格,包括无空格。
*
普通字符(即空格或aq%aq以外的其他字符)。此字符必须与输入的下一个字符完全匹配。
*
转换规范,以aq%aq(百分比)字符开头。根据此规范转换来自输入的字符序列,并将结果放置在相应的指针参数中。如果输入的下一项不符合转换规范,则转换失败-这是匹配失败。

每个格式的转换规范都以字符aq%aq或字符序列"%n $"(区别见下文)开头,后跟:

*
可选的aq * aq分配抑制字符:scanf()按照转换规范的指示读取输入,但丢弃输入。不需要相应的指针参数,并且scanf()返回的成功分配计数中不包含此规范。
*
对于十进制转换,使用可选的引号字符(aq)。这指定输入数字可能包括由当前语言环境的LC_NUMERIC类别定义的数千个分隔符。 (请参阅setlocale(3)。)引号字符可以在aq * aq分配抑制字符之前或之后。
*
可选的aqmaq字符。它与字符串转换(%s,%c,%[)一起使用,使调用者无需分配相应的缓冲区来保存输入:相反,scanf()分配了足够大小的缓冲区,并分配了地址该缓冲区的值对应的指针参数,该参数应该是指向char *变量的指针(在调用之前不需要初始化此变量)。随后,当不再需要此缓冲区时,调用者应释放(3)此缓冲区。
*
一个可选的十进制整数,用于指定最大字段宽度。当达到此最大值或发现不匹配的字符时(以先发生者为准),字符读取将停止。大多数转换会丢弃初始的空白字符(下面有例外说明),并且这些丢弃的字符不会计入最大字段宽度。字符串输入转换存储一个终止的空字节(aq \ 0aq)来标记输入的结尾;最大字段宽度不包括此终结器。
*
可选的类型修饰符。例如,l类型修饰符与整数转换(例如%d)一起使用,以指定相应的指针参数指向long int而不是指向int的指针。
*
一个转换说明符,用于指定要执行的输入转换的类型。

格式的转换规范有两种形式,以aq%aq开头或以"%n $"开头。两种格式不应以相同的格式字符串混合使用,除非包含"%n $"规范的字符串可以包含%%和%*。如果format包含aq%aq规范,则它们与连续的指针参数按顺序对应。在"%n $"形式(在POSIX.1-2001中指定,但不是C99)中,n是一个十进制整数,指定转换后的输入应放置在第n个指针参数引用的位置以下格式。

Conversions

以下类型修饰符可以出现在转换规范中:

h
指示转换将是dioux,X或n中的一个,并且下一个指针是short int或unsigned short int(而不是int)的指针。
hh
至于h,但下一个指针是指向有符号字符或无符号字符的指针。
j
至于h,但下一个指针是指向intmax_t或uintmax_t的指针。此修饰符是在C99中引入的。
l
表示转换将是dioux,X或n中的一个,并且下一个指针是指向long int或unsigned long int(而不是int)的指针,或者将转换为e,f或g中的一个,下一个指针是一个指向double(而不是float)的指针。指定两个l个字符等效于L。如果与%c或%s一起使用,则相应的参数分别被视为指向宽字符或宽字符字符串的指针。
L
表示转换将是e,f或g,下一个指针是一个指向long double的指针,或者转换将是dio,u或x,下一个指针是指向long long的指针。
q
等效于L。此说明符在ANSI C中不存在。
t
至于h,但下一个指针是指向ptrdiff_t的指针。此修饰符是在C99中引入的。
z
至于h,但下一个指针是指向size_t的指针。此修饰符是在C99中引入的。

可以使用以下转换说明符:

%
匹配文字aq%aq。也就是说,格式字符串中的%%与单个输入aq%aq字符匹配。不进行任何转换(但初始空格字符将被丢弃),并且不会发生分配。
d
匹配一个可选的带符号十进制整数;下一个指针必须是指向int的指针。
i
匹配一个可选的带符号整数;下一个指针必须是指向int的指针。如果整数以0x或0X开头,则以16为基数;如果以0开头,则以8为基数;否则以10为基数。仅使用对应于基数的字符。
o
匹配一个无符号的八进制整数;下一个指针必须是指向unsigned int的指针。
u
匹配一个无符号的十进制整数;下一个指针必须是指向unsigned int的指针。
x
匹配一个无符号的十六进制整数(可以选择以0x或0X前缀开头,该前缀将被丢弃);下一个指针必须是指向unsigned int的指针。
X
等效于x。
f
匹配可选签名的浮点数;下一个指针必须是要浮动的指针。
e
等效于f。
g
等效于f。
E
等效于f。
a
(C99)等同于f。
s
匹配一系列非空格字符;下一个指针必须是一个指向字符数组的初始元素的指针,该指针的长度足以容纳输入序列和终止的空字节(aq \ 0aq),后者会自动添加。输入字符串停在空白处或最大字段宽度处,以先到者为准。
c
匹配长度由最大字段宽度指定的字符序列(默认为1);下一个指针必须是指向char的指针,并且所有字符必须有足够的空间(不添加任何终止空字节)。通常的前导空白跳过被抑制。要先跳过空格,请使用格式中的显式空格。
[
匹配指定的一组可接受字符中的非空字符序列;下一个指针必须是指向char的指针,并且字符串中的所有字符必须有足够的空间,再加上一个终止的空字节。通常的前导空白跳过被抑制。字符串应由(或不在)特定集中的字符组成;该集合由左方括号[字符和右方括号]字符之间的字符定义。如果开括号后的第一个字符是抑扬符(ha),则该字符集将排除这些字符。要在集合中包含右括号,请将其放在开括号或抑扬符之后的第一个字符;任何其他位置将结束该集合。连字符-也很特殊;当放置在其他两个字符之间时,它将所有中间字符添加到集合中。要包含连字符,请使其成为最后一个方括号之前的最后一个字符。例如,[ha] 0-9-]表示集合"除右括号,零至九和连字符以外的所有内容"。字符串的结尾是未设置(或带有抑扬符号,输入)字符或字段宽度用尽的情况。
p
匹配一个指针值(由printf(3)中的%p打印);下一个指针必须是指向void的指针。
n
没什么可期待的;取而代之的是,到下一个输入为止消耗的字符数通过下一个指针存储,该指针必须是指向int的指针。这不是转换,不会增加该函数返回的计数。可以使用*分配抑制字符来抑制分配,但是对返回值的影响是不确定的。因此,不应使用%* n转换。

语法

#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);

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

vscanf(),vsscanf(),vfscanf():

_ISOC99_SOURCE || _POSIX_C_SOURCE>= 200112L

BUGS

所有功能都完全符合C89,但提供了额外的说明符q和a,以及L和l说明符的额外行为。后者可能会被视为错误,因为它会更改C89中定义的说明符的行为。

ANSI C定义的类型修饰符和转换说明符的某些组合没有意义(例如,%Ld)。尽管它们在Linux上可能具有明确定义的行为,但在其他体系结构上不必如此。因此,通常最好使用根本不由ANSI C定义的修饰符,即与diou,x和X转换或ll结合使用q而不是L。

q的用法与4.4BSD上的用法不同,因为它可以等效于L在浮点转换中使用。

返回值

成功后,这些函数将返回成功匹配和分配的输入项的数量;如果较早匹配失败,则该数目可能小于所提供的数目,甚至为零。

如果在第一次成功转换或匹配失败发生之前达到输入结束,则返回EOF值。如果发生读取错误,也会返回EOF,在这种情况下,将设置流的错误指示符(请参阅ferror(3)),并设置errno来指示错误。

日期:2019-08-20 18:01:22 来源:oir作者:oir