C语言getchar()函数详解

getchar()是一个用来获取字符的函数

cpp 复制代码
#include <stdio.h>
int getchar(void);    // 功能:从标准输入(键盘)读取下一个可用的字符

一、讲解

当敲键盘的时候,数据不是直接被getchar()获取,而是先进入了一个"缓冲区(buffer)"

过程:

  1. 输入a,b,c...时,getchar()处于一个阻塞状态(没有进行),它在等待一个信号(通常是回车)

  2. 当按下回车键时:

    1. 回车本身是一个字符(\n,换行)

    2. 按下回车不仅把\n放到了缓冲区,还相当于在上面说的信号,告诉getchar(),我的输入已经结束了,可以进行读取了

    3. getchar()开始运行:到缓冲区里面,但是只拿走一个字符。getchar()一次只取一个字符。如果你输入了abc然后回车,缓冲区里面其实有4个东西:a,b,c,\n。第一个调用getchar()拿走了a,剩下的b,c,\n还在缓冲区里面排队,下一次调用会直接拿走b,不需要再敲键盘。

二、为什么返回值是int,不是char

函数的原型是int getchar(void)

原因:

  1. ASCII码:返回的是字符对应的ASCII,比如A对应65

  2. 处理错误(EOF):这是最重要的原因:

    1. char类型的范围通常是0-255(unsigned)或-128-127(signed)

    2. 如果读取失败,或读取到文件末尾,getchar()需要返回一个特殊的标志,叫做EOF(End Of File)

    3. 在标准库中,EOF通常被定义为-1

    4. 有些编译器下的char是无法表示-1的(比如unsigned char),或者-1恰好代表某个特殊字符

    5. 为了正确地把"正常字符"和"错误标志EOF"区分开,C语言决定使用范围更大的int来接受返回值

cpp 复制代码
int c; // 千万不要写 char c;
c = getchar();
if (c != EOF) {
    // ...
}

三、注意:scanf后面的getchar会失效

现象:先用scanf读个数字,想再用getchar读个字符,结果程序直接跳过了getchar,不让输入了。

cpp 复制代码
#include <stdio.h>
int main(){
        int num;
        char ch;
        
        printf("请输入一个数字:");
        scanf("%d", &num); 
        
        printf("请输入一个字符:");
        ch = getchar(); // 这一行仿佛没执行一样!
        
        printf("你输入了:%d 和 %c\n", num, ch);
        return 0;
}

假如输入了2,然后按回车:

  1. 缓冲区里是2 \n

  2. scanf读取了2,但是留下了\n在缓冲区。

  3. 轮到getchar(),直接读取了缓冲区里的\n

解决办法

scanf后面加一个无用的getchar(),专门用来获取遗留的\n

cpp 复制代码
#include <stdio.h>
int main(){
        int num;
        char ch;
        
        printf("请输入一个数字:");
        scanf("%d", &num); 
        getchar(); // 专门吃掉缓冲区的 \n 
        
        printf("请输入一个字符:");
        ch = getchar(); // 这一行仿佛没执行一样!
        
        printf("你输入了:%d 和 %c\n", num, ch);
        return 0;
}

常见用法

1. 连续读取直到换行

如果想实现类似getsfgets(连续读取)的功能:

cpp 复制代码
#include <stdio.h>
int main(){
        int c;
        printf("请输入一行文字:\n");
        
        // 只要没读到回车,也没读到文件结束,就一直读
        while ((c = getchar()) != '\n' && c != EOF) {
            printf("读取了字符: %c (ASCII: %d)\n", c, c);
        }
}
2. 清空缓冲区

有时候不知道缓冲区里面剩余多少字符,我想全部清空,为下一次输入做准备

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

int main() {
    int password;
    int confirm; 

    // 1. 输入密码
    printf("请输入数字密码: ");
    scanf("%d", &password); 

    // ==========================================
    // 【关键操作】清空缓冲区
    // 循环不断地吃掉字符,直到吃到回车符(\n)为止
    // 吃到回车符,说明这一行结束了,循环停止
    while (getchar() != '\n'); 
    // ==========================================

    // 2. 确认保存
    printf("确认保存吗?(Y/N): ");
    confirm = getchar(); // 这次它必须等你敲键盘了,因为缓冲区空了

    // 3. 打印结果
    if (confirm == 'Y' || confirm == 'y') {
        printf("保存成功!\n");
    } else {
        printf("取消保存。\n");
    }

    return 0;
}

⚠ 不要用fflush(stdin)去清空输入流!!!

while (getchar() != '\n');才是正解!!!

相关推荐
黎雁·泠崖2 小时前
Java 方法栈帧深度解析:从 JIT 汇编视角,打通 C 与 Java 底层逻辑
java·c语言·汇编
hqyjzsb2 小时前
2026年AI证书选择攻略:当“平台绑定”与“能力通用”冲突,如何破局?
大数据·c语言·人工智能·信息可视化·职场和发展·excel·学习方法
天赐学c语言2 小时前
12.30 - 合并区间 && C++中class和C语言中struct的区别
c语言·c++·算法·leecode
Albert Edison2 小时前
【MySQL】使用C/C++语言连接数据库
c语言·数据库·mysql
CodeOfCC3 小时前
c语言 封装跨平台条件变量头文件
c语言
_Voosk3 小时前
macOS Xcode C++程序设置相对路径根目录
c语言·c++·xcode·swift
小刘爱玩单片机4 小时前
【stm32简单外设篇】- LCD1602A
c语言·stm32·单片机·嵌入式硬件
巧克力味的桃子4 小时前
让程序在读取到整数0时就终止循环
c语言·算法
C++ 老炮儿的技术栈5 小时前
时序数据库 相对于关系型数据库,有什么区别
c语言·开发语言·c++·机器人·时序数据库·visual studio