I am using Cereal C++ v1.1.1 and similar to the example given in the documentation I am trying the following:
#include <sstream>
#include <iostream>
#include <cereal/archives/json.hpp>
int main() {
std::ostringstream os;
cereal::JSONOutputArchive archive(os);
int x = 12;
archive(CEREAL_NVP(x));
std::cout << os.str(); // JUST FOR DEMONSTRATION!
}
I expect to have the following:
{
"x":12
}
but the closing curly brace is missing. Any idea what is missing in the code?
Update:
adding archive.finishNode() seems to solve the problem. But I would say that it's not the solution. According to the operator() documentation, calling the operator serializes the input parameters, why should I add the finishNode extra?
I was having the same problem, and found the solution in a comment on an issue filed on Cereal's GitHub: https://github.com/USCiLab/cereal/issues/101
The documentation states "Archives are designed to be used in an RAII
manner and are guaranteed to flush their contents only on
destruction..." (http://uscilab.github.io/cereal/quickstart.html).
Your problem is that you are trying to print the contents of the
stringstream before the archive has been destroyed. At this point, the
archive has no idea whether you will want to write more data to it in
the future, so it refrains from streaming out the closing brace. You
need to make sure the archive's destructor has been called before
printing out the stringstream.
Try this:
int main()
{
std::stringstream ss;
{
cereal::JSONOutputArchive archive( ss );
SomeData myData;
archive( myData );
}
std::cout << ss.str() << std::endl;
return 0;
}
Please see the documentation for more information.
Related
If I want to write my own test.cpp that checks if another .cpp file is outputting the way I want it to output, is there anyway to do it without explicitly printing it?
In other words, is there anything such as
assert(output_of_file_being_tested, "this is the correct output");
where output_of_file_being_tested is something that's supposed to be "cout"ed.
The solution is not to hard-code the output stream. Pass a reference to std::ostream to your code somehow, and use std::stringstream to collect the output in test environment.
For example, this is the content of your "another .cpp" file:
void toBeTested(std::ostream& output) {
output << "this is the correct output";
}
So in your production/release code you may pass std::cout to the function:
void productionCode() {
toBeTested(std::cout);
}
while in the test environment you may collect the output to a sting stream and check it for correctness:
// test.cpp
#include <sstream>
#include <cassert>
void test() {
std::stringstream ss;
toBeTested(ss);
assert(ss.str() == "this is the correct output");
}
In addition to Sergey's great answer above, you may choose to have std::cout as a default parameter.
So, if you have a code:
// Only need console output
using std::cout;
...
void toBeTested()
{
cout << "This is the correct output.";
}
And it is used (or may be frequently used in the future) in many places:
int main()
{
...
toBeTested();
...
toBeTested();
...
// And so on...
return 0;
}
In order to avoid breaking a lot of code and maintaining a simple interface,
you can convert the above function to:
using std::cout;
...
void toBeTested(std::ostream& cout = std::cout)
{
cout << "This is the correct output.";
}
And your main does not need to be touched.
Note that cout of the function now overshadows cout of the global scope. Therefore, this cout can be any output stream, and does not interfere with the global cout.
And now you can test this as above!
#include <sstream>
#include <cassert>
...
void testMyFunctionDisplay()
{
// Arrange
std::ostringstream output_buffer;
// Act
toBeTested(output_buffer);
// Assert
assert(output_buffer.str() == "This is the correct output.");
}
However. it is not necessary to make every function in this way.
It is useful if we want to redirect that function's output to other output streams:
Stringstreams: If you want to use the output somewhere, perhaps for testing the module, or for other purposes in the program.
Files: If you want to maintain the output even after the program termination.
I need redirect the copy of std::cout to the file. I.e. I need see the output in console, and in file. If I use this:
// redirecting cout's output
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("c:\\temp\\test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
cout.rdbuf(backup); // restore cout's original streambuf
filestr.close();
return 0;
}
then I write string to the file, but I see the nothing in console. How can I do it?
The simplest you can do is create an output stream class that does this:
#include <iostream>
#include <fstream>
class my_ostream
{
public:
my_ostream() : my_fstream("some_file.txt") {}; // check if opening file succeeded!!
// for regular output of variables and stuff
template<typename T> my_ostream& operator<<(const T& something)
{
std::cout << something;
my_fstream << something;
return *this;
}
// for manipulators like std::endl
typedef std::ostream& (*stream_function)(std::ostream&);
my_ostream& operator<<(stream_function func)
{
func(std::cout);
func(my_fstream);
return *this;
}
private:
std::ofstream my_fstream;
};
See this ideone link for this code in action: http://ideone.com/T5Cy1M
I can't currently check if the file output is done correctly though it shouldn't be a problem.
You could also use boost::iostreams::tee_device. See C++ "hello world" Boost tee example program for an example.
Your code does not work, because it is the streambuf that determines where the output written to a stream end up, not the stream itself.
C++ does not have any streams or streambufs that support directing the output to multiple destinations, but you could write one yourself.
The following program prints 0.
#include <ostream>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string subjectString("subject");
std::ostream tempStream(NULL);
tempStream << subjectString;
std::ostream& updatedStream = tempStream;
std::stringstream ss;
ss << updatedStream;
std::cout << ss.str() << std::endl;
return 0;
}
Why?
EDIT
As per Niall's sugesstion, I tried:
#include <ostream>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string subjectString("subject");
std::stringbuf buffer;
std::ostream tempStream(&buffer);
buffer.sputn(subjectString.c_str(), subjectString.size());
std::stringstream ss;
ss << tempStream;
std::cout << ss.str() << std::endl;
return 0;
}
Even this prints an address. Not the actual string.
The construction of std::ostream requires a buffer (not NULL).
In addition, basic_stream objects are not copyable;
basic_ostream( const basic_ostream& rhs ) = delete;
Reference;
http://en.cppreference.com/w/cpp/io/basic_ostream/basic_ostream
Try something more like this;
// ...
std::stringbuf buffer;
std::ostream tempStream(&buffer);
// ...
To associate a buffer with the stream.
Following on some of the discussions and edits;
In general, I would not directly manipulate the buffer, you should rather use the stream instead tempStream.write(...). The exact details are beyond the immediate question/problem; being the initialisation of the first stream with the buffer and streaming content into that stream. If all you want to do with the code is check if the data is in the buffer, then you could use tempStream.rdbuf()->sgetn(...).
You have already mentioned that this is part of a larger problem.
In the context of some the comments here and the original problem; this could be a case in which direct manipulation of the buffer is needed (in much the same way as the stream would). Your implementation would need to be well tested since this is not "the usual" way of working with streams, but it can work; .rdbuf() is the manner in which you can get to the underlying buffer. I don't have an exact snippet (maybe that's another question), but you can "clear the buffer" by resetting the position(s) of the put and get areas to be the same (see the positioning, put and get area functions of the buffer - std::ostream::seekp was mentioned as being used to deal with this). I think you standard library implementation of stringstream could also offer some useful hints.
Because tempStream has no stream to hold anything.
ss.str() returns NULL (0).
For a project, I'd like to use stringstream to carry on data. To achieve this goal, I have to pass some stringstream as parameter to some function, but when I output the stringstreams, I see something like an address.
The code :
#include <iostream>
#include <sstream>
void doStuff(const std::iostream& msg)
{
std::cerr << msg << std::endl;
}
int main(void)
{
doStuff(std::stringstream("av"));
}
The output is :
0xbff4eb40
Can someone explains why I get an address when passing an rvalue ?
And why can't I pass a stringstream by value ?
You probably want to access the string on which the stringstream is storing its data:
void doStuff(const std::stringstream& msg)
{
std::cerr << msg.str() << std::endl;
}
What is happening in your code is that iostreams contain a void* operator which returns 0 if the stream contains any error or has reached EOF, and another value otherwise. This is usefull for error checking.
When you try to write you stream to std::cerr, the compiler realizes that the stream can be converted to a void* using that operator, and that a void* can be written to a ostream(the operator<< has been defined), and therefore uses it.
Note that i changed the method's signature so that it receives an std::stringstream as an argument, since std::iostream::str is not defined(this method is only available on string streams).
You get an address because it (like other streams) has a conversion to void * (which is primarily useful as a Boolean, to see whether reading/writing the stream has failed).
You can't pass it by value, because streams (again, in general, not just stringstreams) don't support copying and/or assigning.
To print the content of the stream, you could do something like:
void dostuff(std::iostream &msg) {
std::cerr << msg.rdbuf() << "\n";
}
Edit: Here's a complete demo program:
#include <iostream>
#include <sstream>
void show(std::ostream &os) {
std::cout << os.rdbuf() << "\n";
}
int main(){
std::stringstream test("whatever");
show(test);
return 0;
}
When I execute it, the output I get is the expected "whatever".
I have written a piece of code which writes either to console or to a file depending upon the boolean value set by user.
The code looks like this.
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout<<"bDump bool"<<std::endl;
std::cin>>bDump;
std::ostream* osPtr;
std::ofstream files;
if(bDump)
{
files.open("dump.txt");
osPtr = &files;
}
else
{
osPtr = &std::cout;
}
std::ostream& stream = *osPtr;
stream<<"hello";
if(bDump)
{
files.close();
}
return 0;
}
Here I am creating a std::ostream pointer and depending upon boolean value I am assinging address of either an ofstream object or std::cout. My only concern here whether the file operation like open or close are done properly or not. As I am new to c++ please help me out. Also point out if any bad programming practice is being followed here.
Its correct and works.
The main thing I would do differently is not to explicitly call close() as this is done automatically by the destructor.
You can simplify your code slightly (and get rid of the pointer) with the ternary operator;
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout << "bDump bool"<<std::endl;
std::cin >> bDump;
std::ofstream files;
std::ostream& stream = (bDump) ? (files.open("dump.txt"), files)
: std::cout;
stream<<"hello";
}
There's no potential leak. However, if an exception is thrown by
stream<<"hello";
then
files.close();
will never be called, but for your specific example of code there's no concern. ofstream's destructor happens to call close() for you.
You did everything fine, but there is no need for the close() at the end, because in C++ we rely on destructors to clean up for us, and std::ofstream has one which closes the file automatically.
You can also omit the return 0; statement at the bottom of main() in C++: 0 (success, really) will be returned by default.