#C 语言标准库函数 scanf
/*********************************************
* @brief 从标准输入中获取输入
* @param format 格式字符串
* @param ... 可变长度参数,要打印的变量
* @return 打印的字符数量
********************************************/
int scanf(const char* restrict format, ...);
说明
从标准输入中获取输入。
参数
format
- 格式化字符串,指向以空字符(\0
)结尾的字符串指针,指定如何解释数据- 普通字符直接输入,如果不匹配则导致失败
- 转义字符按照转义打印
- 空格字符将读取输入的所有连续空白字符,包括空格,
\n
,\t
等 - 以
%
开头的 格式占位符,按照指定格式读取输入并写入后续相应位置的参数
...
- 可变长度参数,为接收输入的地址,需要与format
参数中的格式占位符一一对应
返回值
- 成功分配的接收参数的数量
- 分配第一个接收参数之前发生匹配失败时返回 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
说明符 | 说明 | 参数类型 | 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* | - | - | - | - | - |
匹配字符集合 [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_least816_t 的 d 格式 |
SCNdLEAST32 | C99 | scanf 中用于输入 int_least832_t 的 d 格式 |
SCNdLEAST64 | C99 | scanf 中用于输入 int_least864_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_least816_t 的 i 格式 |
SCNiLEAST32 | C99 | scanf 中用于输入 int_least832_t 的 i 格式 |
SCNiLEAST64 | C99 | scanf 中用于输入 int_least864_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_least816_t 的 u 格式 |
SCNuLEAST32 | C99 | scanf 中用于输入 uint_least832_t 的 u 格式 |
SCNuLEAST64 | C99 | scanf 中用于输入 uint_least864_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_least816_t 的 o 格式 |
SCNoLEAST32 | C99 | scanf 中用于输入 uint_least832_t 的 o 格式 |
SCNoLEAST64 | C99 | scanf 中用于输入 uint_least864_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_least816_t 的 x 格式 |
SCNxLEAST32 | C99 | scanf 中用于输入 uint_least832_t 的 x 格式 |
SCNxLEAST64 | C99 | scanf 中用于输入 uint_least864_t 的 x 格式 |