国际访客建议访问 Primers 编程伙伴 国际版站点 > C 教程 > scanf 以获得更好的体验。

# C 语言标准库函数 scanf

在头文件 stdio.h 中定义。
/*********************************************
 * @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

# 格式占位符

格式占位符以 %[*][宽度][长度修饰]说明符 的形式出现。

  • * 是赋值抑制符,表示这部分输入不赋值给接收参数

  • 宽度:输入的最大字符数

  • 长度修饰:表示类型长度,例如 %dint,而 %ldlong

说明符 !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] 表示读取连续的多个 abc,遇到其它字符时停止匹配

  • %[^abc] 表示读取连续的多个除了 abc 以外的字符,遇到 abc时停止匹配

  • %[^\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_td 格式(有符号十进制)
SCNd16 C99 scanf 中用于输入 int16_td 格式
SCNd32 C99 scanf 中用于输入 int32_td 格式
SCNd64 C99 scanf 中用于输入 int64_td 格式
SCNdPTR C99 scanf 中用于输入 intptr_td 格式
SCNdMAX C99 scanf 中用于输入 intmax_td 格式
SCNdFAST8 C99 scanf 中用于输入 int_fast8_td 格式
SCNdFAST16 C99 scanf 中用于输入 int_fast16_td 格式
SCNdFAST32 C99 scanf 中用于输入 int_fast32_td 格式
SCNdFAST64 C99 scanf 中用于输入 int_fast64_td 格式
SCNdLEAST8 C99 scanf 中用于输入 int_least8_td 格式
SCNdLEAST16 C99 scanf 中用于输入 int_least16_td 格式
SCNdLEAST32 C99 scanf 中用于输入 int_least32_td 格式
SCNdLEAST64 C99 scanf 中用于输入 int_least64_td 格式
SCNi8 C99 scanf 中用于输入 int8_ti 格式(有符号十进制)
SCNi16 C99 scanf 中用于输入 int16_ti 格式
SCNi32 C99 scanf 中用于输入 int32_ti 格式
SCNi64 C99 scanf 中用于输入 int64_ti 格式
SCNiPTR C99 scanf 中用于输入 intptr_ti 格式
SCNiMAX C99 scanf 中用于输入 intmax_ti 格式
SCNiFAST8 C99 scanf 中用于输入 int_fast8_ti 格式
SCNiFAST16 C99 scanf 中用于输入 int_fast16_ti 格式
SCNiFAST32 C99 scanf 中用于输入 int_fast32_ti 格式
SCNiFAST64 C99 scanf 中用于输入 int_fast64_ti 格式
SCNiLEAST8 C99 scanf 中用于输入 int_least8_ti 格式
SCNiLEAST16 C99 scanf 中用于输入 int_least16_ti 格式
SCNiLEAST32 C99 scanf 中用于输入 int_least32_ti 格式
SCNiLEAST64 C99 scanf 中用于输入 int_least64_ti 格式
SCNu8 C99 scanf 中用于输入 uint8_tu 格式(无符号十进制)
SCNu16 C99 scanf 中用于输入 uint16_tu 格式
SCNu32 C99 scanf 中用于输入 uint32_tu 格式
SCNu64 C99 scanf 中用于输入 uint64_tu 格式
SCNuPTR C99 scanf 中用于输入 uintptr_tu 格式
SCNuMAX C99 scanf 中用于输入 uintmax_tu 格式
SCNuFAST8 C99 scanf 中用于输入 uint_fast8_tu 格式
SCNuFAST16 C99 scanf 中用于输入 uint_fast16_tu 格式
SCNuFAST32 C99 scanf 中用于输入 uint_fast32_tu 格式
SCNuFAST64 C99 scanf 中用于输入 uint_fast64_tu 格式
SCNuLEAST8 C99 scanf 中用于输入 uint_least8_tu 格式
SCNuLEAST16 C99 scanf 中用于输入 uint_least16_tu 格式
SCNuLEAST32 C99 scanf 中用于输入 uint_least32_tu 格式
SCNuLEAST64 C99 scanf 中用于输入 uint_least64_tu 格式
SCNo8 C99 scanf 中用于输入 uint8_to 格式(有符号八进制)
SCNo16 C99 scanf 中用于输入 uint16_to 格式
SCNo32 C99 scanf 中用于输入 uint32_to 格式
SCNo64 C99 scanf 中用于输入 uint64_to 格式
SCNoPTR C99 scanf 中用于输入 uintptr_to 格式
SCNoMAX C99 scanf 中用于输入 uintmax_to 格式
SCNoFAST8 C99 scanf 中用于输入 uint_fast8_to 格式
SCNoFAST16 C99 scanf 中用于输入 uint_fast16_to 格式
SCNoFAST32 C99 scanf 中用于输入 uint_fast32_to 格式
SCNoFAST64 C99 scanf 中用于输入 uint_fast64_to 格式
SCNoLEAST8 C99 scanf 中用于输入 uint_least8_to 格式
SCNoLEAST16 C99 scanf 中用于输入 uint_least16_to 格式
SCNoLEAST32 C99 scanf 中用于输入 uint_least32_to 格式
SCNoLEAST64 C99 scanf 中用于输入 uint_least64_to 格式
SCNx8 C99 scanf 中用于输入 uint8_tx 格式(有符号十六进制,小写)
SCNx16 C99 scanf 中用于输入 uint16_tx 格式
SCNx32 C99 scanf 中用于输入 uint32_tx 格式
SCNx64 C99 scanf 中用于输入 uint64_tx 格式
SCNxPTR C99 scanf 中用于输入 uintptr_tx 格式
SCNxMAX C99 scanf 中用于输入 uintmax_tx 格式
SCNxFAST8 C99 scanf 中用于输入 uint_fast8_tx 格式
SCNxFAST16 C99 scanf 中用于输入 uint_fast16_tx 格式
SCNxFAST32 C99 scanf 中用于输入 uint_fast32_tx 格式
SCNxFAST64 C99 scanf 中用于输入 uint_fast64_tx 格式
SCNxLEAST8 C99 scanf 中用于输入 uint_least8_tx 格式
SCNxLEAST16 C99 scanf 中用于输入 uint_least16_tx 格式
SCNxLEAST32 C99 scanf 中用于输入 uint_least32_tx 格式
SCNxLEAST64 C99 scanf 中用于输入 uint_least64_tx 格式

# 推荐阅读

# 参考标准

  • 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

本文 更新于: 2025-11-27 09:38:10 创建于: 2025-11-27 09:38:10