测试标准输入是否具有C++输入(windows和/或linux)

测试标准输入是否具有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解决方案。

+0

如果标准输入是文件句柄(而不是管道),那么'PeekNamedPipe'解决方案失败。另外,你的'handle'变量不应该是静态的。如果在你的应用程序运行时把手被重定向,你会在以后感到惊讶。 –

+0

@比利:我不认为一个句柄可能会随机重定向。当然,你可能会改变你认为是stdin的东西,但旧的手柄仍然存在。但我同意第一部分。 – Mehrdad

+0

Lionel B在http://bytes.com/topic/c/answers/841283-how-make-non-blocking-call-cin上提供了Linux的一些代码 - 讨论也值得一读。 –

下面是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 
+0

这正是我想要的。现在,如果您能告诉我如何测量输入缓冲区大小,我将永远感激不尽,但我不想听起来像一个问题猪。 – norcalli

+0

您可以使用read()来获取输入。首先使用fcntl()将文件描述符0设置为非阻塞,然后当没有更多传入数据时,read()将返回读取的字节数或0。 – Antti

+2

+1。另一个常用的选择是'select()' - 概念上类似的用法。至关重要的是要注意,这些操作系统询问描述符是否有新的数据可用 - 如果您正在使用该级别,则必须在描述符上直接使用'read()',您也不能使用library- level stdin流或'std :: cin'(除非你提供了一个新的缓冲区实现)。 –

我不确定,但_kbhit()做你所需要的吗?

这会不会工作?

std::cin.rdbuf()->in_avail();