Convert from C++ style printing to my_printf() - c++

C++ purists may want to look away now. You will hate this.
I have been given an open source windows console app that I am merging with a pre-existing, very old, very large windows app of my own. My old program started life as pure C though recently has been tweaked so that it can compile as C++. My program makes extensive use of a my_printf() function which prints text to a window.
The old console app does its printing C++ style via streams (I have never used this type of printing mechanism before).
When converting the console app to work under my system I could manually edit all the lines that do printing so that they use my_printf() instead. But before I embarked on that I thought I'd just check with StackOverflow to see if I was missing a trick. For example I could imagine somehow letting the C++ prints be done via the stream and then somehow scooping the final text somewhere and then calling my_printf() with the result. Might that be possible?
EDIT: please note my knowledge of C++ is extremely limited and I may need to look some things up in order to understand your answers so please use language that facilitates this.

There's indeed a trivial trick. But C++ impurists will hate the fact that C++ has a pure solution ;)
std::ostream is responsible for formatting, but not printing itself. That's handled by std::streambuf. std::cout combines a std::ostream formatter with a std::streambuf-derived object that writes to stdout.
However, you can change the streambuf backing an ostream with ostream::rdbuf(newbuf). As std::cout is just another ostream, you can replace its streambuf too. In this case, you only need to come up with a streambuf-derived class that writes already-formatted output to my_printf(). That should be quite trivial.

You might find string streams useful. For example:
std::ostringstream os;
os << "Print " << whatever << data;
my_printf( "%s", os.str().c_str() );
In case you were feeling adventurous, you could write your own streambuf instead that used my_printf underneath, and inject it into the stream object that is currently used in output statements (e.g. std::cout). Be warned that this latter approach might not be trivial, however it would result in almost no changes to existing codebase.

Subclass std::ostream and make operator << call my_print_f(). You can use internal stringstream in your stream to retrieve string representation of operator << arguments.
Then you'd just have to do find&replace, replacing cout (or whatever stream you directed your output to in the console app) with an instance of your stream class.

Something along these lines might be helpful:
http://www.codeproject.com/KB/debug/debugout.aspx
Should be obvious where the meat of it is, so you can make it print via your own systems, or what have you. In theory, you'd need only search for references to std::cout and replace them with references to your own object.

Overloading the global operator<< is probably what will solve your problem:
#include <iostream>
#include <cstdio>
static int
my_printf (const char* s)
{
printf ("my_printf: %s\n", s);
}
namespace std {
std::ostream& operator<< (std::ostream& out, const char* s)
{
my_printf (s);
return out;
}
}
int
main ()
{
std::cout << "hello, world"; // => my_printf: hello, world
return 0;
}

Related

Question std::cout in C++ how exactly does the stream work?

Say we have:
std::cout << "Something";
How exactly is this working? I just want to make sure I understand this well and, from what I've been reading, is it okay to say that basically the insertion operator inserts the string literal "Something" into the standard output stream?
But what happens after that? Where does the standard output stream lead? Can anyone explain this?
That's basically the only part I don't get: I have the string literal "Something" in the standard output stream, but where does the stream lead?
The technical details vary between the different Operating Systems, but the basics are the same:
Every program has usually 3 standard streams: out (cout), in (cin), and err (cerr) (same as out, but used for errors). Those streams are nothing on their own; they exist to be used by a third party. That third party may be, for example, the terminal. When you execute a program form the terminal, it attaches to the program streams and show their output/request their input in the terminal.
If you wanted to do the same, you could execute a command yourself from your program, and take the out/in/err streams to read or write from/to them.
You have an example of that here: How do I execute a command and get the output of the command within C++ using POSIX?
Edit: When talking about C++, remember that cout << "anything" is just syntactic sugar for the function cout.operator<<("anything"). And that function "simply" writes to the stream
so,'std' is the namespace in which is stored everything found in the standard library , so basically you are saying "hey C++, go to 'std' storage and find cout command and run it" at least I know 'std' is this. and when you are saying using namespace std; you tell the compiler "take everything that's in the std namespace and dump it in the global namespace".
I hope it helped you to understand.

How to properly reroute output (away from std::cout)?

I have heard several times, that one should avoid plain writes to std::cout. (Is this correct?) However, I did not find good examples of how to achieve this. What I came up with so far is this:
#include <iostream>
class Logger {
std::ostream os;
auto RdBuffer( bool const decision ) { return decision ? std::cout.rdbuf() : nullptr; }
public:
explicit Logger( bool const use_cout = true ) : os( RdBuffer( use_cout ) ) {}
void Print() {
os << "Ptinting" << std::endl;
}
};
It allows me to write to std::cout if wanted, or stays silent otherwise. It seems to work, but I'm not sure this is the correct approach. What worries me in particular is the initialization with the nullptr and the consecutive writing to it in case the bool is set to false.
Is this going in the right direction? I'm particular interested in modern C++ ways of achieving this. So C++11 or newer answers are greatly appreciated.
Edit: Corrected typo in code.
I have heard several times, that one should avoid plain writes to std::cout. Is this correct?
No. It is accepted practice to write output to the standard output stream - unless you're in some embedded setting, or using an exotic OS where output is handled very differently.
The operating system and other processes will expect output to be written to that stream, or to whatever it represents (e.g. the standard output file handle on Unix-like systems).
What I came up with so far is this [piece of code here]
Well,
There are several popular logging libraries for C++. Here's a question about that over at SoftwareRecs.SX. No need to re-invenet the wheel if what you want is to do logging.
As #largest_prime_is_463035818 suggests in their comment, it's often good enough to just pass around an std::ostream and write to that. And when you want to not write anywhere - that's possible too; read these SO questions:
Standard no-op output stream
Printing to nowhere with ostream
Having said all this - there are some cases in which you might legitimately want to have std::cout itself be redirected to print somewhere else. I don't think that's covered by the standard, though.

Using std::cout on STM32 microcontroller

I managed to use printf() on my STM32 (CortexM7) compiling under C++, by defining functions like _write and _read and so on.
But I wanted to use std::cout instead of printf. However including <iostream> yields like 300 errors.
Do you know what has to be done to use cout with custom char printing functions?
Compiler used G++ 6.2.
I have found partial solution. You can make class (even name it cout) and overload operator << for different types and inside execute printf() with proper format string. Maybe not most efficient but for UART is ok.
So I don't need answer anymore, but if someone knows, then for curiosity you can post it.

Is it OK to use iostreams with int as character-type?

When trying to come up with an answer to this question, I wrote this little test-program:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
void writeFile() {
int data[] = {0,1,2,3,4,5,6,7,8,9,1000};
std::basic_ofstream<int> file("test.data", std::ios::binary);
std::copy(data, data+11, std::ostreambuf_iterator<int>(file));
}
void readFile() {
std::basic_ifstream<int> file("test.data", std::ios::binary);
std::vector<int> data(std::istreambuf_iterator<int>(file),
(std::istreambuf_iterator<int>()));
std::copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main()
{
writeFile();
readFile();
return 0;
}
It works as expected, writing the data to the file, and after reading the file, it correctly prints:
0 1 2 3 4 5 6 7 8 9 1000
However, I am not sure if there are any pitfalls (endianess issues aside, you always have these when dealing with binary data)? Is this allowed?
It works as expected.
I'm not sure what you are expecting...
Is this allowed?
That's probably not portable. Streams relies on char_traits and on facets which are defined in the standard only for char and wchar_t. An implementation can provides more, but my bet would be that you are relying on a minimal default implementation of those templates and not on a conscious implementation for int. I'd not be surprised that a more in depth use would leads to problems.
Instantiating any of the iostream classes, or basic_string, on anything
but char or wchar_t, without providing a specific custom traits class,
is undefined behavior; most of the libraries I've seen do define it to
do something, but that definition often isn't specified, and is
different between VC++ and g++ (the two cases I've looked at). If you
define and use your own traits class, some of the functionality should
work.
For just about all of the formatted inserters and extractors (the << and
>> operators), istream and ostream delegate to various facets in
the locale; if any of these are used, you'll have to take steps to
ensure that these work as well. (This usually means providing a new
numpunct facet.)
Even if you only use the streambuf (as in your example), filebuf
uses the codecvt facet. And an implementation isn't required to provide
a codecvt, and if it does, can do pretty much whatever it wants in
it. And since filebuf always writes and reads char to and from the
file, this translation must do something. I'm actually rather
surprised that your code worked, because of this. But you still don't
know what was actually on the disk, which means you can't document it,
which means that you won't be able to read it sometime in the future.
If your goal is to write binary data, your first step should be to
define the binary format, then write read and write functions which
implement it. Possibly using the iostream << and >> syntax, and
probably using a basic_streambuf<char> for the actual input and
output; a basic_streambuf<char> that you've carefully imbued with the
"C" locale. Or rather than define your own binary format, just use an
existing one, like XDR. (All of this paragraph supposes that you want
to keep the data, and read it later. If these are just temporary files,
for spilling temporary internal data to disk during a single run, and
will be deleted at the end of the program execution, simpler solutions
are valid.)

Internal "Tee" setup

I have inherited some really old VC6.0 code that I am upgrading to VS2008 for building a 64-bit app. One required feature that was implemented long, long ago is overriding std::cout so its output goes simultaneously to a console window and to a file. The implementation depended on the then-current VC98 library implementation of ostream and, of course, is now irretrievably broken with VS2008. It would be reasonable to accumulate all the output until program termination time and then dump it to a file. I got part of the way home by using freopen(), setvbuf(), and ios::sync_with_stdio(), but to my dismay, the internal library does not treat its buffer as a ring buffer; instead when it flushes to the output device it restarts at the beginning, so every flush wipes out all my accumulated output. Converting to a more standard logging function is not desirable, as there are over 1600 usages of "std::cout << " scattered throughout almost 60 files. I have considered overriding ostream's operator<< function, but I'm not sure if that will cover me, since there are global operator<< functions that can't be overridden. (Or can they?)
Any ideas on how to accomplish this?
You could write a custom stream buffer and attach it to cout with cout.rdbuf(). Your custom stream buffer would then tee the data to cout's original stream buffer and to a stream buffer stolen from an appropriate ofstream.
ofstream flog("log.txt");
teebuf tb(flog.rdbuf(), cout.rdbuf());
cout.rdbuf(&tb);
For your teeing stream buffer you can get an inspiration from this page.
You could use the pre-processor:
#define cout MyLogger
to inject new code.