【问题标题】:Run .exe and redirect stdin and out运行 .exe 并重定向标准输入和输出
【发布时间】:2017-04-19 15:57:50
【问题描述】:

在我的大部分时间里,我一直在使用cstdio。现在我正在尝试切换到iostream

假设我有一个名为“foo.cpp”的单独程序,如下所示:

int main(){ // foo.cpp
    int x;
    std::cin >> x;
    std::cout << x + 5 << "\n";
}

在另一个名为“bar.cpp”的程序中,我调用了 foo 可执行文件。过去,如果我想将标准输入和标准输出重定向到一个文件,我会像这样使用freopen

int main(){ // bar.cpp, redirecting stdin and stdout
    freopen("foo.in", "r", stdin); // Suppose "foo.in" contains a single integer "42"
    freopen("foo.out", "w", stdout);

    system("foo.exe"); // "foo.out" will contain "47"
}

现在我正在尝试将std::cinstd::cout 重定向到字符串流。像这样的:

int main(){ // bar.cpp, redirecting cin and cout
    std::istringstream instr("62");
    std::ostringstream outstr;

    std::cin.rdbuf(instr.rdbuf());
    std::cout.rdbuf(outstr.rdbuf());

    system("foo.exe"); // outstr should contain "67"
}

但我了解到的是 std::cinstd::cout 在执行“foo.exe”时没有被重定向。该程序现在需要用户输入并将打印到std::cout。执行完“foo.exe”后,“bar.cpp”中的std::cinstd::cout 仍然分别重定向到instroutstr

我的问题是,有没有办法像我想要的那样使用iostream,还是我坚持使用freopen

【问题讨论】:

  • 操作系统负责处理可执行文件的输出。 C++ 语言没有重定向输出的功能。
  • 程序之间共享数据的常用解决方案:文件、套接字、管道(告诉操作系统将其他程序的输出通过管道传输到您程序的标准输入)、共享内存区域。搜索互联网。
  • 您是否尝试过只进行相同的 freopen 调用?

标签: c++ c++11 redirect


【解决方案1】:

有一段时间没有看到freopen 的电话了。这让我想起了一些旧的回忆。

无论如何,我认为你应该坚持使用freopen。该函数的documentation 页面字面意思是这是主要用例之一:

此函数对于将预定义的流(如 stdinstdoutstderr)重定向到特定文件特别有用。

我认为您不能仅使用 iostream 进行重定向,因为 iostream 库没有 freopen 函数的等效项。

有趣的是,为什么您尝试的这个解决方案不起作用:

std::cin.rdbuf(instr.rdbuf());
std::cout.rdbuf(outstr.rdbuf());

也许通过这两行,您只会影响当前进程中std::cinstd::coutrdbuf,并且子进程还有另一个std::cinstd::cout 实例。

在调用system 时,文件信息似乎从父进程复制到子进程。这就是为什么您在 stdinstdout 上使用freopen 在主进程中所做的更改在子进程中也可见。

无论如何,you should not use system 从您的主 C++ 程序运行子程序。由于您可能在 Windows 上(从 foo.exe 猜测),我将分析来自 Microsoft 的 example。它解释了如何创建子进程并使用管道重定向子程序的输入和输出。

【讨论】:

    【解决方案2】:

    在您使用 freopen 的示例代码中,您正在重定向到物理文件/从物理文件重定向,对吗?在您使用 std::istringstream 和 std::ostringstream 的示例代码中,您试图重定向到/从内存,对吗?物理文件与内存不同。内存没有文件描述符。在 Linux 中,您可以像在 windows - C - create file in memory - Stack Overflow 中一样使用 fmemopen,但这对 C++ 标准类(例如 std::istringstream 和 std::ostringstream)没有帮助,也无法将 stdin 和 stdout 重定向到 fmemopen 或从 fmemopen 重定向。因为 fmemopen 并非在所有操作系统中都可用。 C++ 标准类不支持这种类型的东西;见c++ - Getting a FILE* from a std::fstream - Stack Overflow。 std::istream 和 std::ostream 在 C++ 交互级别上可能看起来像 std::istringstream 和 std::ostringstream 但在内部它们不兼容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多