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 天前
C语言内存函数
c语言·后端
norlan_jame4 天前
C-PHY与D-PHY差异
c语言·开发语言
czy87874754 天前
除了结构体之外,C语言中还有哪些其他方式可以模拟C++的面向对象编程特性
c语言
m0_531237174 天前
C语言-数组练习进阶
c语言·开发语言·算法
Z9fish4 天前
sse哈工大C语言编程练习23
c语言·数据结构·算法
代码无bug抓狂人4 天前
C语言之单词方阵——深搜(很好的深搜例题)
c语言·开发语言·算法·深度优先
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习
枫叶丹44 天前
【Qt开发】Qt界面优化(七)-> Qt样式表(QSS) 样式属性
c语言·开发语言·c++·qt
with-the-flow4 天前
从数学底层的底层原理来讲 random 的函数是怎么实现的
c语言·python·算法
Sunsets_Red4 天前
P8277 [USACO22OPEN] Up Down Subsequence P 题解
c语言·c++·算法·c#·学习方法·洛谷·信息学竞赛