如何不使用getchar()判断标准输入是否为空以避免程序暂停?
判断标准输入是否为空的非
getchar()方案 问题场景
- 第一个代码中,由于标准输入为空,
getchar()会阻塞程序,必须等待用户输入字符并回车后,才会打印"After"。 - 第二个代码通过
ungetc('a', stdin)预先向标准输入缓冲区写入字符,getchar()直接读取该字符,程序无需等待用户操作,会立即输出"Before"和"After"。
第一个代码
int main() { printf("Before"); char c = getchar(); printf("After"); }
第二个代码
int main() { ungetc( 'a', stdin ); printf("Before"); char c = getchar(); printf("After"); }
核心疑问
是否存在不使用getchar()的方法来判断标准输入是否为空,从而避免标准输入为空时的程序暂停?
可行方案
1. POSIX系统下使用select()
select()可以监听文件描述符的可读状态,无需读取字符就能判断标准输入是否有数据。示例代码:
#include <stdio.h> #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main() { printf("Before\n"); fd_set readfds; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); struct timeval tv; tv.tv_sec = 0; // 超时时间设为0,立即返回结果 tv.tv_usec = 0; // 检查标准输入是否可读 int ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv); if (ret == -1) { perror("select error"); return 1; } else if (ret > 0) { printf("标准输入不为空,可读取数据\n"); char c = getchar(); printf("读取到字符: %c\n", c); } else { printf("标准输入为空,无需等待\n"); } printf("After\n"); return 0; }
select()会立即返回标准输入的状态,不会阻塞程序,适合Unix/Linux等POSIX兼容系统。
2. Windows平台使用kbhit()
Windows提供的kbhit()函数可以检查键盘缓冲区是否有输入,无需读取字符。示例代码:
#include <stdio.h> #include <conio.h> int main() { printf("Before\n"); if (kbhit()) { printf("标准输入不为空,可读取数据\n"); char c = getchar(); printf("读取到字符: %c\n", c); } else { printf("标准输入为空,无需等待\n"); } printf("After\n"); return 0; }
注意kbhit()是Windows特有的函数,需要包含conio.h头文件。
3. POSIX系统下设置非阻塞模式
通过fcntl()将标准输入设置为非阻塞模式,调用getchar()时若输入为空会直接返回错误,而非阻塞。示例代码:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> int main() { printf("Before\n"); // 获取当前文件状态标志 int flags = fcntl(STDIN_FILENO, F_GETFL, 0); if (flags == -1) { perror("fcntl get error"); return 1; } // 设置非阻塞模式 if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl set error"); return 1; } char c = getchar(); if (c == EOF) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("标准输入为空,无需等待\n"); } else { perror("getchar error"); return 1; } } else { printf("读取到字符: %c\n", c); } // 恢复原模式(可选) fcntl(STDIN_FILENO, F_SETFL, flags); printf("After\n"); return 0; }
这种方法需要处理非阻塞IO的错误码,适合需要灵活控制输入状态的场景。
内容的提问来源于stack exchange,提问作者Shadow43375
相关产品推荐
相关产品推荐

