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. 连续读取直到换行

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

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');才是正解!!!

相关推荐
wuminyu1 小时前
JMM学习总结:深入理解happens-before关系
java·linux·c语言·jvm·c++
Zwawa3 小时前
让电机走到指定位置:编码器位置环 PID
c语言·单片机·嵌入式
fensnote4 小时前
西门子 S7 PLC 内部寄存器读写 Demo(C 语言)
c语言·开发语言
Logic1017 小时前
C语言/数据结构位运算题解:异或XOR找出被挑选一次的果子编号——只出现一次的数字
c语言·数据结构·算法·数组·位运算·时间复杂度·空间复杂度
dear_bi_MyOnly7 小时前
栈和队列:从原理到应用全解析
c语言·开发语言·c++·学习·分类
从小白到软工8 小时前
4-3 项目-学生成绩管理系统(上)
c语言·开发语言·数据结构·经验分享·ai编程
Code_Solitude9 小时前
c语言:指针(3)+冒泡排序
java·c语言·算法
巴巴媛66610 小时前
【Debug1】程序死机,while(1)循环,怎么办?
c语言·笔记·stm32·嵌入式硬件·bug
Lxx_Zw10 小时前
PID 用顺了,然后呢:增强手术与前馈
c语言·stm32·单片机·嵌入式硬件
BeiGuTing_code10 小时前
C链表基础(二)有视频模拟!!!
c语言·链表·音视频