【09】C语言中的格式输入函数scanf()详解

【09】C语言中的格式输入函数scanf()详解


文章目录

  • [1. 基本用法](#1. 基本用法)
  • [2. 格式说明符详解](#2. 格式说明符详解)
  • [3. 高级用法](#3. 高级用法)
    • [3.1 宽度限定符](#3.1 宽度限定符)
    • [3.2 跳过某些输入](#3.2 跳过某些输入)
    • [3.3 扫描集](#3.3 扫描集)
  • [4. 常见问题与注意事项](#4. 常见问题与注意事项)
    • [4.1 缓冲区问题](#4.1 缓冲区问题)
    • [4.2 字符串输入限制](#4.2 字符串输入限制)
    • [4.3 输入验证](#4.3 输入验证)
    • [4.4 综合代码示例](#4.4 综合代码示例)

scanf()是C语言标准库中最常用的输入函数之一,它允许从标准输入(通常是键盘)按照指定格式读取数据。下面我将全面讲解这个函数的使用方法和注意事项。

1. 基本用法

基本语法

c 复制代码
int scanf(const char *format, ...);
  • 返回值:成功读取的数据项个数,如果失败则返回EOF(通常是-1)
  • format参数:格式控制字符串,指定输入数据的格式
  • ...:可变参数列表,是需要读取的变量地址

要点须知:

  1. 始终检查返回值:确保所有预期的数据都被成功读取
  2. 注意缓冲区问题:特别是混合使用不同格式说明符时
  3. 限制输入长度:防止缓冲区溢出,尤其是字符串输入
  4. 考虑使用更安全的替代方案 :如fgets()+sscanf()
  5. 处理无效输入:提供错误恢复机制

代码示例

c 复制代码
#include <stdio.h>

int main() {
    // 设置控制台为GBK编码(Windows中文默认编码)
    SetConsoleOutputCP(936); 
    int age;
    float height;
    char name[50];
    
    printf("请输入您的年龄、身高和姓名:");
    scanf("%d %f %s", &age, &height, name);
    
    printf("年龄:%d,身高:%.2f,姓名:%s\n", age, height, name);
    
    return 0;
}

执行效果:

请输入您的年龄、身高和姓名:18 180.5 frank

年龄:18,身高:180.50,姓名:frank


2. 格式说明符详解

格式符 说明 示例
%d 读取十进制整数 scanf("%d", &num);
%i 读取整数(可识别八进制/十六进制前缀) scanf("%i", &num);
%u 读取无符号十进制整数 scanf("%u", &num);
%f 读取浮点数 scanf("%f", &fnum);
%lf 读取双精度浮点数 scanf("%lf", &dnum);
%c 读取单个字符 scanf("%c", &ch);
%s 读取字符串(不包含空格) scanf("%s", str);
%x 读取十六进制整数 scanf("%x", &hex);
%o 读取八进制整数 scanf("%o", &oct);
%% 读取百分号 scanf("%%");

3. 高级用法

3.1 宽度限定符

可以指定读取的最大字符数:

c 复制代码
char str[10];
scanf("%9s", str);  // 最多读取9个字符,保留1个给'\0'

3.2 跳过某些输入

使用*可以跳过某些输入项:

c 复制代码
int year, month;
scanf("%d-%*d-%d", &year, &month);  // 输入"2023-05-15"会跳过中间的05

3.3 扫描集

使用%[ ]可以指定接受的字符集:

c 复制代码
char vowels[10];
scanf("%[aeiou]", vowels);  // 只读取元音字母

反向扫描集(使用^):

c 复制代码
char no_space[50];
scanf("%[^\n]", no_space);  // 读取直到换行符

4. 常见问题与注意事项

4.1 缓冲区问题

c 复制代码
int num;
char ch;

scanf("%d", &num);    // 输入数字后按回车
scanf("%c", &ch);     // 会读取之前输入的回车符

解决方案

  1. %c前加空格:

    c 复制代码
    scanf(" %c", &ch);  // 空格会跳过空白字符
  2. 使用getchar()清空缓冲区


4.2 字符串输入限制

%s会读取到第一个空白字符(空格、制表符、换行符)为止:

c 复制代码
char name[20];
scanf("%s", name);  // 输入"John Doe"只会读取"John"

解决方案

c 复制代码
scanf("%[^\n]", name);  // 读取整行(不包括换行符)
// 或使用fgets()
fgets(name, sizeof(name), stdin);

4.3 输入验证

scanf()不会检查输入是否匹配变量类型:

c 复制代码
int num;
scanf("%d", &num);  // 如果输入"abc",num不会被赋值

解决方案

c 复制代码
if (scanf("%d", &num) != 1) {
    printf("输入无效!\n");
    while(getchar() != '\n');  // 清空缓冲区
}

安全替代方案

由于scanf()存在缓冲区溢出风险,推荐使用:

c 复制代码
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%d", &num);  // 从字符串解析

4.4 综合代码示例

c 复制代码
#include <stdio.h>

int main() {
    int id, age;
    char name[50];
    float score;
    
    printf("请输入学生信息(ID 年龄 姓名 分数):");
    
    // 使用fgets+sscanf更安全
    char input[100];
    fgets(input, sizeof(input), stdin);
    
    if (sscanf(input, "%d %d %49s %f", &id, &age, name, &score) != 4) {
        printf("输入格式错误!\n");
        return 1;
    }
    
    printf("学生信息:\n");
    printf("ID:%d\n", id);
    printf("姓名:%s\n", name);
    printf("年龄:%d\n", age);
    printf("分数:%.2f\n", score);
    
    return 0;
}
相关推荐
初学小白...3 小时前
实现Runnable接口
java·开发语言
Bruce-li__3 小时前
CI/CD流水线全解析:从概念到实践,结合Python项目实战
开发语言·python·ci/cd
JustNow_Man4 小时前
【Cline】插件中clinerules的实现逻辑分析
开发语言·前端·javascript
hope_wisdom4 小时前
C/C++数据结构之用链表实现栈
c语言·数据结构·c++·链表·
ceclar1234 小时前
C++容器forward_list
开发语言·c++·list
夏玉林的学习之路5 小时前
Anaconda的常用指令
开发语言·windows·python
m0_748233645 小时前
【类与对象(中)】C++类默认成员函数全解析
开发语言·c++·算法
郝学胜-神的一滴5 小时前
使用 Python 元类与属性实现惰性加载:Effective Python 第47条
linux·服务器·开发语言·python
GilgameshJSS5 小时前
STM32H743-ARM例程30-Modbus
c语言·arm开发·stm32·单片机·嵌入式硬件