测试 stdin 是否有 C++ 输入(Windows 和/或 Linux)

问题描述 投票:0回答:5

我基本上想测试标准输入是否有输入(就像你回显并通过管道传输它一样)。我找到了可行的解决方案,但它们很丑陋,我喜欢我的解决方案是干净的。

在 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 的更好的解决方案。

c++ testing pipe stdin
5个回答
15
投票

这是 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

5
投票

这行不通吗?

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

1
投票

我不确定,但是

_kbhit()
能满足您的需求吗?


0
投票

窗户:

return ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 3) == WAIT_OBJECT_0;

老问题,但(当前)其他答案都不适用于 Windows(我可能会在一年内再次查找它:)。


0
投票

[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);

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 可用字节

© www.soinside.com 2019 - 2024. All rights reserved.