Belgi
Belgi

Reputation: 15082

How to redirect printing from screen (or any FILE*) into a string/char* in C++

I am working on a C++ code and I wish to do the following:

In the code there is a new type, T, there is a method defined on T that prints some information to a type FILE* variable.

I would like to do some work on this string inside of the program, so I would like to have a variable of type string (or even char*) that will contain what is printed to the screen (if I give the printing function stdout as the File*).

How can I do this ? maybe I can create some FILE* variable and then create (somehow) a string/char* variable with the information that is stored in that File* variable we created ?

Any help is appreciated!

Upvotes: 0

Views: 245

Answers (2)

Sergey
Sergey

Reputation: 8248

There are several platform-independent ways to do it. In C++ you can use stringstream(http://www.cplusplus.com/reference/sstream/stringstream/), which has many << operator overloads. So if you pass a reference to ostream& (not oFstream) to the output method, you can easily switch between files, stadard output stream and string outputs, because all this streams are inherited from ostream. Then you can get std::string object from stringstream and get C-string from it if you need.

Code example:

Output function (or method, then you don't need the second argument from the example):

void PrintMyObjectToSomeStream(std::ostream& stream, const MyClass& obj)
{
    stream << obj.pubField1;
    stream << obj.pubField2;
    stream << obj.GetPrivField1();
    stream << "string literal";
    stream << obj.GetPrivField2();
}

Usage:

MyClass obj1;
std::ofsstream ofs;
std::stringstream sstr;
//...open file for ofs, check if it is opened and so on...
//...use obj1, fill it's member fields with actual information...
PrintMyObjectToSomeStream(obj1,std::cout);//print to console
PrintMyObjectToSomeStream(obj1,sstr);//print to stringstream
PrintMyObjectToSomeStream(obj1,ofs);//print to file

std::string str1=sstr.str();//get std::string from stringstream
char* sptr1=sstr.str().c_str();//get pointer to C-string from stringstream

Or you can overload operator<<:

std::ostream& operator<<(std::ostream& stream, const MyClass& obj)
{
    stream << obj1.pubField;
    //...and so on
    return stream;
}

then you can use it in this way:

MyClass obj2;
int foo=100500;
std::stringstream sstr2;
std::ofstream ofs;//don't forget to open it

//print to stringstream
sstr2 << obj2 << foo << "string lineral followed by int\n";
//here you can get std::string or char* as like as in previous example

//print to file in the same way
ofs << obj2 << foo << "string lineral followed by int\n";

Using FILE is more C than C++ but you can think how to switch between fpirntf and sprintf or use Anton's answer.

Upvotes: 1

Anton Kovalenko
Anton Kovalenko

Reputation: 21507

POSIX 1.2008 fmemopen, open_memstream functions create a FILE* pointer which writes to (and/or reads from) memory.

If it does not work for your platform (and there is no other way to hook into FILE *), then you're out of luck.

The next thing I'd try is creating an anonymous pipe, (POSIX pipe, Windows CreatePipe), wrapping its writing side into FILE * (POSIX fdopen, plus Windows _open_osfhandle to get a CRT fd from HANDLE). Here you have to ensure that the pipe's buffer size is enough, or to spawn a thread for reading the pipe. Don't forget to fflush the writing side after the method is done (or use setbuf to disable buffering).

Upvotes: 4

Related Questions