/*********************************************
* @brief 从标准输入中获取输入
* @param format 格式字符串
* @param ... 可变长度参数,要打印的变量
* @return 打印的字符数量
********************************************/
int scanf(const char* restrict format, ...);
!subtitle:说明
从标准输入中获取输入。
!subtitle:参数
format - 格式化字符串,指向以空字符(\0)结尾的字符串指针,指定如何解释数据
普通字符直接输入,如果不匹配则导致失败
转义字符按照转义打印
空格字符将读取输入的所有连续空白字符,包括空格,\n,\t 等
以 % 开头的 格式占位符,按照指定格式读取输入并写入后续相应位置的参数
... - 可变长度参数,为接收输入的地址,需要与 format 参数中的格式占位符一一对应
!subtitle:返回值
成功分配的接收参数的数量
分配第一个接收参数之前发生匹配失败时返回 0
分配第一个接收参数之前发生输入失败时返回 EOF
#include <stdio.h>
int main(void)
{
int age;
float height;
double weight;
char initial;
char name[50]; // 存储姓名(无空格)
char sentence[100]; // 存储带空格的整行输入
// 示例1:读取整数、浮点数、字符
printf("请输入您的年龄、身高(米)、体重(kg)和姓氏首字母(用空格分隔):");
int items_read = scanf("%d %f %lf %c", &age, &height, &weight, &initial);
if (items_read != 4) {
printf("输入错误!请确保输入4个值(年龄 身高 体重 首字母)。\n");
while (getchar() != '\n'); // 清空输入缓冲区
} else {
printf("结果:您今年%d岁,身高%.2f米,体重%.1lfkg,姓名首字母是'%c'。\n",
age, height, weight, initial);
}
// 示例2:读取名称首字母(无空格)
printf("\n请输入您的名称首字母(不要带空格):");
if (scanf("%49s", name) == 1) { // 限制长度防止溢出
printf("您好,%s!\n", name);
} else {
printf("未能读取姓名。\n");
}
// 示例3:读取整行(允许空格)
printf("\n请输入一句话(可以带空格):");
while (getchar() != '\n'); // 清空之前的输入缓冲区
if (scanf("%99[^\n]", sentence) == 1) { // 读取直到换行符
printf("您输入的是:「%s」\n", sentence);
} else {
printf("未接收到输入。\n");
}
// 示例4:安全读取整数(错误处理)
int number;
printf("\n请输入一个整数:");
while (scanf("%d", &number) != 1) { // 循环直到输入有效
printf("输入无效!请重新输入整数:");
while (getchar() != '\n'); // 清空缓冲区
}
printf("您输入的整数是:%d\n", number);
return 0;
}
运行结果:
请输入您的年龄、身高(米)、体重(kg)和姓氏首字母(用空格分隔):17 160 50 h
结果:您今年17岁,身高160.00米,体重50.0kg,姓名首字母是'h'。
请输入您的名称首字母(不要带空格):bc
您好,bc!
请输入一句话(可以带空格):hello world
您输入的是:「hello world」
请输入一个整数:233
您输入的整数是:233
格式占位符以 %[*][宽度][长度修饰]说明符 的形式出现。
* 是赋值抑制符,表示这部分输入不赋值给接收参数
宽度:输入的最大字符数
长度修饰:表示类型长度,例如 %d 是 int,而 %ld 是 long
| 说明符 | !embed:<div style='min-width:12em'>说明</div> |
参数类型 | hh |
h |
l |
ll |
j |
z |
t |
L |
|---|---|---|---|---|---|---|---|---|---|---|
% |
百分号(%)本身 |
|||||||||
c |
单个字符 | char* |
wchar_t |
|||||||
s |
字符串,以空字符(\0)结尾 |
char* |
wchar_t* |
|||||||
d |
有符号十进制整数 | int* |
signed char* |
short* |
long* |
long long* |
intmax_t* |
size_t* |
ptrdiff_t* |
|
i |
有符号十进制整数,同 %d |
int* |
signed char* |
short* |
long* |
long long* |
intmax_t* |
size_t* |
ptrdiff_t* |
|
u |
无符号十进制整数 | unsigned int* |
unsigned char* |
unsigned short* |
unsigned long* |
unsigned long long* |
uintmax_t* |
size_t* |
ptrdiff_t* |
|
o |
无符号八进制整数 | unsigned int* |
unsigned char* |
unsigned short* |
unsigned long* |
unsigned long long* |
uintmax_t* |
size_t* |
ptrdiff_t* |
|
x |
无符号十六进制整数,字母小写 | unsigned int* |
unsigned char* |
unsigned short* |
unsigned long* |
unsigned long long* |
uintmax_t* |
size_t* |
ptrdiff_t* |
|
X |
无符号十六进制整数,字母大写 | unsigned int* |
unsigned char* |
unsigned short* |
unsigned long* |
unsigned long long* |
uintmax_t* |
size_t* |
ptrdiff_t* |
|
f |
浮点数,字母小写 | float* |
double* |
long double* |
||||||
F |
浮点数,同 %f |
float* |
double* |
long double* |
||||||
e |
浮点数,科学计数法,字母小写 | float* |
double* |
long double* |
||||||
E |
浮点数,科学计数法,字母大写 | float* |
double* |
long double* |
||||||
g |
浮点数,省略小数末尾的 0,值较大时使用科学计数法,字母小写 | float* |
double* |
long double* |
||||||
G |
浮点数,省略小数末尾的 0,值较大时使用科学计数法,字母大写 | float* |
double* |
long double* |
||||||
a |
浮点数,十六进制,科学计数法,字母小写 | float* |
double* |
long double* |
||||||
A |
浮点数,十六进制,科学计数法,字母大写 | float* |
double* |
long double* |
||||||
p |
指针地址 | void* |
||||||||
n |
将当前已读取的字符数量写入参数中 | int* |
siged char* |
short* |
long* |
long long* |
intmax_t* |
size_t* |
ptrdiff_t* |
|
[set] |
匹配字符集合,类似正则表达式的中括号 | char* |
wchar_t* |
非字符类型的格式,例如 %d,%x 等,在读取输入时将忽略开头的空白字符,例如向 %d 输入 " 12 34" 可以得到 12," 34" 将保留在输入缓冲区。
匹配字符集合 [set] 用于指定匹配某些字符。例如:
%[abc] 表示读取连续的多个 a,b 或 c,遇到其它字符时停止匹配
%[^abc] 表示读取连续的多个除了 a,b,c 以外的字符,遇到 a,b 或 c时停止匹配
%[^\n] 表示读取连续的多个除了 \n 以外的字符,遇到 \n 时停止匹配;也就是读取整行
%[a-z] 表示读取连续的多个小写字母,遇到其它字符时停止匹配
%[0-9] 表示读取连续的多个数字,遇到其它字符时停止匹配
%9[0-9] 表示读取连续的多个数字,遇到其它字符时停止匹配;最多读取 9 个字符
%*[^A-Za-z] 表示读取连续的多个字母,遇到其它字符时停止匹配;并将这些输入丢弃
由于 C 语言中类型的长度不是固定的。反过来说,固定长度的类型,其原始类型是不确定的。
例如 int32_t 在某些环境下是 int,另外某些环境下是 long;前者使用 scanf 读取时应使用 %d,而后者应使用 %ld。
为了方便,可以使用以下宏来标识格式。
scanf 格式 |
标准 | 说明 |
|---|---|---|
SCNd8 |
C99 | scanf 中用于输入 int8_t 的 d 格式(有符号十进制) |
SCNd16 |
C99 | scanf 中用于输入 int16_t 的 d 格式 |
SCNd32 |
C99 | scanf 中用于输入 int32_t 的 d 格式 |
SCNd64 |
C99 | scanf 中用于输入 int64_t 的 d 格式 |
SCNdPTR |
C99 | scanf 中用于输入 intptr_t 的 d 格式 |
SCNdMAX |
C99 | scanf 中用于输入 intmax_t 的 d 格式 |
SCNdFAST8 |
C99 | scanf 中用于输入 int_fast8_t 的 d 格式 |
SCNdFAST16 |
C99 | scanf 中用于输入 int_fast16_t 的 d 格式 |
SCNdFAST32 |
C99 | scanf 中用于输入 int_fast32_t 的 d 格式 |
SCNdFAST64 |
C99 | scanf 中用于输入 int_fast64_t 的 d 格式 |
SCNdLEAST8 |
C99 | scanf 中用于输入 int_least8_t 的 d 格式 |
SCNdLEAST16 |
C99 | scanf 中用于输入 int_least16_t 的 d 格式 |
SCNdLEAST32 |
C99 | scanf 中用于输入 int_least32_t 的 d 格式 |
SCNdLEAST64 |
C99 | scanf 中用于输入 int_least64_t 的 d 格式 |
SCNi8 |
C99 | scanf 中用于输入 int8_t 的 i 格式(有符号十进制) |
SCNi16 |
C99 | scanf 中用于输入 int16_t 的 i 格式 |
SCNi32 |
C99 | scanf 中用于输入 int32_t 的 i 格式 |
SCNi64 |
C99 | scanf 中用于输入 int64_t 的 i 格式 |
SCNiPTR |
C99 | scanf 中用于输入 intptr_t 的 i 格式 |
SCNiMAX |
C99 | scanf 中用于输入 intmax_t 的 i 格式 |
SCNiFAST8 |
C99 | scanf 中用于输入 int_fast8_t 的 i 格式 |
SCNiFAST16 |
C99 | scanf 中用于输入 int_fast16_t 的 i 格式 |
SCNiFAST32 |
C99 | scanf 中用于输入 int_fast32_t 的 i 格式 |
SCNiFAST64 |
C99 | scanf 中用于输入 int_fast64_t 的 i 格式 |
SCNiLEAST8 |
C99 | scanf 中用于输入 int_least8_t 的 i 格式 |
SCNiLEAST16 |
C99 | scanf 中用于输入 int_least16_t 的 i 格式 |
SCNiLEAST32 |
C99 | scanf 中用于输入 int_least32_t 的 i 格式 |
SCNiLEAST64 |
C99 | scanf 中用于输入 int_least64_t 的 i 格式 |
SCNu8 |
C99 | scanf 中用于输入 uint8_t 的 u 格式(无符号十进制) |
SCNu16 |
C99 | scanf 中用于输入 uint16_t 的 u 格式 |
SCNu32 |
C99 | scanf 中用于输入 uint32_t 的 u 格式 |
SCNu64 |
C99 | scanf 中用于输入 uint64_t 的 u 格式 |
SCNuPTR |
C99 | scanf 中用于输入 uintptr_t 的 u 格式 |
SCNuMAX |
C99 | scanf 中用于输入 uintmax_t 的 u 格式 |
SCNuFAST8 |
C99 | scanf 中用于输入 uint_fast8_t 的 u 格式 |
SCNuFAST16 |
C99 | scanf 中用于输入 uint_fast16_t 的 u 格式 |
SCNuFAST32 |
C99 | scanf 中用于输入 uint_fast32_t 的 u 格式 |
SCNuFAST64 |
C99 | scanf 中用于输入 uint_fast64_t 的 u 格式 |
SCNuLEAST8 |
C99 | scanf 中用于输入 uint_least8_t 的 u 格式 |
SCNuLEAST16 |
C99 | scanf 中用于输入 uint_least16_t 的 u 格式 |
SCNuLEAST32 |
C99 | scanf 中用于输入 uint_least32_t 的 u 格式 |
SCNuLEAST64 |
C99 | scanf 中用于输入 uint_least64_t 的 u 格式 |
SCNo8 |
C99 | scanf 中用于输入 uint8_t 的 o 格式(有符号八进制) |
SCNo16 |
C99 | scanf 中用于输入 uint16_t 的 o 格式 |
SCNo32 |
C99 | scanf 中用于输入 uint32_t 的 o 格式 |
SCNo64 |
C99 | scanf 中用于输入 uint64_t 的 o 格式 |
SCNoPTR |
C99 | scanf 中用于输入 uintptr_t 的 o 格式 |
SCNoMAX |
C99 | scanf 中用于输入 uintmax_t 的 o 格式 |
SCNoFAST8 |
C99 | scanf 中用于输入 uint_fast8_t 的 o 格式 |
SCNoFAST16 |
C99 | scanf 中用于输入 uint_fast16_t 的 o 格式 |
SCNoFAST32 |
C99 | scanf 中用于输入 uint_fast32_t 的 o 格式 |
SCNoFAST64 |
C99 | scanf 中用于输入 uint_fast64_t 的 o 格式 |
SCNoLEAST8 |
C99 | scanf 中用于输入 uint_least8_t 的 o 格式 |
SCNoLEAST16 |
C99 | scanf 中用于输入 uint_least16_t 的 o 格式 |
SCNoLEAST32 |
C99 | scanf 中用于输入 uint_least32_t 的 o 格式 |
SCNoLEAST64 |
C99 | scanf 中用于输入 uint_least64_t 的 o 格式 |
SCNx8 |
C99 | scanf 中用于输入 uint8_t 的 x 格式(有符号十六进制,小写) |
SCNx16 |
C99 | scanf 中用于输入 uint16_t 的 x 格式 |
SCNx32 |
C99 | scanf 中用于输入 uint32_t 的 x 格式 |
SCNx64 |
C99 | scanf 中用于输入 uint64_t 的 x 格式 |
SCNxPTR |
C99 | scanf 中用于输入 uintptr_t 的 x 格式 |
SCNxMAX |
C99 | scanf 中用于输入 uintmax_t 的 x 格式 |
SCNxFAST8 |
C99 | scanf 中用于输入 uint_fast8_t 的 x 格式 |
SCNxFAST16 |
C99 | scanf 中用于输入 uint_fast16_t 的 x 格式 |
SCNxFAST32 |
C99 | scanf 中用于输入 uint_fast32_t 的 x 格式 |
SCNxFAST64 |
C99 | scanf 中用于输入 uint_fast64_t 的 x 格式 |
SCNxLEAST8 |
C99 | scanf 中用于输入 uint_least8_t 的 x 格式 |
SCNxLEAST16 |
C99 | scanf 中用于输入 uint_least16_t 的 x 格式 |
SCNxLEAST32 |
C99 | scanf 中用于输入 uint_least32_t 的 x 格式 |
SCNxLEAST64 |
C99 | scanf 中用于输入 uint_least64_t 的 x 格式 |
C17 standard (ISO/IEC 9899:2018):
7.21.6.4 The scanf function (p: 236-237)
C11 standard (ISO/IEC 9899:2011):
7.21.6.4 The scanf function (p: 325)
C99 standard (ISO/IEC 9899:1999):
7.19.6.4 The scanf function (p: 290)
C89/C90 standard (ISO/IEC 9899:1990):
4.9.6.4 The scanf function