C++官网参考链接:https://cplusplus.com/reference/cstdio/scanf/
函数
<cstdio>
scanf
int scanf ( const char * format, ... );
从stdin读取格式化的数据
从标准输入(stdin)读取数据,并根据形参format将数据存储到附加实参所指向的位置。
附加实参应该指向format字符串中相应的格式说明符指定的已分配类型的对象。
形参
format
C字符串,包含一个字符序列,控制如何处理从流中提取的字符:
*空白字符:该函数将读取并忽略下一个非空白字符之前遇到的任何空白字符(空白字符包括空格、换行符和制表符---参见isspace)。format字符串中的一个空白验证从流中提取的任何数量的空白字符(包括没有)。
*非空白字符,格式说明符(%)除外:任何既不是空白字符(空格、换行符或制表符)也不是格式说明符(以%字符开始)一部分的字符都会导致函数从流中读取下一个字符,并将其与此非空白字符进行比较,如果匹配,则丢弃该字符,并继续处理format的下一个字符。如果字符不匹配,则函数失败,返回并保留未读取流的后续字符。
*格式说明符:由初始百分比符号(%)组成的序列指示格式说明符,用于指定要从流中获取的数据的类型和格式,并将其存储到附加实参所指向的位置。
scanf的格式说明符遵循以下原型:
%[*][width][length]specifier
其中,结束的specifier字符是最重要的组件,因为它定义了提取哪些字符、它们的解释以及对应实参的类型:
specifier | Description | Characters extracted |
---|---|---|
i | Integer | Any number of digits, optionally preceded by a sign (+ or -). (任意数量的数字,前面带可选的符号(+或-)。 默认为十进制数字(Decimal digits)(0-9),但0前缀引入八进制数字(0-7)和0x引入十六进制数字(hexadecimal digits)(0-f)。 有符号实参。) |
d or u | Decimal integer | Any number of decimal digits (0-9), optionally preceded by a sign (+ or -). (任意数量的十进制数字(decimal digits)(0-9),前面有一个可选的符号(+或-)。 d是有符号实参,u是无符号实参。) |
o | Octal integer | Any number of octal digits (0-7), optionally preceded by a sign (+ or -). (八进制数字(0-7)的任意数量,前面有一个可选的符号(+或-)。 无符号实参。) |
x | Hexadecimal integer | Any number of hexadecimal digits (0-9, a-f, A-F), optionally preceded by 0x or 0X, and all optionally preceded by a sign (+ or -). (任意数量的十六进制数字(hexadecimal digits)(0-9,a-f, A-F),前面可选的是0x或0X,前面都有一个可选的符号(+或-)。 无符号实参。) |
f, e, g | Floating point number | A series of decimal digits, optionally containing a decimal point, optionally preceeded by a sign (+ or -) and optionally followed by the e or E character and a decimal integer (or some of the other sequences supported by strtod). (一组十进制(decimal)数字,可选地包含小数点,前面有一个可选的符号(+或-),后面有可选的e或E字符和一个十进制整数(或strtod支持的其他一些序列)。 符合C99的实现还支持前面有0x或0X的十六进制浮点格式。) |
a | ||
c | Character | The next character. If a width other than 1 is specified, the function reads exactly width characters and stores them in the successive locations of the array passed as argument. No null character is appended at the end. (下一个字符。如果指定的width不是1,则该函数准确读取width个字符并将其存储在作为实参传递的数组的连续位置中。结束处不追加空字符。) |
s | String of characters | Any number of non-whitespace characters, stopping at the first whitespace character found. A terminating null character is automatically added at the end of the stored sequence. (任意数量的非空白字符,终止于找到的第一个空白(whitespace)字符。在存储序列的结束处自动添加一个终止空字符。) |
p | Pointer address | A sequence of characters representing a pointer. The particular format used depends on the system and library implementation, but it is the same as the one used to format %p in fprintf. (表示指针的字符序列。所使用的特定格式取决于系统和库实现,但它与fprintf中用于格式化%p的格式相同。) |
[characters] | Scanset | Any number of the characters specified between the brackets. (括号之间指定的任意数量的字符。 破折号 (-) 不是第一个字符的在某些库实现中可能会产生不可移植的行为。) |
[^characters] | Negated scanset | Any number of characters none of them specified as characters between the brackets.(任意数量的字符,其中没有一个指定为括号之间的字符。) |
n | Count | No input is consumed. The number of characters read so far from stdin is stored in the pointed location. (不消耗任何输入。 从stdin到目前为止读取的字符数存储在指定位置。) |
% | % | A % followed by another % matches a single %.(一个%后面跟另一个%匹配一个%。) |
除n外,任何说明符至少需要消耗一个字符。否则,匹配失败,扫描在此结束。
格式说明符还可以包含子说明符:星号(*),width和height(按此顺序),它们是可选的,遵循以下规范:
sub-specifier | description |
---|---|
* | An optional starting asterisk indicates that the data is to be read from the stream but ignored (i.e. it is not stored in the location pointed by an argument). (可选的起始星号表示数据将从流中读取,但会被忽略 (即它不会存储在实参指定的位置)。) |
width | Specifies the maximum number of characters to be read in the current reading operation (optional). (指定当前读取操作中要读取的最大字符数(可选)。) |
length | One of hh, h, l, ll, j, z, t, L (optional). This alters the expected type of the storage pointed by the corresponding argument (see below). (hh,h,l,ll,j,z,t,l中的一个(可选的)。 这将改变相应实参所指向的存储的预期类型(见下文)。) |
这是一个图表,显示了存储输入的相应实参的预期类型(有和没有length子说明符):
specifiers | |||||||
---|---|---|---|---|---|---|---|
length | d i | u o x | f e g a | c s [] [^] | p | n | |
(none) | int* | unsigned int* | float* | char* | void** | int* | |
hh | signed char* | unsigned char* | signed char* | ||||
h | short int* | unsigned short int* | short int* | ||||
l | long int* | unsigned long int* | double* | wchar_t* | long int* | ||
ll | long long int* | unsigned long long int* | long long int* | ||||
j | intmax_t* | uintmax_t* | intmax_t* | ||||
z | size_t* | size_t* | size_t* | ||||
t | ptrdiff_t* | ptrdiff_t* | ptrdiff_t* | ||||
L | long double* |
注:黄色行表示C99引入的说明符和子说明符。
...(附加实参)
根据format字符串的不同,函数可能期望一个附加实参序列,每个实参包含一个指向已分配存储空间的指针,在该存储空间中,用适当的类型存储对提取字符的解释。
这些实参的数量至少应该与格式说明符存储的值的数量相同。函数将忽略额外的实参。
这些实参应该是指针:要在一个普通变量上存储scanf操作的结果,它的名称之前应该有引用操作符(&)。
返回值
成功时,函数返回成功填充的实参列表的项数。由于匹配失败、读取错误或到达文件结束,此计数可以与预期的项数匹配,也可以更少(甚至为0)。
如果在读取过程中发生读取错误或到达文件结束,则设置适当的指示符(feof或ferror)。并且,如果在成功读取任何数据之前发生任何一种情况,则返回EOF。
如果在解释宽字符时发生编码错误,该函数将errno设置为EILSEQ。
用例
/* scanf example */
#include <stdio.h>
int main ()
{
char str [80];
int i;
printf ("Enter your family name: ");
scanf ("%79s",str);
printf ("Enter your age: ");
scanf ("%d",&i);
printf ("Mr. %s , %d years old.\n",str,i);
printf ("Enter a hexadecimal number: ");
scanf ("%x",&i);
printf ("You have entered %#x (%d).\n",i,i);
return 0;
}
这个例子演示了一些可以用scanf读取的类型:
兼容性
特定的库实现可能支持额外的说明符和子说明符。
这里列出的是由最新的C和C++标准支持的(都是在2011年发布的),但是黄色的那些是在C99中引入的(只有C++11之后的C++实现才需要),并且可能不被遵循旧标准的库所支持。