man fscanf scanf sscanf vfscanf vscanf vsscanf

名称

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

概要

        #include

        int scanf(const char *format, ...);

        int fscanf(FILE *stream, const char *format, ...);

        int sscanf(const char *str, const char *format, ...);

        #include

        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):

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

            _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;

            or cc -std=c99

说明

        scanf函数族按照下文描述的格式扫描输入。格式可以包含多个转换规则。转换的

        结果,如果有的话,存储在格式之后的指针参数所指向的位置。每个指针参数的类

        型必须与转换之后的结果的类型匹配。

        如果格式中的转换规则的数量超过了指针参数的数量,那么结果是未定义的。如果

        指针参数的数量超过了转换规则的数量,那么超过的指针参数会被计算但是不会做

        其他操作。

        scanf从标准输入流stdin读取输入,fscanf从stream指向的流读取输入,sscanf从

        str指向的字符串读取输入。

        vfscanf类似于vfprintf,使用可变的指针参数列表从stream指向的流读取输入(参

        考stdarg)。vscanf从标准输入扫描可变参数列表,vsscanf从字符串扫描可变参数

        列表,它们分别类似于vprintf和vsprintf。

        格式串由一系列指令组成,这些指令描述了如何处理输入的字节序列。当一条指令

        执行失败时就不会继续读取输入,函数返回。下列情况会导致失败:输入失败,即

        输入字符不可用,或者匹配失败,意味着输入不合适(看下述说明)。

        下列的描述都是指令:

        ·       一系列空白字符(空格,制表符,换行符等,参考isspace)。该指令匹

                 配输入中任意数量的空白字符,包括零个。

        ·       普通字符(既不是空白字符也不是’%’)。此字符必须与输入的下一个字

                 符完全匹配。

        ·       转换规则,以一个’%’(百分号)开头。输入中的字符序列根据此规则进

                 行转换,并将结果放在相应的指针参数中。如果输入项与规则不匹配,

                 那么转换失败,这是一个匹配失败。

        每条转换规则要么以字符’%’开头,或者以字符序列"%n$"开头(区别见下文),后

        面跟着如下内容:

        ·      一个可选的赋值抑制字符’*’:scanf按照转换规则读取输入,但丢弃读到

                的内容。不需要相应的指针参数,并且此规则不包含在scanf成功时返回

                的计数中。

        ·      一个可选的字符’m’。用于字符串的转换(%s,%c,%[),调用者无需分

                配相应的缓冲区来保存输入,相反,scanf分配一个足够大小的缓冲区,

                并将该缓冲区的地址分配给相应的指针参数,该指针参数指向char *类型

                的变量(这个变量不需要在调用前初始化),调用者应该在不需要该缓冲

                区时释放它。

        ·      一个可选的十进制整数,用于指定最大字段宽度。当达到此最大值或找

                到不匹配的字符时(以先发生者为准)停止读取字符。大多数转换会丢

                弃开头的空白字符(下文会描述例外的情况),并且这些丢弃的字符不

                计入最大字段宽度。字符串输入转换存储一个结束符('\0')来标记输入

                的结束,最大字段宽度不包括该字符。

        ·      一个可选的类型修饰符。例如,l修饰符与整数转换如%d一起使用,表

                示对应的指针参数指向一个long int类型而不是int类型。

        ·      转换说明符,用来指定输入转换的类型。

        转换规则有两种形式,要么以'%'开始,要么以"%n$"开始。两种形式不应混合在同

        一个格式串中,除了包含"%n$"规则的格式串可以包含%%和%*之外。如果格式包

        含’%’规则,那么它们与指针参数按序一一对应。在"%n$"形式(在 POSIX.1-2001 中

        指定,但在 C99 中未指定)中,n是一个十进制整数,指定转换后的输入应放置

        在第n个指针参数所指的位置。

    转换

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

        h      指示转换将是d、i、o、u、x、X或n之一,并且指针指向short int或unsigned

               short int(而不是 int)。

        hh     跟h一样,但是指针指向signed char或者unsigned char。

        j      跟h一样,但是指针指向intmax_t或者uintmax_t。该修饰符由C99引进。

        l      指示转换将是d、i、o、u、x、X或n之一,并且指针指向long int或unsigned

               long int(而不是 int),或者转换将是e、f或g,并且指针指向double(而

               不是float)。两个l字符相当于L。如果与%c或%s一起使用,则相应的参

               数被视为分别指向宽字符或宽字符串的指针。

        L      指示转换将是e、f或g之一,并且指针指向long double,或者转换将是d、

               i、o、u或x,并且指针指向long long。

        q      等于L。该说明符在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      匹配一个无符号8进制整数,指针必须指向unsigned int类型。

        u      匹配一个无符号10进制整数,指针必须指向unsigned int类型。

        x      匹配一个无符号16进制整数,指针必须指向unsigned int类型。

        X      相当于x。

        f      匹配一个有符号浮点数,指针必须指向float类型。

        e      相当于f。

        g      相当于f。

        E      相当于f。

        a      (在C99)相当于f。

        s      匹配一串非空白字符序列,指针必须指向字符数组的初始元素,数组长度

               足以容纳输入序列和结束符('\0'),其中结束符是自动添加的。输入字符串

               在空白处或最大字段宽度处停止,以先发生者为准。

        c      匹配一串字符序列,其长度由最大字段宽度(默认为 1)指定,指针必须

               指向char类型,并且必须有足够的空间容纳所有的字符(不会添加结束符)。

               不会跳过前面的空格,如果想先跳过空格,那么需要在格式串中显式地加

               一个空格。

        [      匹配接收字符中的非空字符串,指针必须指向char类型,并且必须有足够

               的空间容纳串中的所有字符,包括结束符,不会跳过前面的空格,串由属

               于(或者不属于)特定字符集的字符组成,字符集由左括号’[‘和右括号’]’

               之间的字符组成,如果’[‘后的第一个字符为’^’则表示字符集由不包含’[‘和’]’

               之间的字符组成。为了在字符中包含’]‘,必须将该字符放在’[‘或者’^’后面

               的第一个字符位置处,放在其他任何位置都表示为字符集定义结束。连字

               符’-’也比较特殊,当把它放在两个字符的中间时,表示所有它们中间的字

               符也添加进字符集中。为了在字符中包含’-‘,必须将它作为最后一个字符

               放在’]’的前面。例如,[^]0-9-]表示为除了右括号’]‘、零到九和连字符之外

               的所有内容。当出现字符集以外的字符或者超过最大字段宽度时匹配结束。

        p      匹配一个指针值(就好像在printf中使用%p一样),指针必须指向void *

               类型。

        n      没有什么是预期的。到目前为止从输入消耗的字符数通过下一个指针存储,

               该指针必须是指向int的指针。这不是转换并且不会增加函数返回的计数

               值。可以使用字符’*’来抑制赋值,但对返回值的影响是不确定的,因此不

               应使用%*n转换。

返回值

        成功时,这些函数返回成功匹配和赋值的项数,在匹配失败的情况下,这可能比预

        期的项数要少,甚至为零。

        如果在第一次成功转换之前或匹配失败之前到达输入末尾,则返回EOF。如果出现

        读错误,也会返回EOF,在这种情况下会设置流的错误标志,errno对应此时的错

        误。

错误

        EAGAIN  与流关联的文件描述符被标记为非阻塞,而读操作会引起阻塞。

        EBADF   与流关联的文件描述符非法,或者没有以读方式打开文件。

        EILSEQ   输入的字节序列没有组成有效字符。

        EINTR    读操作被信号中断。

        EINVAL   没有足够的参数,或者格式串format为NULL。

        ENOMEM 内存不足。

        ERANGE  整数转换的结果超过相应整数类型可以存储的大小。

线程安全特征

接口

特征

scanf(), fscanf(), sscanf(), vscanf(),vsscanf(), vfscanf()

线程安全

locale级别多线程安全

标准

        函数fscanf(), scanf(), sscanf()遵循C89、C99和POSIX.1-2001,这些标准没有指定

        ERANGE错误码。

        修饰符q在4.4BSD用于long long类型,而ll或者L在GNU中用于整数转换。

        这些函数的Linux版本基于GNU libio库,可以查看GNU libc(glibc-1.08)的信息文

        档以获得更简洁的描述。

注意

    'a' 赋值分配修饰符

        最初,GNU C库支持通过'a'字符动态分配字符串输入(作为非标准扩展)。(这

        个特性至少可以追溯到 glibc 2.0。)因此,可以编写以下内容让scanf()为输入字

        符串分配一个缓冲区,并在*buf中返回指向该缓冲区的指针。

            char *buf;

            scanf("%as", &buf);

        这样使用字符’a’是有问题的,因为’a’也被ISO C标准指定为f(浮点输入)的同义词。

        POSIX.1-2008改为用m修饰符赋值。(如上文所述)。

        请注意,如果使用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说明符的附加行为。

        这些附加的功能可能被认为是一个错误,因为它改变了C89中定义的说明符的行

        为。

        ANSI C定义的类型修饰符和转换说明符的某些组合没有意义(例如%Ld)。虽然它

        们在Linux上可能有明确定义的行为,但在其他架构上不一定如此。因此,通常最

        好使用ANSI C根本没有定义的修饰符,即使用q或ll而不是L与d、i、o、u、x、

        X转换结合使用。

        q的用法与4.4BSD上的不同,因为它和L等效地用于浮点转换。

示例

        要使用动态分配转换说明符,请将m指定为长度修饰符(因此为%ms或%m[range])。

        调用者释放返回的字符串,如下例所示:

           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。

推荐阅读

        getc,printf,setlocale,strtod,strtol,strtoul

版本记录

        这个页面是Linux man-pages项目4.04版本的一部分。关于该项目的信息和bug报

        道可以在该网站找到:http://www.kernel.org/doc/man-pages/。

                                2015-04-19

你可能感兴趣的:(GNU,C,Library,Reference,Manual,linux)