Well, the iostream library is one of the very first C++ libraries. I
would call it broken by design. The fumbling with the shift operators
primarily makes the code unreadable, especially in conjunction with
formatting.
yep.
it is also notable that, for the most part, languages which followed
after C++ still tended towards more C-like interfaces regarding printing
(function or method, often with some sort of formatting string, and
arguments following after said string).
I personally much prefer printf as well, but granted I have also written
much more C code than I have C++ code, which could be a factor.
printf is still part of the C++ runtime. But take care about it's
variants. While printf and fprintf is usually safe, sprintf is
error-prone. Using inconsistent format characters is not the primary
problem. Some compilers print warnings about that. But buffer overflows
are difficult to handle with sprintf. In general one should avoid char*
for strings in C++. (const char* in contrast is often fine.)
generally agreed.
although, I think the issue isn't so much about "char *" vs "const char
*" vs "std::string" or similar, but often the (generally unsafe)
practice of regarding strings as mutable buffers.
in my case, I tend to regard strings as immutable by default, but
usually the const keyword is not used given the compiler often taking
issue with const and non-const char-pointers being mixed (implicit
conversions, ...), so more often the "const" is implied. this could be
fixed (by switching to consistently using "const char *", or probably a
typedef thereof), but the codebase is large enough to where doing so
would be a hassle.
however, sadly, a lot of code in my case still uses a lot of temporary
char arrays as buffers as well, which albeit unsafe, there are few
"good" alternatives in the general case (at least in plain C land).
however, it is a convention in my case to (usually) make some effort to
avoid running past the end of the buffer (typically by comparing the
current target-pointer against a target-buffer-end pointer). this is at
least generally safer (if applied consistently), without some of the
potentially steep costs of some other options (higher implementation
complexity, poor performance, ...).
for, example rather than simply something like:
while(*s)*t++=*s++;
a person can instead write something like:
while(*s && t<te)*t++=*s++;
which is not particularly more complicated, or significantly slower, but
can have the advantage of not running past the end of the buffer (given
by 'te').
or, if the code in question is C++, a person can also just use std::string.
In fact I prefer printf syntax in almost all cases of logging and human
readable formatting. To be save I use a sprintf variant that safely
prints into a string class with matching storage, std::string or
whatever. vsnprintf, supported by many platforms makes this quite easy
to implement.
yeah.
snprintf and vsnprintf are good idea, but have the drawback of being
absent on some compilers (including MSVC last I checked).
it is possible to work around this and some of the other issues by
implementing a custom version of the printing function, but this is
admittedly kind of a hassle (as is implementing all of the various
formatting options).
If it fits your needs: use it.
yep.
I personally believe there is no real "right" or "wrong" in regards to
programming, rather it is more about costs and benefits, ...
one thing I ran across before was a convention known as "SWOT"
(Strengths, Weaknesses, Opportunities, Threats), which is IMO a
moderately more useful convention for classifying various development
options.
I often use this internally, but often end up expressing them more in
terms of a pros/cons convention (so: pros=strengths+opportunities, and
cons=weaknesses+threats), usually because this is easier to express
(don't need 4 categories).
so, the "good" option is that with more good points, and the "bad"
option is that with more bad points, rather than some sort of law etched
in stone somewhere ("all X much be done using Y" or similar).
similarly, anything which can be implemented is possible (even if
potentially counter-intuitive), because programming is about writing
things (and not merely invoking language features), ...
granted, I have gotten into pointless arguments with people about these
sorts of things. ( I wrote some about it, but decided to leave it out as
it was starting to look like a bit of a pointless rant, which will often
cause people to try to argue about it, which isn't really productive. )
You won't get happy with the iostream library if you inter-operate with
files of Fortran number crunchers.
yep, among other things...