linux中c语言kbhit函数用法,C语言判断用户是否输入-非阻塞函数kbhit

一、基础研究

要从地址读取数据,肯定是要定义一个指针变量p,用它来实现变换地址和取值的功能。另外程序是当两个条件中的某一个出现时才停止,所以应该用while~do循环语句循环输出n和d,并用while进行判断。这里实现三个问题:

(1)循环地把值转换成地址。

(2)判断偏移地址是否为0xffff。

(3)判断用户是否输入了‘q’。

前两个问题比较好实现,对于第三个问题我们需要注意的是c语言是怎么处理用户输入的。之前做汇编课设的时候我们研究过汇编对于输入的处理,并且尝试过两个中断,一个是要中止等待用户输入的,一个是不中止等待的。现在我们的需求就类似于第二个中断,即等待用户输入同时不停止程序的运行。

首先写了一个程序如下:

896a3dde441a323717ba041c0ddfe707.png

编译时警告说0xffff在比较中超过常量范围,也就是超过int型的范围,将整个程序的int改成long后警告消失。int是两个字节,应该正好能够容纳偏移地址0xffff,为什么比较时会超出范围呢?难道是与比较的机制有关吗?这里作为一个问题来扩展研究。

将编译之后的程序进行连接,出现错误:getchar()函数没有定义,这说明在我们当前连接的obj文件里没有getchar()函数,解决的办法有两个:(1)用#include导入头文件。(2)不使用getchar()函数。在这里我们先尝试第二种方法,scanf()函数会暂停程序等待输入,并且在输入完后还要按回车才能继续向下执行,所以不符合我们的需求。查找资料发现getche()函数不用敲回车就可以将字符输入,而getch()函数不用敲回车,也不显示,只是将字符输入进行处理。而且这两个函数也不需要导入其他文件,修改后的程序如下:

e42995a9ab680a6ebae6482a29205ad6.png

这时发现还有一个问题:每次循环都还要用户输入字符才能向下进行,就是说函数是阻塞的。在网上查找资料发现输入函数都是阻塞型的,那么我们可以调整思路,检测用户是否输入。查找资料发现输入检测函数有kbhit()函数,如果有输入它会返回一个非0值,没有就返回0,修改后的函数如下:

225fea941c53e1602647da678f8db711.png

运行程序,它会不停地打印地址和地址的值,直到用户输入字符q。

但是运行结果发现:当地址为0xffff时,程序并没有停止:

deb98b4f3daae006ebef896ece30fb1a.png

将程序改成如下所示也不行:

f2066537d380c2eb760a33647eb8a8f2.png

这里可能是判断语句有问题,结果将判断语句改为p==(long *)0xffff之后程序在地址为0xffff时可以停止,修改的程序为:

89f4a19f89a421a8f7cece446dd0d80d.png

之前是对数进行比较,修改后是对指针进行比较,那为什么对数进行比较会出错呢?我们觉得是因为将p强制类型转换成long会出错,再次修改程序如下:

41a779bc3f8b2a40a89e659c2429b318.png

发现虽然有警告,但是程序仍能正常执行,这说明用long型确实会对地址判断有影响。

二、扩展研究

(1)int是两个字节,应该正好能够容纳偏移地址0xffff,为什么比较时会警告超出范围呢?

答:因为int是带正负的类型,它的最高位为符号位,而0xffff是unsigned int类型,所以会超出范围。这里把它进行强制类型转换就行了。

(2)Getchar()的实现方式。

答:getchar 由宏实现:#define getchar() getc(stdin)。所以要与头文件相关联,它不是真正的函数,而是定义为预处理器宏。

(3)为什么用(long)p==0xffff判断时会识别不到0xffff,导致循环停不下来?

答:同样这里应该是unsigned long类型。

三、研究总结

c语言是接近底层的语言,这在它和汇编的联系上可以看出来。之前做课设时要用到非阻塞中断,在这里是用到非阻塞函数,问题是相似的,只不过实现的语言变了。但是只要我们掌握了程序设计的精髓,其他的就只是语法上的实现问题了。

还有,独立分析和思考的能力真的很重要,我们不要养成随便问问题的习惯,要先自己思考,抓住问题的本质,提出自己的猜想,然后在询问别人或者查资料去证实,这样自己解决问题的能力才能够得到成长。

0b1331709591d260c1c78e86d0c51c18.png

<think>好的,我现在需要回答用户关于C语言kbhit()函数的问题。首先,我得回忆一下这个函数的基本信息。kbhit()是一个用于检查键盘是否有按键被按下的函数,它属于非阻塞式的输入检测。这意味着程序可以在不暂停执行的情况下检查输入状态。 接下来,我应该考虑这个函数的所属头文件。我记得在Windows环境下,kbhit()通常位于<conio.h>头文件中,而Linux或Unix系统可能需要使用其他库,比如<curses.h>或者<ncurses.h>,或者通过系统调用来实现类似功能。这点需要明确指出,避免用户在不同平台使用时遇到问题。 然后,函数的返回值是关键。当有按键按下时,kbhit()返回非零值,否则返回0。这样用户就可以在循环中使用它来实时检测输入,而不必等待输入阻塞程序。例如,在游戏开发中处理用户输入或实时监控按键时很有用。 不过,需要注意这个函数的标准性问题。C标准库中并没有kbhit(),它是编译器特定的扩展,比如在MSVC或Borland C中常见。在跨平台开发时,依赖这个函数可能导致兼容性问题,所以可能需要替代方案,比如在Linux下使用select()或ncurses库的函数。 实际应用中,用户可能会在循环中使用kbhit()配合getch()来获取具体的按键值。这时候要提醒用户及时处理输入缓冲区,防止多个按键堆积。此外,不同编译器或平台的实现可能有差异,需要查阅相关文档。 还需要考虑用户可能的后续问题,比如替代函数或示例代码。虽然用户现在没有问,但提前准备这些信息会让回答更全面。例如,提供一个简单的示例代码,展示如何在Windows下使用kbhit()检测按键,并退出循环。 最后,确保回答结构清晰,分点说明函数的作用、头文件、返回值、注意事项和示例,帮助用户逐步理解。同时,使用中文口语化表达,避免技术术语过于晦涩,让不同层次的用户都能理解。</think>在C语言中,`kbhit()` 是一个用于 **非阻塞式键盘输入检测** 的函数。以下是分步说明: --- ### 1. **功能作用** - **核心功能**:检测键盘是否有按键被按下(无需等待用户输入)。 - **特点**:非阻塞(non-blocking),即无论是否输入函数会立即返回结果,不会暂停程序执行。 --- ### 2. **所属头文件** - **Windows环境**:需包含 `<conio.h>`(非标准库,常见于MSVC、Borland等编译器)。 - **Linux环境**:原生不支持,需借助第三方库(如 `ncurses`)或系统调用。 --- ### 3. **函数原型** ```c int kbhit(void); ``` - **返回值**: - **非0值**:键盘缓冲区中有按键被按下。 - **0**:无按键按下。 --- ### 4. **典型使用场景** ```c #include <stdio.h> #include <conio.h> // Windows专用 int main() { while(1) { if (kbhit()) { // 检测到按键 char ch = getch(); // 获取按键值 printf("按下了: %c\n", ch); if (ch == 'q') break; // 按q退出 } // 其他任务(如循环内的计算) } return 0; } ``` --- ### 5. **注意事项** - **平台依赖性**:非C标准函数,Windows专用。Linux需用替代方案: - 使用 `select()` 检测输入(涉及文件描述符)。 - 使用 `ncurses` 库的 `nodelay()` 和 `getch()`。 - **缓冲区问题**:多次调用 `kbhit()` 后需及时用 `getch()` 清空键盘缓冲区。 --- ### 6. **替代方案(跨平台)** ```c // Linux示例(需包含 <termios.h> 和 <unistd.h>) int kbhit_linux() { struct termios oldt, newt; int ch, oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); if (ch != EOF) { ungetc(ch, stdin); return 1; } return 0; } ``` --- ### 总结 - **用途**:实时检测键盘输入(如游戏控制、交互式命令行工具)。 - **局限**:依赖特定环境,跨平台需谨慎处理。 - **推荐**:优先使用标准输入函数(如 `fgets()`)或跨平台库(如 `ncurses`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值