C语言flushkey

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

flushkey 函数并不是标准C库(ANSI C/C99/C11等)的一部分,它是一个非标准、平台特定的函数,主要用于某些特定的DOS环境。

C语言flushkey
(图片来源网络,侵删)

在Windows、Linux或macOS等现代操作系统上,你无法直接使用 #include <some_header.h> 然后调用 flushkey()

下面我将从几个方面为你详细解释这个函数:


flushkey 的作用和来源

flushkey 主要来源于 Turbo CBorland C++ 这两个经典的DOS编译器,它的作用非常明确:

清空键盘缓冲区。

C语言flushkey
(图片来源网络,侵删)

键盘缓冲区是一个内存区域,用于存储用户按下的键,即使你的程序还没有准备好读取它们。flushkey() 会强制清空这个缓冲区,丢弃其中所有尚未被程序处理的按键。

典型使用场景: 当你的程序需要等待用户输入一个特定的、不受干扰的字符时,为了避免用户之前不小心按下的键影响程序的判断,你可以在提示用户输入之前调用 flushkey()


在DOS环境下的使用(Turbo C/Borland C++)

如果你正在使用一个古老的DOS环境(比如通过DOSBox运行Turbo C),你可以这样使用它:

#include <stdio.h>
#include <conio.h> // 包含 flushkey 函数的头文件
int main() {
    printf("程序即将开始,请准备好按任意键...");
    getch(); // 等待用户按下一个键(不显示)
    printf("\n已清除之前的所有按键,现在请按 'Y' 或 'N' 来确认,\n");
    // 在等待用户确认前,清空键盘缓冲区
    // 这样即使用户之前按了Y或N,也不会被误读
    flushkey();
    char choice;
    choice = getch();
    if (choice == 'y' || choice == 'Y') {
        printf("\n你选择了 Yes,\n");
    } else if (choice == 'n' || choice == 'N') {
        printf("\n你选择了 No,\n");
    } else {
        printf("\n无效的输入,\n");
    }
    return 0;
}

代码解释:

C语言flushkey
(图片来源网络,侵删)
  1. #include <conio.h>:这个头文件是Turbo C/Borland C++特有的,包含了像 getch()(从键盘获取一个字符,不回显)和 flushkey() 这样的控制台输入/输出函数。
  2. flushkey():在提示用户输入 'Y' 或 'N' 之前调用,确保缓冲区是干净的,防止历史输入干扰本次操作。

在现代操作系统(Windows, Linux, macOS)上的替代方案

由于 flushkey() 不可用,我们需要使用现代操作系统提供的方法来实现相同的功能,核心思想都是清空输入缓冲区

A. 在 Windows 平台

在Windows控制台程序中,你可以使用 <conio.h>(通常是编译器自带的,如MinGW)中的 kbhit()getch() 组合来模拟,或者更彻底地使用 <windows.h> 中的函数。

使用 kbhit()getch() 循环清空(推荐)

这是最常见、最简单的方法,不依赖于特定的Windows API,可移植性较好(只要你的编译器支持 conio.h)。

#include <stdio.h>
#include <conio.h> // Windows下(如MinGW)通常支持这个头文件
void clear_input_buffer() {
    // 当键盘缓冲区中有字符时
    while (kbhit()) {
        // 读取并丢弃该字符
        getch();
    }
}
int main() {
    printf("请按一些键,然后按回车继续...");
    getchar(); // 等待用户按回车,期间用户可能按了很多其他键
    printf("\n正在清空键盘缓冲区...\n");
    clear_input_buffer();
    printf("现在请按 'A' 键:");
    char c = getch();
    printf("\n你按下了: %c\n", c);
    return 0;
}

使用Windows API(更底层)

如果你想直接调用Windows系统功能,可以使用 <windows.h>

#include <stdio.h>
#include <windows.h> // Windows API头文件
void flush_windows_console_input() {
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD numEvents;
    INPUT_RECORD inputRecord;
    // 获取输入缓冲区中的事件数量
    GetNumberOfConsoleInputEvents(hStdin, &numEvents);
    // 如果有事件,则将它们全部从缓冲区中移除(读取并丢弃)
    if (numEvents > 0) {
        // ReadConsoleInput 会消耗掉缓冲区中的事件
        // 我们只需要循环读取直到没有事件为止
        while (numEvents--) {
            ReadConsoleInput(hStdin, &inputRecord, 1, &numEvents);
        }
    }
}
int main() {
    printf("请按一些键,然后按回车继续...");
    getchar(); // 等待回车
    printf("\n正在清空键盘缓冲区...\n");
    flush_windows_console_input();
    printf("现在请按 'B' 键:");
    // 使用 _getch() 或 _kbhit() 需要 <conio.h>
    // 这里用另一种方式等待
    system("pause > nul"); // 一个笨办法,但能演示
    // 更好的方法是循环等待特定按键,这里省略
    return 0;
}

B. 在 Linux 和 macOS 平台

在类Unix系统中,标准C库没有直接清空键盘缓冲区的函数,因为输入通常是行缓冲的(按回车才提交),但如果你想实现类似功能,可以读取标准输入直到缓冲区为空。

最常用的方法是使用 select() 系统调用来检查输入是否可读,然后使用 read() 来读取并丢弃。

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/select.h>
// 设置终端为原始模式,以便逐个字符读取
void set_terminal_mode_raw() {
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~(ICANON | ECHO); // 关闭规范模式和回显
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
// 恢复终端为标准模式
void set_terminal_mode_standard() {
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag |= (ICANON | ECHO); // 开启规范模式和回显
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
// 清空标准输入缓冲区
void clear_stdin_buffer() {
    fd_set fds;
    struct timeval tv = {0, 0}; // 立即返回,不等待
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    // 检查是否有数据可读
    if (select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv) > 0) {
        // 有数据,则读取并丢弃
        char ch;
        while (read(STDIN_FILENO, &ch, 1) > 0) {
            // 不断读取直到缓冲区为空
        }
    }
}
int main() {
    set_terminal_mode_raw();
    printf("请按一些键,然后按 'q' 退出...\n");
    char c;
    while (1) {
        read(STDIN_FILENO, &c, 1);
        if (c == 'q') {
            break;
        }
    }
    printf("\n正在清空键盘缓冲区...\n");
    clear_stdin_buffer();
    printf("现在请按 'r' 键:");
    while (1) {
        read(STDIN_FILENO, &c, 1);
        if (c == 'r') {
            printf("\n你按下了: r\n");
            break;
        }
    }
    set_terminal_mode_standard();
    return 0;
}

注意: Linux/macOS的实现比Windows复杂,因为它涉及到终端模式的设置,而不仅仅是简单的缓冲区操作。


特性 flushkey() (DOS/Turbo C) 现代替代方案 (Windows) 现代替代方案 (Linux/macOS)
标准性 非标准,平台特定 非标准,但使用标准API 非标准,使用系统调用
作用 清空键盘缓冲区 清空键盘缓冲区 清空标准输入缓冲区
头文件 <conio.h> <conio.h><windows.h> <unistd.h>, <termios.h>, <sys/select.h>
方法 直接调用函数 while(kbhit()) getch();ReadConsoleInput select() + read() 循环
关键点 简单直接,但已过时 方法简单,兼容性好 需要处理终端模式,较复杂

flushkey 是一个历史遗留函数,如果你正在维护旧的DOS代码,你可能会遇到它,在新的C语言项目中,你应该根据你运行的操作系统,采用上面提到的现代替代方案来实现“清空键盘输入”的功能,对于跨平台需求,推荐使用 kbhit()getch() 的组合,因为它在Windows(通过MinGW等)和许多类Unix系统上都能工作。

-- 展开阅读全文 --
头像
织梦不用手机站,如何适配移动端?
« 上一篇 04-17
c语言 sound
下一篇 » 04-17

相关文章

取消
微信二维码
支付宝二维码

目录[+]