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

scanf函数族用于从不同来源读取格式化的输入,如标准输入、文件或字符串。转换规范如%d、%f、%s等根据格式匹配输入,并将结果存储在提供的变量中。转换失败或输入不匹配会导致读取停止。返回值表示成功匹配和赋值的转换数量。
摘要由CSDN通过智能技术生成

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/.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值