Reputation: 15082
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
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
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