getch c语言

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

这是一个在控制台编程中非常常见但又有些特殊的函数。

getch c语言
(图片来源网络,侵删)

getch() 是什么?

getch() 是一个“非缓冲输入”函数,它的全称是 "get character"(获取字符)。

核心特点: 当程序调用 getch() 时,它会立即等待用户按下任意一个键,并且不需要用户按回车键(Enter),一旦用户按下键,getch() 就会立刻返回这个键的值,然后程序继续执行。

这个特性使得 getch() 非常适合制作游戏、菜单选择等需要即时响应的应用程序。


getch() 的工作原理(缓冲 vs. 非缓冲)

为了更好地理解 getch(),我们需要先了解两种输入方式:

getch c语言
(图片来源网络,侵删)

a) 缓冲输入

这是 C 语言标准输入(scanf, gets 等)的默认方式。

  • 工作流程

    1. 用户在键盘上输入字符。
    2. 字符被暂存到一个称为“输入缓冲区”或“行缓冲区”的内存区域。
    3. 当用户按下 回车键(Enter) 时,缓冲区中的内容被一次性发送给程序。
    4. scanfgets 等函数从缓冲区中读取数据。
  • 缺点

    • 用户必须按回车才能确认输入。
    • 如果缓冲区里有残留字符(比如上一次输入留下的),scanf 会直接读取它们,而不会等待新输入。

b) 非缓冲输入

getch() 采用的就是这种方式。

getch c语言
(图片来源网络,侵删)
  • 工作流程

    1. 程序调用 getch()
    2. 程序暂停,等待用户按键。
    3. 用户按下任意一个键(不需要回车)。
    4. getch() 立即获取这个键的值,并返回给程序。
    5. 程序继续执行。
  • 优点

    • 即时响应,无需按回车。
    • 可以捕获功能键(如 F1, F2)、方向键等特殊按键(需要额外处理)。

如何使用 getch()(重要:包含头文件)

getch() 并不是 C 语言标准库(ANSI C)的一部分,它是一个由特定编译器提供的扩展函数,最常见于 Turbo C++Borland C++ 编译器,因此在 Windows 平台的 MS-DOS/Windows 控制台环境中被广泛使用。

要使用 getch(),你必须包含头文件 <conio.h>

示例代码:

#include <stdio.h>
#include <conio.h> // 必须包含这个头文件
int main() {
    char ch;
    printf("请按任意一个键继续...\n");
    // 程序会在这里暂停,直到你按下键盘上的任意一个键
    ch = getch(); // 获取你按下的键,并存入变量 ch
    printf("\n你按下的键是: %c\n", ch);
    printf("该键的 ASCII 码是: %d\n", ch);
    return 0;
}

编译和运行:

  • 在支持 <conio.h> 的旧式编译器(如 Turbo C++)中,可以直接编译运行。
  • 在现代编译器(如 GCC、Clang、Visual Studio)中,默认可能不包含这个头文件,你需要特定的环境或库来支持它,在 Windows 上使用 MinGW 或 Visual Studio 的传统控制台项目。

getch() 的常见用途

  1. 暂停程序执行 这是最常见的用途,让用户看清屏幕上的输出后,按任意键继续。

    printf("程序执行完毕。");
    getch(); // 暂停,等待用户按键
  2. 即时菜单选择 不需要用户输入后按回车,直接按一个键就能触发相应功能。

    printf("请选择操作: \n");
    printf("1. 保存\n");
    printf("2. 加载\n");
    printf("3. 退出\n");
    char choice = getch();
    switch (choice) {
        case '1': printf("保存文件...\n"); break;
        case '2': printf("加载文件...\n"); break;
        case '3': printf("退出程序,\n"); break;
        default: printf("无效选择,\n"); break;
    }
  3. 游戏开发 在简单的控制台游戏中,用来捕获玩家的按键输入,如移动、跳跃等。

    // 伪代码
    while (game_is_running) {
        // ... 游戏逻辑 ...
        if (kbhit()) { // 检查是否有键被按下(另一个 conio.h 函数)
            char key = getch();
            if (key == 'w') {
                move_player_up();
            }
        }
    }

getch() 的相关函数

<conio.h> 头文件中还提供了一些与 getch() 相关的、非常有用的函数:

  • int getche(void);

    • 功能和 getch() 几乎一样,区别在于:getche() 会将用户按下的字符 “回显” 到屏幕上(即你能看到你按了什么键)。
    • getch() 是“get character echo”(获取字符并回显)。
  • int kbhit(void);

    • 这是一个“键盘点击检测”函数。
    • 不等待用户按键,而是立即检查是否有键被按下。
    • 如果有键被按下,它返回一个非零值(真);否则返回 0(假)。
    • 这个函数对于制作游戏循环非常有用,可以避免程序因等待输入而卡住。

    kbhit()getch() 结合使用的经典示例:

    #include <stdio.h>
    #include <conio.h>
    int main() {
        printf("按 'q' 键退出程序...\n");
        while (1) { // 无限循环
            if (kbhit()) { // 检查是否有按键
                char ch = getch(); // 获取按键
                if (ch == 'q' || ch == 'Q') {
                    printf("\n检测到退出指令,程序结束,\n");
                    break; // 退出循环
                }
            }
            // 在这里可以放置游戏的主逻辑或动画
            printf("."); // 模拟一些后台工作
            _sleep(100); // 暂停100毫秒 (Windows.h 中的函数)
        }
        return 0;
    }

跨平台问题与现代替代方案

由于 getch() 是非标准的,代码的可移植性很差,如果你想在现代的、跨平台的 C 项目中实现类似的功能,有以下几种替代方案:

Windows 平台(使用 Windows API)

如果你在 Windows 上开发,可以使用 <windows.h> 中的函数。

#include <stdio.h>
#include <windows.h> // 使用 Windows API
void my_getch() {
    // 清空输入缓冲区,防止旧输入干扰
    FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
    // 等待单个按键事件
    INPUT_RECORD record;
    DWORD count;
    do {
        ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &count);
    } while (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown);
    // 输出按下的字符(类似 getche)
    printf("%c", record.Event.KeyEvent.uChar.AsciiChar);
}
int main() {
    printf("按任意键继续...");
    my_getch();
    printf("\n你按下了键,\n");
    return 0;
}

Linux / macOS 平台(使用 termios)

在 Unix-like 系统上,可以通过修改终端的属性来实现非缓冲输入。

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
// 保存和恢复终端设置的辅助函数
void set_terminal_mode(int enable) {
    static struct termios oldt, newt;
    if (enable) {
        tcgetattr(STDIN_FILENO, &oldt); // 保存旧设置
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO); // 关闭规范模式和回显
        tcsetattr(STDIN_FILENO, TCSANOW, &newt); // 应用新设置
    } else {
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // 恢复旧设置
    }
}
char my_getch() {
    char ch;
    set_terminal_mode(1); // 设置为非缓冲模式
    ch = getchar();      // 读取一个字符
    set_terminal_mode(0); // 恢复为默认模式
    return ch;
}
int main() {
    printf("按任意键继续...");
    char ch = my_getch();
    printf("\n你按下了键: %c\n", ch);
    return 0;
}
特性 getch()
头文件 <conio.h> (非标准)
功能 从控制台获取一个字符,无需按回车
响应 非缓冲,立即响应。
回显 不回显(按下的字符不会显示在屏幕上)。
标准性 非标准,特定于旧式编译器(如 Turbo C)。
主要用途 暂停程序、即时菜单、游戏输入。
跨平台 ,在现代编译器中通常不可用。

对于学习 C 语言基础和了解控制台编程原理,getch() 是一个很好的例子,但在进行实际项目开发时,应优先考虑使用标准库或特定平台的 API 来实现跨平台的即时输入功能。

-- 展开阅读全文 --
头像
dede数据还原不了,问题出在哪?
« 上一篇 04-16
C语言中ifdef与ifndef有何区别?
下一篇 » 04-17

相关文章

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

目录[+]