Redirect both cout and stdout to a string in C++ for Unit Testing
std::stringstream
may be what you're looking for.
UPDATE
Alright, this is a bit of hack, but maybe you could do this to grab the printf output:
char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout);
setbuf(stdout, huge_string_buffer);
Note you should use "/dev/null" for linux instead of "NUL". That will rapidly start to fill up huge_string_buffer. If you want to be able to continue redirecting output after the buffer is full you'll have to call fflush(), otherwise it will throw an error. See std::setbuf
for more info.
redirect stdout/stderr to a string
Yes, you can redirect it to an std::stringstream
:
std::stringstream buffer;
std::streambuf * old = std::cout.rdbuf(buffer.rdbuf());
std::cout << "Bla" << std::endl;
std::string text = buffer.str(); // text will now contain "Bla\n"
You can use a simple guard class to make sure the buffer is always reset:
struct cout_redirect {
cout_redirect( std::streambuf * new_buffer )
: old( std::cout.rdbuf( new_buffer ) )
{ }
~cout_redirect( ) {
std::cout.rdbuf( old );
}
private:
std::streambuf * old;
};
redirect output of an function printing to console to string
Yes. That can be done. Here is a little demo:
#include <sstream>
#include <iostream>
void print_to_console() {
std::cout << "Hello from print_to_console()" << std::endl;
}
void foo(){
std::cout<<"hello world"<<std::endl;
print_to_console(); // this could be printed from anything
}
int main()
{
std::stringstream ss;
//change the underlying buffer and save the old buffer
auto old_buf = std::cout.rdbuf(ss.rdbuf());
foo(); //all the std::cout goes to ss
std::cout.rdbuf(old_buf); //reset
std::cout << "<redirected-output>\n"
<< ss.str()
<< "</redirected-output>" << std::endl;
}
Output:
<redirected-output>
hello world
Hello from print_to_console()
</redirected-output>
See Online Demo.
How to get output sent to stdout onto a string
Use rdbuf.
std::stringstream stream;
auto * old = std::cout.rdbuf(stream.rdbuf());
CallFunction();
std::cout.rdbuf(old);
std::string value = stream.str();
How to capture stdout/stderr with googletest?
I have used this snippet before to redirect cout calls to a stringstream when testing output. Hopefully it might spark some ideas. I've never used googletest before.
// This can be an ofstream as well or any other ostream
std::stringstream buffer;
// Save cout's buffer here
std::streambuf *sbuf = std::cout.rdbuf();
// Redirect cout to our stringstream buffer or any other ostream
std::cout.rdbuf(buffer.rdbuf());
// Use cout as usual
std::cout << "Hello World";
// When done redirect cout to its old self
std::cout.rdbuf(sbuf);
Before redirecting back to the original output use your google test to check the output in buffer.
How to redirect cin and cout to files?
Here is an working example of what you want to do. Read the comments to know what each line in the code does. I've tested it on my pc with gcc 4.6.1; it works fine.
#include <iostream>
#include <fstream>
#include <string>
void f()
{
std::string line;
while(std::getline(std::cin, line)) //input from the file in.txt
{
std::cout << line << "\n"; //output to the file out.txt
}
}
int main()
{
std::ifstream in("in.txt");
std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
std::ofstream out("out.txt");
std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
std::string word;
std::cin >> word; //input from the file in.txt
std::cout << word << " "; //output to the file out.txt
f(); //call function
std::cin.rdbuf(cinbuf); //reset to standard input again
std::cout.rdbuf(coutbuf); //reset to standard output again
std::cin >> word; //input from the standard input
std::cout << word; //output to the standard input
}
You could save and redirect in just one line as:
auto cinbuf = std::cin.rdbuf(in.rdbuf()); //save and redirect
Here std::cin.rdbuf(in.rdbuf())
sets std::cin's
buffer to in.rdbuf()
and then returns the old buffer associated with std::cin
. The very same can be done with std::cout
— or any stream for that matter.
Redirect FILE * stdout to string in c++
In linux, your best bet is anonymous pipe.
First, create a pipe:
int redirectPipe[2];
pipe(redirectPipe)
Then, open the file descriptor returned to us via pipe(2) using fdopen:
FILE* inHandle = fdopen(redirectPipe[0], "w");
FILE* outHandle = fdopen(redirectPipe[1], "r");
Call the function:
getInfo(inHandle, someValue);
Then, read using outHandle
as if it's a regular file.
One thing to be careful: Pipes have fixed buffer size and if there is a possibility for getInfo function to fill the buffer, you'll have a deadlock.
To prevent the deadlock, you can either call getInfo
from another thread, or increase pipe buffer size using fcntl
and F_SETPIPE_SZ
. Or better, as Ben Voigt mentioned in the comments, create a temp file.
Note: I was specific to *nix since OP mentioned he/she wanted the "best one in linux"
Redirecting stdout from another program in C++
You could create a filebuf
then replace cout
's streambuf with it:
{
std::filebuf f;
f.open("output.txt", std::ios::out);
std::streambuf* o = std::cout.rdbuf(&f);
std::cout << "hello" << std::endl; // endl will flush the stream
std::cout.rdbuf(o);
}
You need to restore cout
's original streambuf again (or set it to a null pointer) or it will probably crash when the global streams are flushed and destroyed, because the filebuf
will already have gone out of scope.
Related Topics
Visual Studio 2013: Cl.Exe Exited with Code -1073741515
How to Implement Readlink to Find the Path
What Is the Maximum Memory Available to a C++ Application on 32-Bit Windows
What Does the & (Ampersand) at the End of Member Function Signature Mean
Nested Class' Access to Enclosing Class' Private Data Members
C++ 2 Dimensional Array with Variable Size Rows
C++ Std::Tuple Order of Destruction
Visual Studio 2015 Code Analysis C6386 Warns of Buffer Overrun
What Are the Differences Between Std::Variant and Boost::Variant
What Are the Advantages and Disadvantages of Implementing Classes in Header Files
C++ "Hello World" Boost Tee Example Program
Concatenate Char Arrays in C++
Check If Class Is Derived from a Specific Class (Compile, Runtime Both Answers Available)