我基本上想测试标准输入是否有输入(就像你回显并通过管道传输它一样)。我找到了可行的解决方案,但它们很丑陋,我喜欢我的解决方案是干净的。
在 Linux 上我使用这个:
bool StdinOpen() {
FILE* handle = popen("test -p /dev/stdin", "r");
return pclose(handle) == 0;
}
我知道我应该添加更多错误处理,但这不是重点。
在 Windows 上我使用这个:
bool StdinOpen() {
static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD bytes_left;
PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL);
return bytes_left;
}
这对于 Linux 来说很好,但我想知道在不使用管道的情况下可以调用的等效 API 是什么(就像
test -f $file
你所做的 fopen($file, "r") != NULL
)。我有一种预感,我可以 open("/dev/stdin", "r")
做同样的事情,但我想知道最好的方法。
总结:我想知道我可以使用哪些 API 来替代 linux 的
test -p /dev/stdin
,并且,如果您知道针对 Windows 的更好的解决方案。
这是 POSIX (Linux) 的解决方案:我不确定 Windows 上的 poll() 等效项是什么。在 Unix 上,编号为 0 的文件描述符是标准输入。
#include <stdio.h>
#include <sys/poll.h>
int main(void)
{
struct pollfd fds;
int ret;
fds.fd = 0; /* this is STDIN */
fds.events = POLLIN;
ret = poll(&fds, 1, 0);
if(ret == 1)
printf("Yep\n");
else if(ret == 0)
printf("No\n");
else
printf("Error\n");
return 0;
}
测试:
$ ./stdin
No
$ echo "foo" | ./stdin
Yep
这行不通吗?
std::cin.rdbuf()->in_avail();
_kbhit()
能满足您的需求吗?
窗户:
return ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 3) == WAIT_OBJECT_0;
老问题,但(当前)其他答案都不适用于 Windows(我可能会在一年内再次查找它:)。
[LINUX] ioctl() 非常简单且常见,因为它是标准 C 库的一部分,https://man7.org/linux/man-pages/man2/ioctl.2.html
语法:
ioctl(int fd, int opt, int *n)
ioctl(0, FIONREAD, &available_bytes);
uin64_t bytes
变量的指针,用于存储可用字节。
#include <stdio.h>
#include <stdint.h>
#include <sys/ioctl.h>
uint64_t is_stdin_empty() {
uint64_t bytes;
ioctl(0,FIONREAD, &bytes);
return bytes;
}
int main(int argc, const char **args)
{
uint64_t available_bytes = is_stdin_empty();
if(available_bytes == 0){
printf("empty\n");
}else{
printf("%lu available bytes\n",available_bytes);
}
return 0;
}
测试:
🚬🐸gurgui@arch1to tmp.VmyPJIU1Kg$ ./t
空
🚬🐸gurgui@arch1to tmp.VmyPJIU1Kg$ 回声“wiski”| ./t
6 个可用字节
🚬🐸gurgui@arch1to tmp.VmyPJIU1Kg$ ./t < /etc/passwd
2172 可用字节