Run .exe and redirect standard input and output

For most of my life I used cstdio . Now I'm trying to switch 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. Previously, if I wanted to redirect stdin and stdout to a file, I would use freopen as follows:

 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 am trying to redirect std::cin and std::cout to stringstreams. Something like that:

 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 I realized that std::cin and std::cout were not redirected while running "foo.exe". The program now expects user input and will print before std::cout . When the execution of "foo.exe" was executed, std::cin and std::cout inside "bar.cpp" still remained redirected to instr and outstr respectively.

My question is: is there a way to do this with iostream , as I expected, or am I sticking to using freopen ?

+5
source share
2 answers

Did not see freopen call after a while. This brings back some old memories.

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

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

I don't think you can only redirect using iostream , because the iostream library has no equivalent for the freopen function.

I wonder why this solution you tried does not work:

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

Perhaps with these two lines you are simply influencing the rdbuf from std::cin and std::cout from the current process, and the subprocess has a different instance of std::cin and std::cout .

The file information is apparently copied from the parent process to the subprocess when the system called. This is why the changes you make in the main process on stdin and stdout using freopen are also visible in the subprocess.

Regardless, you should not use the system to run a routine from your main C ++ program. Since 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 channels to redirect input and output of a subprogram.

+1
source

In your code sample using freopen, you are redirected to / from physical files, right? In your code example using std :: istringstream and std :: ostringstream you are trying to redirect to / from memory, correct? Physical files do not match memory. There are no file descriptors in memory. On Linux, you can use fmemopen, like on windows-C - create a file in memory - stack overflow , but this will not help with standard C ++ classes like std :: istringstream and std :: ostringstream and you cannot redirect stdin and stdout to / from fmemopen, firstly because fmemopen is not available on all operating systems. The standard C ++ classes do not support this type of thing; see C ++ - Getting FILE * from std :: fstream - stack overflow . std :: istream and std :: ostream may look like std :: istringstream and std :: ostringstream at the C ++ interaction level, but internally they are incompatible.

0
source

Source: https://habr.com/ru/post/1266931/


All Articles