测试标准输入是否具有C++输入(windows和/或linux)
我基本上想测试标准输入是否有输入(就像回显并管理它一样)。我找到了可行的解决方案,但它们很丑,我喜欢我的解决方案是干净的。测试标准输入是否具有C++输入(windows和/或linux)
在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")
并做同样的事情,但我想知道做到这一点的最佳方式。
摘要:我想知道我可以用来代替linux的test -p /dev/stdin
的API,以及如果你知道更好的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
这正是我想要的。现在,如果您能告诉我如何测量输入缓冲区大小,我将永远感激不尽,但我不想听起来像一个问题猪。 – norcalli
您可以使用read()来获取输入。首先使用fcntl()将文件描述符0设置为非阻塞,然后当没有更多传入数据时,read()将返回读取的字节数或0。 – Antti
+1。另一个常用的选择是'select()' - 概念上类似的用法。至关重要的是要注意,这些操作系统询问描述符是否有新的数据可用 - 如果您正在使用该级别,则必须在描述符上直接使用'read()',您也不能使用library- level stdin流或'std :: cin'(除非你提供了一个新的缓冲区实现)。 –
这会不会工作?
std::cin.rdbuf()->in_avail();
如果标准输入是文件句柄(而不是管道),那么'PeekNamedPipe'解决方案失败。另外,你的'handle'变量不应该是静态的。如果在你的应用程序运行时把手被重定向,你会在以后感到惊讶。 –
@比利:我不认为一个句柄可能会随机重定向。当然,你可能会改变你认为是stdin的东西,但旧的手柄仍然存在。但我同意第一部分。 – Mehrdad
Lionel B在http://bytes.com/topic/c/answers/841283-how-make-non-blocking-call-cin上提供了Linux的一些代码 - 讨论也值得一读。 –