scanf函数用法小记

Posted 刘英皓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scanf函数用法小记相关的知识,希望对你有一定的参考价值。

By francis_hao    Aug 26,2017

 

scanf – 输入格式转换

 

概述

#include <stdio.h>
int scanf(const char *format, ...);

 

描述

该函数通过format扫描标准输入stdin, format包含转换描述说明,如果需要转换,那么转换后的结果存储在format之后的指针参数中,每个指针参数类型必须要正确对应转换说明。如果format中转换说明符的个数,超过了后面的指针参数,那么结果将是未定义的。反过来,如果指针参数的数量超过了转换符的数量,那么多余的指针参数将被忽略。

format字符串包含一串指令,这些指令描述了该如何处理输入的字符,如果一个指令处理失败,那么之后的输入将不再读取,而且函数返回。处理失败可以是以下几种:
1、输入失败,意味着输入的字符串不可用。
2、匹配失败,意味着输入不相称。

一个指令可以是下面几种:
1、一串空白符(空格,tab,新行等),此指令匹配任何数量的空白符,也可以匹配none。
2、普通的字符(既不是空白字符也不是\'%\')。这种字符必须准确的匹配输入的字符。
3、以\'%\'开头的转换说明,通过此说明将输入的字符串进行转换,结果会放在对应的指针参数中,如果输入的项与转换说明不匹配,那么转换就会失败,这就是上面提到的匹配失败。

format中的转换说明以\'%\'或"%n$"开始,后面(按顺序)跟着以下内容:
1、一个可选的\'*\'分配抑制符,scanf()像普通的转换符那样从输入读取,但是之后会丢弃该输入,不会将该输入存入指针参数,而且不会作为scanf()返回的成功分配项的数量。
2、一个可选的\'m\'字符。此项用于转换符%s,%c和%[,使调用者无需申请存放输入的缓冲,而是由scanf()去申请缓存,并将缓存的地址赋给指针参数,该参数应该是一个指向char *变量(该变量在调用前无需初始化,但是建议仍旧初始化一下)的指针。调用者需要在之后不再需要该缓冲的时候进行free(3)。
3、一个可选的十进制整数,用来指定字段最大宽度。此项表示当读取到了指定的最大宽度或读取到不匹配的字符后就会停止,。大部分的转换符会跳过前面的空白字符(例外情况在下面介绍),而且那些跳过的字符不计入最大字段宽度,字符串输入转换符包含一个终止字节\'\\0\'以表示输入的结束,字段最大宽度也不包括此项。
4、一个可选的,类型修饰符,例如,修饰符l用于转换符%d表示其对应的指针参数指向一个long int类型而不是一个int类型。
5、转换说明符,用以指定输入需要转换的类型。

format中的转换说明有两种形式,要么以\'%\'开始,要么以"%n$"开始。两种形式不能在同一个format中混用,但是有"%n$"的转换说明可以包含%%和%*。如果format包含\'%\'说明,那么参数会按顺序,一个个的进行赋值。但是在"%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的指针

t

类似h,但是其后的参数是一个指向ptrdiff_t的指针

z

类似h,但是其后的参数是一个指向size_t的指针

l

1、表明转换符将是d,i,o,u,x,X或n的其中一个,而且其后的参数是一个指向long int或unsigned long int(而不是int)的指针

2、表明转换符将是e, f,或g的其中一个,而且其后的参数是一个指向double(而不是float)的指针

3、指定两个l,和L一致。

L

1、表明转换符将是e, f, 或 g的其中一个,而且其后的参数是一个指向long double的指针

2、表明转换符是d, i, o, u,或x的其中一个,而且其后的参数是一个指向long double的指针

 

转换符

转换符

说明

d

匹配一个有符号的十进制整数,后面的指针参数必须是一个指向int的指针

i

匹配一个有符号的十进制整数,后面的指针参数必须是一个指向int的指针

输入如果是以0x或0X开头,就以16进制读入

输入如果是以0开头,就以8进制读入

其他形式就以10进制读入

o

匹配一个无符号八进制整数,后面的指针参数必须是指向unsigned int的指针

u

匹配一个无符号十进制整数,后面的指针参数必须是指向unsigned int的指针

x

匹配一个无符号十六进制整数,后面的指针参数必须是指向unsigned int的指针

f,e,E,g,a

匹配一个有符号的浮点数,后面的指针参数必须是指向float的指针

s

匹配一个没有空白字符的字符串序列,其后的指针参数必须是指向字符数组的指针,而且大小要足够大以容纳输入的序列和终止符null字节。当遇到输入的空白字符或者最大字段宽度时即停止。

c

匹配一个字符序列,其长度由最大字段宽度指定(默认是1),其后的指针参数必须是指向char的指针,而且要有足够长的空间存储所有的字符(结尾不会自动添加null字节)。如果开头有空白字符不会跳过,如果想要跳过开头的空白字符,需要在format中使用一个确实的空格。

[

从指定的接受字符集合中匹配一个非空字符序列,后面的指针参数必须是指向char的参数,而且,必须有足够的空间已存放所有匹配的字符和一个终止的null字节。此项中,如果开头有空白字符不会跳过。

[]中的字符组成了一个集合,表示只匹配[]里的字符,如果是开头的字符是^,则表示除了[]内的字符其余的字符集合,如果想包含一个],需要将]放在[或[^后的第一个位置,在其他位置则表示集合终止。-是有特殊含义的,表示一个字符范围,如果想包含-则需要放在[]的最后一个位置。比如

[^]0-9-]:表示除了],0,1,2,3,4,5,6,7,8,9,-这12个字符以外的所有字符。

p

匹配一个指针数值,后面的指针参数必须是指向void的指针

n

不需要输入,而是将截止到该项为止,之前输入的字符数存储在其后对应的指针中,指针参数必须是指向int类型的指针。此项不属于转换符,尽管它可以被*抑制(抑制之后就什么作用都没有了)

返回值

返回函数成功匹配和分配的项数,有可能少于提供的参数,如果最早匹配时发生错误甚至会返回0。

如果在成功转换完成或者匹配失败之前,遇到了输入的结尾,那么就会返回EOF。如果读取失败同样也会返回EOF,并且errno会被置为相应的值。

 

 

示例

1、

结果为

本示例主要说明了分配抑制符*的使用,可以用来过滤掉不需要的输入,因为带*的转换说明不会给其后的参数赋值,因此也不需要给定存储的参数。

而n主要是记录到此前位置共有多少个字符被输入(包含空格),并将该值分配给其后的参数

2、man手册上的一个例子,添加了一些注释

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
    char *p;
    int n;

    errno = 0;
    n = scanf("%m[a-z]", &p);
    if (n == 1) {/*number of input items successfully matched and assigned*/
        printf("read: %s\\n", p);
        free(p);
    } else if (errno != 0) {/*EOF must be returned*/
        perror("scanf");
    } else {/*matching failure n may be zero*/
        fprintf(stderr, "No matching characters.n is %d\\n",n);
    }

    return 0;
}

结果为

 

 


本文由 刘英皓 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:http://www.cnblogs.com/yinghao1991/p/7436582.html

 

 

参考

【1】man scanf

以上是关于scanf函数用法小记的主要内容,如果未能解决你的问题,请参考以下文章

scanf函数与printf函数用法

scanf()函数中*的用法

C++ scanf_s()函数的用法以及注意事项

关于scanf的用法

fetch普通用法及搭配async,await用法小记

C语言scanf_s()函数的用法