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

发布于 2024-11-26 06:10:37 字数 797 浏览 0 评论 0原文

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

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

I basically want to test if stdin has input (like if you echo and pipe it). I have found solutions that work, but they are ugly, and I like my solutions to be clean.

On linux I use this:

bool StdinOpen() {
  FILE* handle = popen("test -p /dev/stdin", "r");
  return pclose(handle) == 0;
}

I know that I should add more error handling, but it's besides the point.

On windows I use this:

bool StdinOpen() {
  static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
  DWORD bytes_left;
  PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL);
  return bytes_left;
}

That is fine for linux, but I want to know what are the equivalent APIs that I can call without using a pipe (like for test -f $file you do fopen($file, "r") != NULL). I have an inkling that I could open("/dev/stdin", "r") and do the same thing, but I want to know the best way to do it.

Summary: I want to know the APIs I could use to substitute for test -p /dev/stdin for linux, and, if you know a better solution for windows.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

诺曦 2024-12-03 06:10:37

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

Here's a solution for POSIX (Linux): I'm not sure what's the equivalent of poll() on Windows. On Unix, The file descriptor with number 0 is the standard input.

#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;
}

Testing:

$ ./stdin
No
$ echo "foo" | ./stdin
Yep
尤怨 2024-12-03 06:10:37

这行不通吗?

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

Would this not work?

std::cin.rdbuf()->in_avail();
粉红×色少女 2024-12-03 06:10:37

I'm not sure, but does _kbhit() do what you need?

双手揣兜 2024-12-03 06:10:37

Windows:

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

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

Windows:

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

Old question, but none of the (current) other answers work on Windows (and I might be looking it up again in an year :).

听你说爱我 2024-12-03 06:10:37

[ POSIX ] ioctl() 非常简单且常见,因为它是标准 C POSIX 库的一部分,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 ->指向 int bytes 变量的指针,用于存储可用字节。

#include <sys/ioctl.h>
#include <stdio.h>

int stdin_avail() {
  int bytes = 0;
  if(ioctl(0,FIONREAD, &bytes) == -1){
    return -1;
  };
  return bytes;
}

int main(int argc, const char **args)
{
  int available_bytes = stdin_avail();
  printf("available: %i bytes\n", available_bytes);
  return 0;
}

[ POSIX ] ioctl() is pretty straightforward and common since it's part of the standard C POSIX library, https://man7.org/linux/man-pages/man2/ioctl.2.html
Syntax: ioctl(int fd, int opt, int *n)
In this case ioctl(0, FIONREAD, &available_bytes);
0 -> stdin
FIONREAD -> opt to ask for available bytes
&available_bytes -> pointer to the int bytes variable to store the available bytes.

#include <sys/ioctl.h>
#include <stdio.h>

int stdin_avail() {
  int bytes = 0;
  if(ioctl(0,FIONREAD, &bytes) == -1){
    return -1;
  };
  return bytes;
}

int main(int argc, const char **args)
{
  int available_bytes = stdin_avail();
  printf("available: %i bytes\n", available_bytes);
  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文