I am looking for a way to use an ostream with my custom string class and overload the operator << to stream to the buffer which i can then flush to anywhere i want (in my case its just gonna be printed in a window)
I'm reasonably new to the inner workings of iostream's but from my understanding the method i've seen of making std::stringbuf a base of my custom stringstream would not work because the stringbuf deals with the std::string.
in essence i want to able to do this (or similar):
MyStringClass string
MyOutput << "hello" << string << "World" << std::endl;
Where MyOutput can be changed to print to anywhere i want.
Thank you.
Not a problem. Define your class, and within it's definition add an ostream& operator<<(const String&);.
Inside that operator, you can code whatever handling you want (look at std::string for inspiration)
Related
I'm working on a C++ beginner level project (not absolute beginner like "what's a loop" but I wouldn't say it's intermediate level either).
In this project I need to save into a file some data stored in memory in struct variables (this is plain imperative programming, with no OOP involved).
I've read a bit about options like serialization, using some non-standard libraries and such. But I need to keep it as simple and clean as possible.
So far I have 2 structs, pretty much like these:
struct client {
string name;
string address;
double phone;
};
struct invoice {
string client_name;
double total;
};
I'm looking for something like this example provided at http://www.cplusplus.com/doc/tutorial/files:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
Is there a way to do something like that, but to write (and then be able to read) struct variables to a file, keeping it simple?
Some years ago I remember handling this in a very simple way in Pascal, when writing records to files. It was something like: open file, write record field 1, write field separador, write record field 2, write field separator, write record separator. Then when reading I would search for separators. Is this not recommended in C++?
Thanks.
You could check serialization for C++, eg. Boost::serialization in the Boost library.
Is it possible to serialize and deserialize a class in C++?
You have to associate 2 functions to this class : inputStruct and OutputStruct. Input should be able to read what Output generate. The easy way consist in writing each struct element in the same order that they are implemented.
The clear way to do that is implementing a serialize and deserialize function for every structure or class that you want to write to a file. You give the serialize function the reference of the output stream, and it writes each of the fields that you want to write. The deserialize do the opposite: it reads all the properties in the same order, and sets them in the current class or structure. If you use the stream operators for serialization, the output file will be a text file.
With c++ you can overload stream operator, so it will look pretty in your code, but in other languages you must use functions for that.
You can also use binary serialization, but it is more problematic, because you need to check the endianness of the platform that you use currently. If you will just use it on one platform, you can try write, and read functions. They need the pointer of the variable, and the size, and they copy them into/from the file. Use these for every property separate, never copy whole structures, because it can lead to errors easily.
UPDATE:
I made serialize and deserialize functions. I haven't tested them, so im not 100% sure they will work.
Static functions:
void serialize_client( ofstream& out, client& cl )
{
out << cl.name << endl;
out << cl.address << endl;
out << cl.phone << endl;
}
void deserialize_client( ifstream& in, client& cl )
{
getline( in, cl.name );
getline( in, cl.address );
in >> cl.phone;
}
Usage:
client client_instance;
deserialize_client( cin, client_instance );
serialize_client( cout, client_instance );
With operator overload:
ostream& operator<<( ostream& os, const client& cl )
{
os << cl.name << endl;
os << cl.address << endl;
os << cl.phone << endl;
return os;
}
istream& operator>>( istream& is, client& cl )
{
getlise( is, cl.name );
getlise( is, cl.address );
is >> cl.phone;
return is;
}
client client_instance;
cin >> client_instance;
cout << client_instance;
I read that cout and cin are objects of classes std::istream and std::ostream. Can there be user defined objects like cout and cin ?
eg.
How can I do something like this :
ostream obj;
obj<<"string"<<endl;
EDIT 1 : I want to define an object that can replicate cout and cin without messing with their in-built definitions.
To handle strings I'd recommend using std::stringstream.
The std::stringstream class is derived from istream.
std::stringstream obj;
obj << "Hello World" << endl;
// You can convert it to a string afterwards
std::string myString = obj.str();
Yes, you can create any stream you want.
Since a stream is a flow of data with a source and a sink, you typically want to use either of the following:
std::stringstream - add data yourself, access it in stream form
std::{i,o}fstream - data comes from / goes to a file
std::cout and std::cin are particular instances of streams that happen to be connected to STDOUT and STDIN respectively, but there's no reason you can't make your own streams.
You just have to be precise and knowledgeable about what you actually want them to do.
I've created an fstream object to write info to files.
I write strings to the new file like
fStreamObject << "New message.\n";
because I want each << to print a string to the next line.
I want to be able to set a property and make a call like
fstreamObject << "New message.";
which will write the string to the next line.
Are there flags/settings for fstream objects that allows this to be done?
I've seen the different file modes (i.e. ofstream::in, ofstream::out, etc.), but I couldn't find one that auto writes to a new line. Also, I'm not looking to write my own solution. I want to be able to use a built in feature.
No, there are no readily configurable capabilities of that sort within the standard streams.
You may have to subclass the stream type and fiddle with operator<< to get this to work the way you want, or do it with a helper function of some description:
fstreamObject << nl("New message.");
(but that's hardly easier than just having the \n in there (for a string, anyway).
It depends on what you mean by "setting the stream". If we consider this to be fairly broad then the answer happens to be "yes"!
Here is how:
Create a stream buffer which inserts a newline every time it is flushed, i.e., when sync() is called. Otherwise it just forwards characters.
Change the file stream's stream buffer to use this stream buffer filtering to the file stream's stream buffer.
Set the flag std::ios_base::unitbuf which causes a flush after every [properly written] output operation.
Here are is the example code to do just that:
#include <iostream>
class newlinebuf
: public std::streambuf {
std::ostream* stream;
std::streambuf* sbuf;
int overflow(int c) { return this->sbuf->sputc(c); }
int sync() {
return (this->sbuf->sputc('\n') == std::char_traits::eof()
|| this->sbuf->pubsync() == -1)? -1: 0;
}
public:
newlinebuf(std::ostream& stream)
: stream(&stream)
, sbuf(stream.rdbuf(this)) {
stream << std::unitbuf;
}
~newlinebuf() { this->stream->rdbuf(this->sbuf); }
};
int main() {
newlinebuf sbuf(std::cout);
std::cout << "hello" << "world";
}
Although this approach work, I would recommend against using it! On problem is that all composite output operators, i.e., those using multiple output operators to do their work, will cause multiple newlines. I'm not aware of anything which can be done to prevent this behavior. There isn't anything in the standard library which enables just configuring the stream to do this: you'll need to insert the newline somehow.
No, the C++ streams do not allow that.
There is no way to decide where one insertion stops and the next starts.
For example for custom types, their stream-inserters are often implemented as calls to other stream-inserters and member-functions.
The only things you can do, is write your own class, which delegates to a stream of your choosing, and does that.
That's of strictly limited utiliy though.
struct alwaysenter {
std::ostream& o;
template<class X> alwaysenter& operator<<(X&& x) {
o<<std::forward<X>(x);
return *this;
}
};
I have to extend the ofstream class to write a logging stream service.
The goal is to intercept each line, adding at the head of each one a customized text (date/time, severity, and so on).
Now, it's clear that I'm not a C++ guru, so I read a lot of documentation about this task, e.g.
http://www.angelikalanger.com/Articles/Topics.html#CPP
http://asmodehn.wordpress.com/2010/06/20/busy-c-coding-and-testing
http://gabisoft.free.fr/articles-en.html
The above articles suggest to write a custom stream buffer, but during porting of this concept on file streams I encountered a lot of difficulties.
Is there a simpler method to achieve this goal?
You don't need to write a custom stream buffer; the simplest and most straightforward way is to make a class you can send output to by giving it a templatized single argument operator<<():
template <typename T>
std::ostream& operator<<(const T& data_)
{
m_outstream << m_severity << "\t" << getTimeStamp() << "\t" << data_;
return m_outstream;
}
Where m_outstream is some type of std::ostream (std::ofstream, etc). m_severity and getTimeStamp() are examples of what you can insert (and you can create a bog standard two argument operator<<() to format and output the severity type to an ostream).
This then allows you to do things like:
myLogger << "failingFunction(" << argument <<
"): Could not do something." << std::endl;
and you will get output on m_outstream that looks like:
WARNING 2012-01-03 19:32 failingFunction("argument value"): Could not do something.
Beyond this, you will want a way to set the severity, which can be as simple as a method called on the logger class you added the templatized operator<<() to. If you want to get really fancy, you can write your own manipulator that acts much like setw() would on a std::ostream. See http://www.math.hkbu.edu.hk/parallel/pgi/doc/pgC++_lib/stdlibug/man_6665.htm for a primer on writing manipulators.
I am looking for a portable way to implement lazy evaluation in C++ for logging class.
Let's say that I have a simple logging function like
void syslog(int priority, const char *format, ...);
then in syslog() function we can do:
if (priority < current_priority)
return;
so we never actually call the formatting function (sprintf).
On the other hand, if we use logging stream like
log << LOG_NOTICE << "test " << 123;
all the formating is always executed, which may take a lot of time.
Is there any possibility to actually use all the goodies of ostream (like custom << operator for classes, type safety, elegant syntax...) in a way that the formating is executed AFTER the logging level is checked ?
This looks like something that could be handled with expression templates. Beware, however, that expression templates can be decidedly non-trivial to implement.
The general idea of how they work is that the operators just build up a temporary object, and you pass that temporary object to your logging object. The logging object would look at the logging level and decide whether to carry out the actions embodied in the temporary object, or just discard it.
What I've done in our apps is to return a boost::iostreams::null_stream in the case where the logging level filters that statement. That works reasonably well, but will still call all << operators.
If the log level is set at compile time, you could switch to an object with a null << operator.
Otherwise, it's expression templates as Jerry said.
The easiest and most straight-forward way is to simply move the check outside of the formatting:
MyLogger log; // Probably a global variable or similar.
if (log.notice())
log << "notified!\n" << some_function("which takes forever to compute"
" and which it is impossible to elide if the check is inside log's"
" op<< or similar");
if (log.warn()) {
log << "warned!\n";
T x;
longer_code_computing(value_for, x); // easily separate out this logic
log << x;
}
If you really wanted to shorten the common case, you could use a macro:
#define LOG_NOTICE(logger) if (logger.notice()) logger <<
LOG_NOTICE(log) << "foo\n";
// instead of:
if (log.notice()) log << "foo\n";
But the savings is marginal.
One possible MyLogger:
struct MyLogger {
int priority_threshold;
bool notice() const { return notice_priority < current_priority; }
bool warn() const { return warn_priority < current_priority; }
bool etc() const { return etc_priority < current_priority; }
template<class T>
MyLogger& operator<<(T const &x) {
do_something_with(x);
return *this;
}
};
The problem here is mixing iostream-style operator overloading with a printf-like logging function – specifically translating manipulators and formatting flags/fields from iostreams into a format string. You could write to a stringstream and then chunk that to your syslog function, or try something fancier. The above MyLogger works easiest if it also contains an ostream reference to which it can forward, but you'll need a few more op<< overloads for iomanips (e.g. endl) if you do that.
For mine I made a debug_ostream class which has templated << operators. These operators check the debug level before calling the real operator.
You will need to define non-template overrides for const char* and std::ostream& (*x)(std::ostream&) because otherwise those don't work. I'm not sure why.
With inlining and high enough optimization levels the compiler will turn the whole output line into a single check of the debug level instead of one per output item.
I should add to this that this doesn't solve the original problem. For example if part of the debug line is to call an expensive function to get a value for output, that function will still be called. My solution only skips the formatting overhead.