scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s
| 在标头 <stdio.h> 定义
|
||
| (1) | ||
| |
(C99 前) | |
| |
(C99 起) | |
| (2) | ||
| |
(C99 前) | |
| |
(C99 起) | |
| (3) | ||
| |
(C99 前) | |
| |
(C99 起) | |
| |
(4) | (C11 起) |
| |
(5) | (C11 起) |
| |
(6) | (C11 起) |
从各种资源读取数据,按照 format 转译,并将结果存储到指定位置。
stream 读取数据buffer 读取数据。抵达字符串结尾等价于 fscanf 的抵达文件尾条件%c 、 %s 及 %[ 转换指示符要求二个参数(通常的指针和指示获取用数组大小的 rsize_t 类型的值,在以 %c 读取单个字符时可以为 1 ),并调用当前安装的约束处理函数:
- 任何指针类型的参数为空指针
format、stream或buffer为空指针%c、%s或%[会写入的字符数,加上空终止字符,要超过提供给这些转换指示符的第二个( rsize_t )参数- 可选,任何其他可检测错误,例如未知转换指示符
- 同所有边界检查函数,
scanf_s、fscanf_s与sscanf_s,仅若实现定义__STDC_LIB_EXT1__且用户在包含 <stdio.h> 前定义__STDC_WANT_LIB_EXT1__为整数常量 1 才保证可用。
参数
| stream | - | 要读取的输入文件流 |
| buffer | - | 指向要读取的空终止字符串的指针 |
| format | - | 指向指定读取输入方式的空终止字符串的指针 |
| ... | - | 各接收实参 |
格式字符串由下列内容组成
- 非空白多字节字符,除了
%:每个格式字符串中的这种字符处理一个来自输入流的完全相同的字符,或在它与流的下个字符比较不相等时导致函数失败。 - 空白字符:任何格式字符串中的单个空白字符处理所有来自输入的可用连续空白字符(如同通过于循环中调用 isspace 确定)。注意,格式字符串中
"\n"、" "、"\t\t"或其他空白无区别。 - 转换指示:每个转换指示拥有下列格式:
- 引入用
%字符
- 引入用
- (可选) 赋值抑制字符
*。如果存在此选项,那么此函数不将结果赋值给任何接收用实参。
- (可选) 赋值抑制字符
- (可选) 指定最大字段宽度 的整数数字(大于零),即函数进行在当前转换指示所指定的转换时,允许处理的最大字符数。注意如果没有提供宽度,那么
%s和%[可能导致缓冲区溢出。
- (可选) 指定最大字段宽度 的整数数字(大于零),即函数进行在当前转换指示所指定的转换时,允许处理的最大字符数。注意如果没有提供宽度,那么
- (可选) 指定接收实参大小的长度修饰符,即实际目标类型。这影响转换准确性和溢出规则。默认目标类型对每个转换类型有所不同(见下表)。
- 转换格式指示符。
下列格式指示符可用:
| 转换指示符 | 解释 | 期望的实参类型 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 长度修饰符→ | hh | h | 无 | l | ll | j | z | t | L | |
| 仅从 C99 起可用→ | 是 | 是 | 是 | 是 | 是 | |||||
%
|
匹配字面
%。 |
不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 |
c
|
匹配一个字符或字符的序列。
|
不适用 | 不适用 | char* |
wchar_t* |
不适用 | 不适用 | 不适用 | 不适用 | 不适用 |
s
|
匹配非空白字符的序列(一个字符串)。
| |||||||||
[集合 ]
|
匹配集合 中的字符的一个非空字符序列。
| |||||||||
d
|
匹配一个十进制整数。
|
signed char* 或 unsigned char* |
signed short* 或 unsigned short* |
signed int* 或 unsigned int* |
signed long* 或 unsigned long* |
signed long long* 或 unsigned long long* |
intmax_t* 或 uintmax_t* |
size_t* |
ptrdiff_t* |
不适用 |
i
|
匹配一个整数。
| |||||||||
u
|
匹配一个无符号十进制整数。
| |||||||||
o
|
匹配一个无符号八进制数。
| |||||||||
xX
|
匹配一个无符号十六进制整数。
| |||||||||
n
|
返回迄今读取的字符数。
| |||||||||
a (C99)A (C99)eEfF (C99)gG
|
匹配一个浮点数。
|
不适用 | 不适用 | float* |
double* |
不适用 | 不适用 | 不适用 | 不适用 | long double* |
p
|
匹配定义了一个指针的由实现定义的字符序列。
|
不适用 | 不适用 | void** |
不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 |
| 注解 | ||||||||||
|
对于每个 所有异于 转换指示符 转换指示符 定宽整数类型(int8_t 等)的正确的转换指示在标头 <inttypes.h> 定义(虽然 SCNdMAX、SCNuMAX 等就是 在每个转换指示符后有一个序列点;这允许存储多个字段到同一“池”变量中。 在分析以无数字指数为结尾的不完整浮点数,如以转换指示符 如果转换指示非法,那么行为未定义。 | ||||||||||
返回值
复杂度
无保证。需要注意的是,有些 sscanf 的实现为 O(N),其中 N = strlen(buffer) [1]。
注解
因为多数转换指示符首先消耗掉所有连续空白符,如下的代码
scanf("%d", &a);
scanf("%d", &b);
将读取在不同行上(第二个 %d 会消耗第一个剩下的换行符)或同一行由空格或制表符分隔(第二个 %d 会消耗空格或制表符)的整数。
不消耗前导空白符的转换指示符,如 %c,可以通过在格式字符串中前置一个空白符令它如此:
scanf("%d", &a);
scanf(" %c", &c); // 消耗 %d 后的所有后继空白符,然后读一个 char
示例
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stddef.h>
#include <locale.h>
int main(void)
{
int i, j;
float x, y;
char str1[10], str2[4];
wchar_t warr[2];
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 :两个宽字符,使用多字节到宽转换 */
int ret = sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
&i, &x, str1, &j, &y, str2, warr);
printf("Converted %d fields:\n"
"i = %d\n"
"x = %f\n"
"str1 = %s\n"
"j = %d\n"
"y = %f\n"
"str2 = %s\n"
"warr[0] = U+%x\n"
"warr[1] = U+%x\n",
ret, i, x, str1, j, y, str2, warr[0], warr[1]);
#ifdef __STDC_LIB_EXT1__
int n = sscanf_s(input, "%d%f%s", &i, &x, str1, (rsize_t)sizeof str1);
// 向 i 写入 25,向 x 写入 5.432,向 str1 写入 9 个字节 "thompson\0",并向 n 写入 3。
#endif
}
输出:
Converted 7 fields:
i = 25
x = 5.432000
str1 = Thompson
j = 56
y = 789.000000
str2 = 56
warr[0] = U+df
warr[1] = U+6c34
引用
- C17 标准(ISO/IEC 9899:2018):
- 7.21.6.2 The fscanf function (第 231-236 页)
- 7.21.6.4 The scanf function (第 236-237 页)
- 7.21.6.7 The sscanf function (第 238-239 页)
- K.3.5.3.2 The fscanf_s function (第 430-431 页)
- K.3.5.3.4 The scanf_s function (第 432 页)
- K.3.5.3.7 The sscanf_s function (第 433 页)
- C11 标准(ISO/IEC 9899:2011):
- 7.21.6.2 The fscanf function (第 317-324 页)
- 7.21.6.4 The scanf function (第 325 页)
- 7.21.6.7 The sscanf function (第 326 页)
- K.3.5.3.2 The fscanf_s function (第 592-593 页)
- K.3.5.3.4 The scanf_s function (第 594 页)
- K.3.5.3.7 The sscanf_s function (第 596 页)
- C99 标准(ISO/IEC 9899:1999):
- 7.19.6.2 The fscanf function (第 282-289 页)
- 7.19.6.4 The scanf function (第 290 页)
- 7.19.6.7 The sscanf function (第 291 页)
- C89/C90 标准(ISO/IEC 9899:1990):
- 4.9.6.2 The fscanf function
- 4.9.6.4 The scanf function
- 4.9.6.6 The sscanf function
参阅
(C99)(C99)(C99)(C11)(C11)(C11) |
从 stdin、文件流或缓冲区读取格式化输入 使用可变参数列表 (函数) |
| 从文件流获取一个字符串 (函数) | |
(C99)(C11)(C11)(C11)(C11) |
打印格式化输出到 stdout、文件流或缓冲区 (函数) |
scanf, fscanf, sscanf 的 C++ 文档
| |