5

For most of my life, I've been using cstdio. Now I'm trying to shift over to iostream.

Suppose I have a separate program called "foo.cpp" that looks like this:

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

In another program called "bar.cpp", I call the foo executable. In the past, if I wanted to redirect stdin and stdout to a file, I would use freopen like so:

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"
}

Now I'm trying to redirect std::cin and std::cout to stringstreams. Something like this:

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"
}

But what I've learned is that std::cin and std::cout was not redirected when executing "foo.exe". The program now expected user input and will print to std::cout. When execution of "foo.exe" was done, std::cin and std::cout within "bar.cpp" still remained redirected to instr and outstr respectively.

My question is, is there a way to do it with iostream like I intended, or am I stuck with using freopen?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • 1
    The operating system is in charge of processing the output of executables. The C++ language has no facilities for redirecting output. – Thomas Matthews Apr 19 '17 at 16:23
  • 1
    Common solutions for sharing data between programs: files, sockets, piping (tell OS to pipe output of other program into standard input for your program), shared memory areas. Search the internet. – Thomas Matthews Apr 19 '17 at 16:24
  • 1
    Have you tried just making the same freopen calls? – stark Apr 19 '17 at 16:45

2 Answers2

1

Haven't seen a freopen call in a while. This brings back some old memories.

Anyway, I think you should stick with freopen. The documentation page of the function literally states that this is one of the main use cases:

This function is especially useful for redirecting predefined streams like stdin, stdout and stderr to specific files.

I don't think you can do the redirection with iostream only, because the iostream library doesn't have an equivalent for the freopen function.

It is interesting though why this solution you tried doesn't work:

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

Maybe with those two lines you just affect the rdbuf of std::cin and std::cout from the current process and the subprocess has another instance of std::cin and std::cout.

The information about files seems to be copied from the parent process to the subprocess when calling system. That is why the changes you do in the main process on stdin and stdout with freopen are also visible in the subprocess.

Regardless, you should not use system to run a subprogram from your main C++ program. As you are probably on Windows (guessing from foo.exe), I would analyze this example from Microsoft. It explains how to create a subprocess and use pipes to redirect the input and output of the subprogram.

Valy
  • 573
  • 2
  • 12
0

In your sample code using freopen, you are redirecting to/from physical files, correct? In your sample code using std::istringstream and std::ostringstream you are trying to redirect to/from memory, correct? Physical files are not the same as memory. Memory does not have file descriptors. In Linux you can use fmemopen as in windows - C - create file in memory - Stack Overflow but that won't help with C++ standard classes such as std::istringstream and std::ostringstream nor would you be able to redirect stdin and stdout to/from fmemopen, for one thing because fmemopen is not available in all operating systems. The C++ standard classes don't support this type of thing; see c++ - Getting a FILE* from a std::fstream - Stack Overflow. std::istream and std::ostream might look like std::istringstream and std::ostringstream at the C++ interace level but internally they are not compatible.

Community
  • 1
  • 1
Sam Hobbs
  • 2,594
  • 3
  • 21
  • 32