函数
<cstdio>

scanf

int scanf ( const char * format, ... );
从 stdin 读取格式化数据
stdin 读取数据,并根据参数 format 将它们存储到附加参数所指向的位置。

附加参数应该指向已分配的对象,其类型由 format 字符串中相应的格式说明符指定。

参数

format
C 字符串,包含一个字符序列,用于控制如何处理从流中提取的字符
  • 空白字符:函数将读取并忽略在下一个非空白字符之前遇到的任何空白字符(空白字符包括空格、换行符和制表符 -- 参见 isspace)。format 字符串中的单个空白符会验证从中提取的任意数量的空白字符(包括没有)。
  • 非空白字符,格式说明符 (%) 除外:任何既不是空白字符(空格、换行或制表符)也不是格式说明符一部分(以%字符开头)的字符,都会导致函数从流中读取下一个字符,并将其与此非空白字符进行比较,如果匹配,则丢弃该字符,函数继续处理 format 的下一个字符。如果字符不匹配,函数将失败,返回并使流中后续的字符保持未读状态。
  • 格式说明符:由初始百分号 (%) 形成的序列表示一个格式说明符,它用于指定要从中检索并存储到附加参数所指向位置的数据的类型和格式。

一个格式说明符scanf遵循此原型

%[*][width][length]specifier

其中,末尾的说明符字符是最重要的组成部分,因为它定义了提取哪些字符、它们的解释以及其相应参数的类型
说明符描述提取的字符
i整数任意数量的数字,可选地以符号 (+-).
) 开头。默认假定为十进制数字 (0-9),但0前缀表示八进制数字 (0-7),而0x 或 0X 表示十六进制数字 ( (0-f).
)。有符号参数。
d u十进制整数任意数量的十进制数字 (0-9),可选地以符号 (+-).
d) 开头。d 用于有符号参数,uu 用于无符号参数。
o八进制整数任意数量的八进制数字 (0-7),可选地以符号 (+-).
),可选地以符号开头。无符号参数。
x十六进制整数任意数量的十六进制数字 (0-9, a-f, A-F),可选地以0x或 0X0x 或 0X 开头,并且都可选地以符号开头。无符号参数。+-).
),可选地以符号开头。无符号参数。
f, e, g浮点数一系列十进制数字,可选地包含一个小数点,可选地以符号 (+-) 开头,并可选地后跟ee 或 E字符和一个十进制整数(或 strtod 支持的其他一些序列)。
符合 C99 标准的实现也支持以 0x0X 开头的十六进制浮点格式。
a
c字符下一个字符。如果指定了非11 的宽度,函数将精确读取宽度个字符,并将它们存储在作为参数传递的数组的连续位置中。末尾不会附加空字符。
s字符串任意数量的非空白字符,在找到第一个空白字符时停止。一个终止空字符会自动添加到存储序列的末尾。
p指针地址表示指针的字符序列。使用的特定格式取决于系统和库的实现,但它与在 fprintf 中格式化%p所用的格式相同。
[字符]扫描集方括号之间指定的任意数量的字符。
一个不是第一个字符的破折号 (-) 在某些库实现中可能会产生不可移植的行为。
[^字符]反向扫描集任意数量的字符,其中没有一个是在方括号内指定为字符的。
n计数不消耗任何输入。
到目前为止从 stdin 读取的字符数被存储在指向的位置。
%%一个%后跟另一个%% 匹配一个单独的%.
% 字符。此说明符不存储任何数据。请参阅获取百分号字符。除了 %n 和 %%n外,任何说明符都应至少消耗一个字符。否则匹配失败,扫描在此结束。

格式说明符还可以包含子说明符:星号 (*)、宽度长度(按此顺序),它们是可选的,并遵循以下规范:
子说明符描述
*一个可选的起始星号表示数据将从流中读取但被忽略(即,它不存储在由参数指向的位置)。
宽度指定在当前读取操作中要读取的最大字符数(可选)。
长度以下之一hh, h, l, ll, j, z, t, L(可选)。
这会改变相应参数所指向的存储的预期类型(见下文)。

这是一个图表,显示了存储输入数据的相应参数的预期类型(带有和不带有长度子说明符)
说明符
长度d iu o xf e g ac s [] [^]pn
(无)int*unsigned int*float*char*void**int*
hhsigned char*unsigned char*signed char*
hshort int*unsigned short int*short int*
llong int*unsigned long int*double*wchar_t*long int*
lllong long int*unsigned long long int*long long int*
jintmax_t*uintmax_t*intmax_t*
zsize_t*size_t*size_t*
tptrdiff_t*ptrdiff_t*ptrdiff_t*
Llong double*
注意:黄色行表示由 C99 引入的说明符和子说明符。
... (附加参数)
根据 format 字符串,该函数可能需要一系列附加参数,每个参数都包含一个指向已分配存储空间的指针,其中提取的字符的解释将以适当的类型存储。
这些参数的数量至少应与格式说明符存储的值的数量相同。多余的参数会被函数忽略。
这些参数应该是指针:要在一个普通变量上存储scanfscanf 操作的结果,其名称前应加上引用运算符 (&&)(参见示例)。

返回值

成功时,函数返回成功填充的参数列表项的数量。由于匹配失败、读取错误或到达文件结尾,该计数可能与预期的项数相符,也可能更少(甚至为零)。

如果在读取时发生读取错误或到达文件末尾,则会设置相应的指示器(feofferror)。并且,如果任一情况在任何数据被成功读取之前发生,则返回 EOF

如果在解释宽字符时发生编码错误,函数会设置 errnoEILSEQ.

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 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:
Enter your family name: Soulie
Enter your age: 29
Mr. Soulie , 29 years old.
Enter a hexadecimal number: ff
You have entered 0xff (255).


兼容性

scanf 读取的一些类型。特定的库实现可能支持额外的说明符和子说明符。
这里列出的是最新的 C 和 C++ 标准(均于 2011 年发布)所支持的,但黄色的部分是由 C99 引入的(自 C++11 起才要求 C++ 实现支持),可能不被符合旧标准的库所支持。

另见