Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run .exe and redirect stdin and out

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?

like image 745
Muhammad Irham Rasyidi Avatar asked Nov 08 '22 23:11

Muhammad Irham Rasyidi


1 Answers

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.

like image 164
Valy Avatar answered Nov 15 '22 05:11

Valy