std::scanf,std::fscanf,std::sscanf
C++
Compiler support
Freestanding and hosted
Language
Standard library
Standard library headers
Named requirements
Feature test macros
(C++20)
Language support library
Concepts library
(C++20)
Diagnostics library
Memory management library
Metaprogramming library
(C++11)
General utilities library
Containers library
Iterators library
Ranges library
(C++20)
Algorithms library
Strings library
Text processing library
Numerics library
Date and time library
Input/output library
Filesystem library
(C++17)
Concurrency support library
(C++11)
Execution control library
(C++26)
Technical specifications
Symbols index
External libraries
Input/output library
I/O manipulators
Print functions
(C++23)
C-style I/O
Buffers
basic_streambuf
basic_filebuf
basic_stringbuf
basic_spanbuf
(C++23)
strstreambuf
(
C++98/26*
)
basic_syncbuf
(C++20)
Streams
Abstractions
ios_base
basic_ios
basic_istream
basic_ostream
basic_iostream
File I/O
basic_ifstream
basic_ofstream
basic_fstream
String I/O
basic_istringstream
basic_ostringstream
basic_stringstream
Array I/O
basic_ispanstream
(C++23)
basic_ospanstream
(C++23)
basic_spanstream
(C++23)
istrstream
(
C++98/26*
)
ostrstream
(
C++98/26*
)
strstream
(
C++98/26*
)
Synchronized Output
basic_osyncstream
(C++20)
Types
streamoff
streamsize
fpos
Error category interface
iostream_category
(C++11)
io_errc
(C++11)
C-style I/O
Types and objects
FILE
fpos_t
stdin
stdout
stderr
Functions
File access
fopen
freopen
fclose
fflush
fwide
setbuf
setvbuf
Direct input/output
fread
fwrite
Unformatted input/output
fgetc
getc
fgets
fputc
putc
fputs
getchar
gets
(until C++14)
putchar
puts
ungetc
fgetwc
getwc
fgetws
fputwc
putwc
fputws
getwchar
putwchar
ungetwc
Formatted input
scanf
fscanf
sscanf
vscanf
vfscanf
vsscanf
(C++11)
(C++11)
(C++11)
wscanf
fwscanf
swscanf
vwscanf
vfwscanf
vswscanf
(C++11)
(C++11)
(C++11)
Formatted output
printf
fprintf
sprintf
snprintf
(C++11)
vprintf
vfprintf
vsprintf
vsnprintf
(C++11)
wprintf
fwprintf
swprintf
vwprintf
vfwprintf
vswprintf
File positioning
ftell
fgetpos
fseek
fsetpos
rewind
Error handling
clearerr
feof
ferror
perror
Operations on files
remove
rename
tmpfile
tmpnam
定义于头文件
int
scanf
(
const
char
*
format, ...
)
;
(1)
int
fscanf
(
std::
FILE
*
stream,
const
char
*
format, ...
)
;
(2)
int
sscanf
(
const
char
*
buffer,
const
char
*
format, ...
)
;
(3)
从多种来源读取数据,根据
format
解释数据,并将结果存储到指定位置。
1)
从
stdin
读取数据。
2)
从文件流
stream
中读取数据。
3)
从以空字符结尾的字符串
buffer
中读取数据。
目录
1
参数
2
返回值
3
复杂度
4
备注
5
示例
6
参见
参数
stream
-
用于读取的输入文件流
buffer
-
指向以空字符结尾的字符串的指针,用于读取数据
format
-
指向以空字符结尾的字符串的指针,指定输入读取格式
...
-
接收参数
format
字符串由以下部分组成
非空白多字节字符(除
%
外):格式字符串中的每个此类字符会从输入流中消耗一个完全相同的字符,如果流中的下一个字符不相等则导致函数执行失败。
空白字符:格式字符串中的任意单个空白字符会消耗输入中所有可用的连续空白字符(通过循环调用
std::isspace
确定)。注意格式字符串中的
"
\n
"
、
" "
、
"
\t
\t
"
或其他空白字符之间没有区别。
转换说明符。每个转换说明符具有以下格式:
引导性
%
字符。
(可选)
赋值抑制字符
*
。若存在此选项,函数不会将转换结果赋值给任何接收参数。
(可选)
指定
最大字段宽度
的整数(大于零),即函数在执行当前转换说明符指定的转换时允许消耗的最大字符数。请注意,若未提供宽度参数,
%
s
和
%
[
可能导致缓冲区溢出。
(可选)
长度修饰符
用于指定接收参数的大小,即实际的目标类型。这将影响转换精度和溢出规则。默认目标类型因各转换类型而异(详见下表)。
转换格式说明符。
以下格式说明符可用:
转换
说明符
说明
期望
参数类型
长度修饰符→
hh
h
无
l
ll
j
z
t
L
仅自 C++11 起可用→
是
是
是
是
是
%
匹配字面量
%
。
N/A
N/A
N/A
N/A
N/A
N/A
N/A
N/A
N/A
c
匹配一个
字符
或一系列
字符
。
如果使用宽度说明符,则精确匹配
width
个字符(参数必须指向具有足够空间的数组)。
与 %s 和 %[ 不同,不会向数组追加空字符。
N/A
N/A
char
*
wchar_t
*
N/A
N/A
N/A
N/A
N/A
s
匹配非空白字符序列(即
string
)。
若使用宽度限定符,则最多匹配
width
个字符或遇到首个空白字符即停止(以先到者为准)。
始终在匹配字符外额外存储一个空字符(因此参数数组必须至少有
width+1
字符的存储空间)。
[
set
]
匹配来自字符集
set
的非空字符序列。
若集合的首字符为
^
,则匹配所有不在该集合中的字符。
若集合以
]
或
^]
开头,则
]
字符也会被包含在集合中。
在非起始位置出现的
-
字符是否表示范围(如
[0-9]
)由实现定义。
若使用了宽度限定符,则最多匹配
width
个字符。
始终在匹配的字符之外额外存储一个空字符(因此参数数组必须至少有
width+1
个字符的空间)。
d
匹配一个
十进制整数
。
数字格式与
std::strtol
函数所期望的格式相同,其中
10
作为
base
参数的值。
signed
char
*
或
unsigned
char
*
signed
short
*
或
unsigned
short
*
signed
int
*
或
unsigned
int
*
signed
long
*
或
unsigned
long
*
signed
long
long
*
或
unsigned
long
long
*
std::
intmax_t
*
或
std::
uintmax_t
*
std::
size_t
*
std::
ptrdiff_t
*
不适用
i
匹配一个
整数
。
数字格式与
std::strtol
函数所期望的格式相同,其中
0
作为
base
参数的值(进制由解析的首字符确定)。
u
匹配无符号
十进制整数
。
数字格式与
std::strtoul
函数所期望的格式相同,其中
10
作为
base
参数的值。
o
匹配无符号
八进制整数
。
数字格式与
std::strtoul
函数的要求相同,其中
8
作为
base
参数的值。
x
X
匹配无符号
十六进制整数
。
数字格式与
std::strtoul
函数的要求一致,其中
16
作为
base
参数的值。
n
返回
当前已读取的字符数
。
不消耗输入。不增加赋值计数。
若格式说明符定义了赋值抑制操作符,则行为未定义。
a
(C++11)
A
(C++11)
e
E
f
F
(C++11)
g
G
匹配
浮点数
。
数字格式与
std::strtof
所预期的格式相同。
不适用
不适用
float
*
double
*
不适用
不适用
不适用
不适用
long
double
*
p
匹配实现定义的字符序列,用于表示
指针
。
printf
系列函数应使用
%p
格式说明符生成相同序列。
N/A
N/A
void
**
N/A
N/A
N/A
N/A
N/A
N/A
备注
对于除
n
之外的所有转换说明符,从流中消耗的输入字符序列是:不超过指定字段宽度、且完全符合转换说明符预期或符合其预期序列前缀的最长字符序列。该消耗序列后的首个字符(若存在)将保持未读取状态。若消耗序列长度为零,或消耗序列无法按上述规则完成转换,则出现匹配失败——除非因文件结束、编码错误或读取错误导致无法从流中获取输入,此时属于输入失败。
除
[
、
c
和
n
之外的所有转换说明符,在尝试解析输入前会消耗并丢弃所有前导空白字符(通过调用
std::isspace
判定)。这些被消耗的字符不计入指定的最大字段宽度。
转换说明符
lc
、
ls
和
l
[
会执行多字节到宽字符的转换,其过程类似于在转换首个字符前,调用以零初始化的
std::mbstate_t
对象进行
std::mbrtowc
调用。
转换说明符
s
和
[
除了存储匹配的字符外,始终会存储空终止符。目标数组的大小必须至少比指定字段宽度大1。若使用
%
s
或
%
[
时未指定目标数组大小,其不安全性等同于
std::gets
。
固定宽度整数类型
(如
std::int8_t
等)的正确转换规范定义于头文件
中(尽管
SCNdMAX
、
SCNuMAX
等分别等同于
%
jd
、
%
ju
等)。
每个转换说明符执行完成后存在一个
顺序点
,这允许将多个字段存储至同一个“接收”变量中。
当解析以指数符号结尾但缺少数字的不完整浮点数值时(例如使用转换说明符
%
f
解析
"100er"
),将消耗序列
"100e"
(可能有效的浮点数的最长前缀),导致匹配错误(消耗的序列无法转换为浮点数),并保留
"r"
。某些现有实现未遵循此规则,会回退至仅消耗
"100"
,留下
"er"
,例如
glibc bug 1765
。
若转换规范无效,则行为未定义。
返回值
成功接收并赋值的参数数量(若在首个接收参数被赋值前发生匹配失败,则该值可能为零),或
EOF
若在首个接收参数被赋值前发生输入失败。
复杂度
不保证性能。特别需要注意的是,某些
std::sscanf
的实现是
O(N)
的,其中
N
=
std::
strlen
(
buffer
)
[1]
。如需高性能字符串解析,请参阅
std::from_chars
。
注释
由于大多数转换说明符首先会消耗所有连续的空白字符,因此诸如
std::scanf("%d", &a);
std::scanf("%d", &b);
将读取在不同行输入的两个整数(第二个
%
d
会消耗第一个输入遗留的换行符)或在同一行输入、以空格或制表符分隔的两个整数(第二个
%
d
会消耗空格或制表符)。
The conversion specifiers that do not consume leading whitespace, such as
%
c
, can be made to do so by using a whitespace character in the format string:
std::scanf("%d", &a);
std::scanf(" %c", &c); // 忽略 %d 后的换行符,然后读取一个字符
请注意,某些
std::sscanf
的实现会调用
std::strlen
,这导致其运行时间与整个字符串的长度成线性关系。这意味着如果在循环中调用
std::sscanf
来重复解析字符串前端的值,您的代码可能会以二次方时间运行(
示例
)。
示例
运行此代码
#include
#include
#include
int main()
{
int i, j;
float x, y;
char str1[10], str2[4];
wchar_t warr[2];
std::setlocale(LC_ALL, "en_US.utf8");
char input[] = "25 54.32E-1 Thompson 56789 0123 56ß水";
// 解析方式如下:
// %d: 整数
// %f: 浮点数值
// %9s: 最多9个非空白字符的字符串
// %2d: 两位整数(数字5和6)
// %f: 浮点数值(数字7、8、9)
// %*d: 不存储在任何位置的整数
// ' ': 所有连续空白字符
// %3[0-9]: 最多3位数字的字符串(数字5和6)
// %2lc: 两个宽字符,使用多字节到宽字符转换
const int ret = std::sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
&i, &x, str1, &j, &y, str2, warr);
std::cout << "转换了 " << ret << " 个字段:\n"
"i = " << i << "\n"
"x = " << x << "\n"
"str1 = " << str1 << "\n"
"j = " << j << "\n"
"y = " << y << "\n"
"str2 = " << str2 << std::hex << "\n"
"warr[0] = U+" << (int)warr[0] << "\n"
"warr[1] = U+" << (int)warr[1] << '\n';
}
输出:
转换了 7 个字段:
i = 25
x = 5.432
str1 = Thompson
j = 56
y = 789
str2 = 56
warr[0] = U+df
warr[1] = U+6c34
另请参阅
vscanf
vfscanf
vsscanf
(C++11)
(C++11)
(C++11)
从
stdin
、文件流或缓冲区读取格式化输入
使用可变参数列表
(函数)
fgets
从文件流获取字符串
(函数)
printf
fprintf
sprintf
snprintf
(C++11)
将格式化输出打印到
stdout
、文件流或缓冲区
(函数)
from_chars
(C++17)
将字符序列转换为整型或浮点型值
(函数)
C 文档
关于
scanf
、
fscanf
、
sscanf