【问题标题】:How to know when there is input through the terminal pipe line on C++ 11?如何知道何时通过 C++ 11 上的终端管道进行输入?
【发布时间】:2016-10-29 21:03:34
【问题描述】:

在 C++ 11 上如何知道终端管道何时有输入?

我可以这样调用我的程序:

1. ./main solved.txt
2. cat unsolved.txt | ./main
3. cat unsolved.txt | ./main solved.txt

我正在使用它来了解我是否需要在 C POSIX 标准上从管道读取数据:

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <unistd.h>

int main( int argumentsCount, char* argumentsStringList[] )
{
    std::stringstream inputedPipeLineString;

    if( argumentsCount > 1 )
    {
        printf( "argumentsStringList[1]: %s", argumentsStringList[ 1 ] );
    }

    // If it is passed input through the terminal pipe line, get it.
    if( !isatty( fileno( stdin ) ) )
    {
        // Converts the std::fstream "std::cin" to std::stringstream which natively
        // supports conversion to string.
        inputedPipeLineString << std::cin.rdbuf();

        printf( "inputedPipeLineString: %s", inputedPipeLineString.str().c_str() );
    }
}

但现在我想使用 C++ 11 标准,而我所爱的 filenoisatty 已经不在了。那么在 C++ 11 上有替代它们的方法吗?

相关话题:

  1. checking data availability before calling std::getline
  2. Why does in_avail() output zero even if the stream has some char?
  3. Error "'fdopen' was not declared" found with g++ 4 that compiled with g++3
  4. stdio.h not standard in C++?
  5. error: ‘fileno’ was not declared in this scope
  6. GoogleTest 1.6 with Cygwin 1.7 compile error: 'fileno' was not declared in this scope

问题是当使用-std=C++11 编译时,filenoisattystdio.h/cstdlib 上是未定义的,因为它们是 POSIX 的东西。因此,一种解决方案是使用-std=GNU++11 而不是-std=C++11。但是是否可以使用-std=C++11 编写其他内容进行编译?

【问题讨论】:

  • 我知道没有可移植的方式。如果没有命令行参数,我通常会使用管道。
  • POSIX 不会因为 C++11 的出现而消失得无影无踪。 filenoisatty 函数从来都不是 C++ 的一部分。
  • -std=gnu++11 有什么问题?
  • 这可能很棘手,但您可以检查cin 是否会使用cin.rdbuf()-&gt;in_avail() 执行阻塞读取。如果它返回 0,则很可能没有等待读取的输入数据(后续读取不会等待用户输入),因此没有管道,除非用户可以在微秒内写入一些东西,当然。可以看到后续的非阻塞读取具有管道存在的间接证明(或&lt;&lt;&lt; 输入)。
  • std::cin.rdbuf()-&gt;in_avail() 总是返回 0。似乎是 GCC 上的一个错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=24206,但我们几乎让它工作了。

标签: c++ c++11 posix


【解决方案1】:

C++ POSIX 标准

据我所知,没有这样的事情。有一个 C POSIX 库,它是 POSIX 标准的一部分。

那么在 C++ 11 上有替代它们的方法吗?

在标准 C++ 中没有替代品(在 C++11 之前没有,到目前为止也没有)。

您需要依赖 POSIX 来获得所需的功能。

即使在 POSIX 中,也是 unistd.h 定义了 isatty。您忽略了将其包含在您的程序中。

【讨论】:

    【解决方案2】:

    我不知道有一种完全可移植的方式来做到这一点。据我所知,标准 C++ 不知道它的输入来自哪里,所以如果你在 posix 系统上工作,你应该只使用isatty

    【讨论】:

      【解决方案3】:

      在 C++17 中,您有 &lt;filesystem&gt; 标头,它有一个 std::filesystem::status() 函数,该函数返回一个 file_status 对象。您可以通过type() 函数访问其类型,例如通过结果,并使用快速比较来查看它是否是您预期目标的类型。 一种非常天真的方法是这样的:

      auto result {std::filesystem::status(fd)};
      if (result.type() == std::filesystem::file_type::character)
      {
         // do some stuff in here 
      }
      

      其中 fd 是要检查的文件描述符。由于没有额外的检查,以上不是完全证明,但如果它是字符类型,它几乎可以肯定等同于终端。 如果你有一个支持 C++17 的编译器,&lt;filesystem&gt; 真的很方便 https://en.cppreference.com/w/cpp/filesystem/file_type

      注意:我刚开始使用 &lt;filesystem&gt;,所以我可能在这里遗漏了一些细微差别,欢迎对答案进行任何更新

      【讨论】:

        猜你喜欢
        • 2022-11-15
        • 2013-06-10
        • 1970-01-01
        • 2021-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-09
        • 2017-02-08
        相关资源
        最近更新 更多