C 语言 kbhit()

2024年8月28日 | 阅读 7 分钟

在本文中,我们将讨论 C 语言中的 **kbhit() 函数**,并附带示例、优点和缺点。

kbhit() 函数 不存在于 **C 标准库** 中。不过,它经常在 **Windows 系统** 上使用,用于检查键盘按键是否已被按下。您可以使用一个 **程序** 来查看键盘缓冲区中是否有等待读取的按键,而不会阻止程序的运行。此函数经常用于需要即时用户输入且不等待用户按下 **回车键** 的交互式基于控制台的程序或游戏。

由于 **kbhit() 函数** 不是 **默认 C 库** 的一部分,因此并非所有平台都可能支持它。如果需要跨平台键盘输入,可以使用平台特定的方法来管理输入事件,或者使用 **ncurses** 等库。

kbhit() 函数 确定按键是否已被按下。您必须包含 **conio.h** 头文件才能使用 **'kbhit' 函数**。当按键被 **按下** 时,将返回 1,否则返回 ****。

程序

让我们看一个程序来理解 C 语言中 **kbhit() 函数** 的用法。

输出

Enter key ESC to exit
You have entered: i
You have entered: P
You have entered: S
You have entered: w
You have entered: 7
You have entered: /
You have entered: *
You have entered: +

说明

  • #**include <stdio.h>:此行包含 **标准输入/输出 (stdio)** 头文件,它提供了输入和输出操作的函数,例如 **printf**。
  • #include <conio.h>: 此行包含 **conio.h** 头文件,它不是 **标准 C 库头文件**。它特定于 Windows,并提供 **kbhit()** 和 **getch()** 等函数,用于在不等待回车键的情况下处理键盘输入。
  • 它仅限于 Windows,并提供 **getch()** 和 **kbhit()** 例程,用于在不等待 **回车键** 的情况下处理键盘输入。
  • int main()...: 任何 C 程序的 **main 函数** 都是其 **入口点**。程序执行从这里开始。
  • char ch;: 此行声明 **char 类型** 变量 **ch**,它将用于存储用户输入(单个字符)。
  • 使用 **printf() 函数,行 **printf("Enter key ESC to exit");** 在屏幕上打印消息 **"Enter key ESC to exit"**。用户可以按 **ESC** 键退出程序,或输入任何键继续。
  • while (1) ...: 由于条件是 **1**,它永远是 **,这个 **while 循环 永远不会结束(无限运行)。一旦遇到 **break 语句,循环就会停止。
  • If (kbhit()): 使用 **conio.h** 中的 **kbhit() 函数,此行在 **循环 中检查按键事件。如果按键被 **按下 并且准备从键盘缓冲区读取,则 kbhit() 函数返回非零结果(真)。
  • Ch = getch();: 如果按下了某个键(即 kbhit() 返回真),则此行使用 **getch() 函数 从键盘缓冲区读取单个字符。**getch() 函数** 不等待按下 **回车键,它直接读取按下的键并返回用户的 **ASCII 值**。
  • 如果 **字符 ch** 等于 **ESC 键的 ASCII 值 (27),则此行将中断。在许多程序中,**ESC 键 通常用作 **退出键。如果用户按下 **ESC 键,程序将退出 **循环 并使用 **break 语句 结束,从而使条件为真。
  • printf ("You have entered: %c," "ch"): 即使用户没有使用 **ESC 键(即循环未中断),此行也会运行。使用 printf() 函数打印用户输入的字符(存储在 **ch** 中)以及短语 **"You have entered:"**。
  • Return 0; 此行标志着 main() 函数的结束,并在 while 循环之后使程序返回 0。操作系统通常将返回结果 0 报告为成功的程序执行。
  • 请记住,**conio.h 头文件 仅限于 **Windows,并且不是 **标准 C 库 的一部分。如果您打算编写跨平台程序,请考虑使用 **ncurses 等库以平台无关的方式处理键盘输入。

复杂度分析

C 程序提供易于理解的 **时间复杂度 和相对较低的 **空间复杂度**。

时间复杂度

  • printf("Enter key ESC to exit") 语句 具有 **O(1) 时间复杂度,因为它只执行一次简单的输出操作。
  • 当按下 **ESC 键(ASCII 值 27) 时,**while (1)** 循环开始无限运行,并以 **break 语句 结束。由于循环内没有与输入大小成比例的操作,因此循环的时间复杂度被视为 **O(1)**。
  • 由于无限循环无法执行任何与输入大小成比例的操作,因此程序的总体 **时间复杂度 为 **O(1)**。

空间复杂度

  • 语句 **char ch;** 声明了一个名为 **ch** 的单个 char 类型变量,它使用的内存量是固定的,与输入大小无关。因此,此变量的 **空间复杂度 为 **O(1)**。
  • 由于它们不依赖于输入大小,因此传递给 **printf()** 函数的固定大小的消息字符串,例如 **"You have entered:"** 和 **"Enter key ESC to exit"**,同样具有 **O(1) 空间复杂度**。
  • **conio.h** 中的 **getch()** 和 **kbhit()** 例程需要一些内部内存来管理键盘缓冲区和状态。然而,这种内存使用是恒定的,并且不随输入量增加,这使得这些函数具有 **O(1) 空间复杂度**。
  • 由于所有声明的变量和函数调用都具有固定的内存需求,这些需求不会随 **输入大小 而改变,因此程序的总体空间复杂度为 **O(1)**。

优点

C 语言中的 **kbhit() 函数** 有多种优点。C 语言中 kbhit() 函数的一些主要优点如下:

**非阻塞键盘输入:** **kbhit() 函数 的主要优点之一是它允许您在不阻塞系统执行的情况下检查键盘输入。与其他 **输入函数(如 **scanf()** 和 **getchar()**)不同,kbhit() 即使没有按下任何键也能快速返回结果,这使其适用于交互式基于控制台的程序和游戏中的实时输入管理。

**实时响应:** **kbhit() 函数 有助于为 **电子游戏 或需要不间断用户输入或对键盘事件做出快速响应的应用程序实现实时交互。由于它不等待用户按下 **回车键,程序可以立即响应按键事件。

**无需按回车键:** 使用 **kbhit(),您不需要用户在输入字符后按 **回车 键。这种行为对于某些类型的应用程序(例如 **游戏)很有用,在这些应用程序中等待 **回车键 可能会破坏用户体验。

**单字符输入:** **kbhit() 函数对于分析 **单字符输入 非常有用,这对于许多交互式控制台程序来说足够常见。它可以简化 **输入处理,因为它一次只处理一个字符。

**实现简单:** **kbhit() 函数 非常简单,使用 **kbhit()** **函数 进行键盘输入的代码简洁明了。

局限性

C 语言中的 **kbhit() 函数** 有多种缺点。C 语言中 kbhit() 函数的一些主要缺点如下:

**有限的输入处理:** **kbhit() 函数 只检查 **键盘缓冲区 中的 **一个字符。Kbhit()** 无法识别同时按下或快速连续按下的所有按键。由于它一次只能读取一个字符,因此可能不适用于需要复杂或 **多个按键组合 的某些应用程序。

**无按键释放检测:** **kbhit() 函数 无法检测按键释放,它只能检测 **按键按下。由于此限制,您无法立即识别并响应按键释放事件。您需要采用更高级的策略,涉及额外的 **状态跟踪 来管理 **按键按下 和 **释放事件**。

**平台特定:** **kbhit() 函数 不是标准的 **C 函数,并且特定于某些环境,包括 **Windows 和一些 **DOS 环境。在类 Unix 系统(例如 **Linux, macOS)或其他操作系统上不可用。

**缺乏缓冲:** 调用函数时,**kbhit()** 只是检查是否有按键被按下。如果您想按输入顺序处理或缓冲多个字符,则需要 **额外的逻辑**。

**有限的输入处理:** 对于更复杂的输入处理,例如多键组合,可能需要 **kbhit() 函数。在这种情况下,您应该考虑其他 **输入库 或特定于平台的 **方法**。

由于这些限制,**kbhit() 函数可能不适用于需要更复杂键盘 **输入处理 的应用程序,例如 **游戏、GUI 或具有 **复杂控制方案 的应用程序。在这些情况下,最好使用专门的输入库,如 **ncurses、特定于平台的技巧,甚至提供广泛输入处理功能的 **游戏开发框架。这些替代方案可能提供更好的 **控制、灵活性 和跨多个系统的 **可移植性**。


下一主题C 中的多行宏