printing in C++

S

Stefan Ram

I was asked to explain pointers. I thought the following would
be a nice example for pointer arithmetics. But I have a question
below.

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <iomanip> /* ::std::setw */
#include <cstdio> /* ::std::printf */

const char * mon( int const m, int const lang )
{ return "Jan" "Feb" "Mar" "Apr" "Mai" "Jun" "Jul" "Aug" "Sep" "Okt" "Nov" "Dez"
"jan" "feb" "mar" "apr" "may" "jun" "jul" "aug" "sep" "oct" "nov" "dec"
+ 3 *( m - 1 )+ 3 * 12 * lang; }

int main()
{ ::std::printf( "%.3s\n", mon( 5, 0 ));
::std::printf( "%.3s\n", mon( 5, 1 )); }

This will print:

Mai
may

I know that I do not have to #include <ostream>.

But how do I »translate« the Cish printf into the C++ish <<?
(The problem is the translation of the maximum field width.)
 
S

Stefan Ram

Christian Gollwitzer said:
I tend to disagree. C style strings are one of the worst "inventions" in
the C language, an abuse of pointers. A modern reconstruction of C++
would have std::string as the type of a string literal.

We have

L"abc"

for a const wchar_t array or

u8"abc"

for UTF-8 strings. So, there should not have been a
technical reason not to introduce, say,

s"abc"

for an ::std::string value. The committee must have had
some reason not to introduce such literals.
 
R

Rui Maciel

Christian said:
Thus argument is fundamentally flawed: "If nobody proved Riemann's
conjecture yet, there must be a reason. Therefore, the conjecture is
wrong."

That's a poor comparison. Adding support for a new string literal to a
programming language isn't exactly on par with one of science's most famous
unproved conjectures. This comparison is even sillier once we account for
the fact that C++'s newest standard support user-defined literals.

I can't think of any good reason why a plain "bla" should not be a
std::string, besides backwards compatibility.

Backwards compatibility is a good reason all in itself.

Nevertheless, the std::string is not a primitive type, and the C++ standard
does not require it to be available in some standard-compliant
implementations. Your requirement would essentially force C++ out of some
application domains. That's another good reason for not making that
mistake.


<snip/>


Rui Maciel
 
J

James Kanze

We have

for a const wchar_t array or

for UTF-8 strings. So, there should not have been a
technical reason not to introduce, say,

for an ::std::string value. The committee must have had
some reason not to introduce such literals.

I think the goal was to create some sort of user defined
literals, and let std::string get caught up with these. If so,
they failed, since std::string is not a literal type (which
would require a trivial destructor).

In the meantime: "abc" should be type std::string, and we'd need
c"abc" to get the old C style string (but how many programs
would _that_ break).
 
J

James Kanze

That's a rather obfuscated and hackish way of doing that. (It also is bad
in that the calling code must assume that only 3 characters must be used
from the returned value, without there being an ending 0.)
The normal solution to doing that is to use a char* array containing all
the names, and indexing that array.

The normal solution would also involve returning a std::string.

Unless you're implementing something like a garbage collector,
of a new implementation of malloc, you really shouldn't be using
pointer arithemtic, at least not explicitly. (Under the hood,
of course, a is pointer arithmetic. But you don't have to,
and probably shouldn't think of it as such, at least if you want
to write readable code.)
 
L

Luca Risolia

int main()
{ ::std::printf( "%.3s\n", mon( 5, 0 ));
::std::printf( "%.3s\n", mon( 5, 1 )); }

This will print:

Mai
may

I know that I do not have to #include <ostream>.

But how do I »translate« the Cish printf into the C++ish <<?
(The problem is the translation of the maximum field width.)

struct width {
const std::size_t n_;
explicit width(std::size_t n) noexcept : n_ {n} {}
std::eek:stream& operator()(std::eek:stream& o, const char* s) const {
for (size_t i = 0; i < n_ && s; ++i) // ok for few chars
o << s;
return o;
}
};

struct Wrapper {
std::eek:stream& o_;
const width& w_;
Wrapper(std::eek:stream& o, const width& w) noexcept : o_(o), w_(w) {}
};

Wrapper operator<<(std::eek:stream& o, const width& w) noexcept {
return Wrapper(o, w);
}

std::eek:stream& operator<<(const Wrapper& wr, const char* s) {
return wr.w_(wr.o_, s);
}

int main() {
std::cout << width(3) << mon(5, 0) << '\n';
std::cout << width(3) << mon(5, 1) << '\n';
}
 
R

Rui Maciel

Christian said:
I know of none which borrowed C-style string handling. I'm sure you are
aware of all the shortcomings of representing a string as a memory
address to the beginning of a sequence, terminated by a special
character

At least one of the men behind C, Dennis Ritche, was well aware of that. As
the story goes, he considered the pros and cons of a couple of methods, and
he picked the one which he saw as the better choice.

http://en.wikipedia.org/wiki/Null-terminated_string


Considering the options available and also the state of the art back then,
whether he picked one way or the other there would always be someone smarter
than both him and his colleagues complaining about the braindead decisions
they've made.


Rui Maciel
 
Ö

Öö Tiib

If the returned strings are static, then what possible advantage could
there be in returning std::strings? I can think only of disadvantages.

std::string contains size information. Extracting it from char const* is
O(n). Most string usages benefit from length being O(1).
If the calling code really wants to use std::strings, it's easy enough
to assign the return value to one. It's not like returning const char
pointers would impede that in any way.

From where you get those 'char const*'?
However, if the calling code would benefit (in terms of efficiency)
from having just char pointers to static strings, then the function
forcefully converting them to std::string and returning such objects
serves no useful purpose whatsoever, other than stop the calling code
from taking advantage of the static nature of the data.

Yes, but please bring example. When can char const* be efficient?
What's worse, many implementations of std::string do not use any kind
of short string optimization, meaning that they will always allocate
a new memory block every time the function returns a value, and we all
should know how amazingly inefficient memory allocation is in C/C++.
And for what?

Nothing to do. If the software you write is worth writing at all then
i18n becomes soon necessity. With i18n you have 0 string literals, every
string is dynamically serialized from language file. You have size
information when serializing. So you either use well-performing
'string const&' that contains the size information or throw size
information away and use weakly performing 'char const*'.

Apparently I miss some case, but please put it onto table?
 
Ö

Öö Tiib

Nothing to do. If the software you write is worth writing at all then
i18n becomes soon necessity. With i18n you have 0 string literals, every
string is dynamically serialized from language file. You have size
information when serializing. So you either use well-performing
'string const&' that contains the size information or throw size
information away and use weakly performing 'char const*'.

Forgot one case. Various debug logs are often done without translations
so there may be string literals on such case. Passing pointers to those
literals around as 'char const*' is still wasting performance.

Example with boost licence that looks OK on first glance (just
googled for it):

http://boost-log.svn.sourceforge.ne...y/string_literal.hpp?revision=848&view=markup

Disclaimer: I haven't tested it. I just have cut feeling that it
performs better than 'char const*'.
 
Ö

Öö Tiib

Umm. Not necessarily true, for two reasons - We write software which is
not intended for retail use, and for that reason we can get away with
writing in English only. As you are nicely demonstrating, most educated
people have a reasonable grasp of English.

The people like to use local tongue if possible. In user interface the
text is one of cheapest things anyway so the std::string just helps to
save some development time.

If there really is a reason to massively use string literals and
converting to std::strings affects performance then use a class like
in link I posted in second message and not 'char const*'. It seems
to cooperate well with strings.
And the other one - for i18n you don't want to use char* on most
systems, but wchar_t* to get Unicode. ISTR you're from a Unix
background, where UTF8 is generally used, but that's not the case
on PC or I think Mac.

wchar_t on Mac is UTF-32 since 2001. Before that it was UTF-16. On OS
level there is suport for all 5 UTFs. Pages in web browsers are mostly
UTF-8. The XML transported in various text-based protocols is also
UTF-8. Most unixes have wchar_t that is UTF-32, but in practice all
use UTF-8.

Most sane seems to pick internally one UTF encoding, stick to it and
convert to everything else in outside interfaces when needed.
BTW how _do_ you pronounce your name?

Öö is pronounced like emphasized 'i' in 'bird' or 'girl'. Tiib is
pronounced like 'T-Ball' suddenly stopped at B.
 
S

Seungbeom Kim

S

Seungbeom Kim

No, you don't want to derive std::string from anything and pay the penalty
of virtual function access all over the place. We already have stringstream
which is full of virtual functions and which is several times slower than
std::string when concatenating strings from pieces (yes I have measured
it), although this should be one of the main usage cases for stringstreams.

No, I didn't mean that virtual functions should be used; I thought that
dynamic polymorphism would not be necessary. Now I realize that, even
though it is possible to derive basic_string from basic_string_literal
using only nonvirtual functions, it would restrict the implementation
of basic_string and may not be desirable.
 
J

James Kanze

No, you don't want to derive std::string from anything and pay the penalty
of virtual function access all over the place. We already have stringstream
which is full of virtual functions and which is several times slower than
std::string when concatenating strings from pieces (yes I have measured
it), although this should be one of the main usage cases for stringstreams.

Why should this be one of the main usage cases for stringstream?
The "abstraction" of istream and ostream is converting to and
from an external human readable format. I don't see where is
should even occur to someone to use them for just concatenation.
 
Ö

Öö Tiib

No, I didn't mean that virtual functions should be used; I thought that
dynamic polymorphism would not be necessary. Now I realize that, even
though it is possible to derive basic_string from basic_string_literal
using only nonvirtual functions, it would restrict the implementation
of basic_string and may not be desirable.

The classes work side by side. It is similar as how std::array was added for cases
where std::vector is wastefully dynamic. I have strong belief that after C++11 we
really do not need to use any naked pointers in everyday programming. If there is
one then enwrapping it makes the code always safer and often better performing.
 
Ö

Öö Tiib

Why should this be one of the main usage cases for stringstream?

One may use stringstream on case when str1 + str2 + str3 does not work.
For example when he needs to concatenate information in dynamic array into
string.
The "abstraction" of istream and ostream is converting to and
from an external human readable format.

Modern times "human readable" text is used a lot in interfaces ... externalor
internal. With external interfaces the latency and through-put of carrying
media is the bottle-neck. Efficiency of streaming does not matter there
much. stingstream is used more in internal interfaces. There media is
memory and bottle-neck is stringstream.
I don't see where is should even occur to someone to use them for just
concatenation.

I trust that Paavo meant that concatenation is operation of stringstream
that it does a lot when used for anything.
 
J

James Kanze

I
have strong belief that after C++11 we really do not need to
use any naked pointers in everyday programming.

Most pointers in well written C++ are for navigation, and should
be raw pointers. Smart pointers have they uses, but they still
correspond to exceptional cases, rather than the usual case.
 
J

James Kanze

One may use stringstream on case when str1 + str2 + str3 does
not work. For example when he needs to concatenate
information in dynamic array into string.
Modern times "human readable" text is used a lot in interfaces
... external or internal. With external interfaces the latency
and through-put of carrying media is the bottle-neck.
Efficiency of streaming does not matter there much.
stingstream is used more in internal interfaces. There media
is memory and bottle-neck is stringstream.

There's never any reason to use stringstream for internal
interfaces. You should be using struct. As long as the
interface is internal, there's no reason to format; both sides
understand the same internal representation.
I trust that Paavo meant that concatenation is operation of stringstream
that it does a lot when used for anything.

I don't know what Paavo meant, but using stringstream for
concatenation is _not_ good practice.
 
I

Ian Collins

James said:
Most pointers in well written C++ are for navigation, and should
be raw pointers. Smart pointers have they uses, but they still
correspond to exceptional cases, rather than the usual case.

One of the most common constructs in my code is containers of smart
pointers, so I don't see from where you derive that generalisation.
 
Ö

Öö Tiib

Most pointers in well written C++ are for navigation, and should
be raw pointers.

Why? For navigation there are usually iterators. While standard allows
raw pointers as iterators all modern implementations use special
classes that are as efficient and lot safer.
Smart pointers have they uses, but they still
correspond to exceptional cases, rather than the usual case.

Pointer has several usages: container (array), iterator of container,
optional object and for polymorphic object. It is best alternative
for none of the tasks.

Smart pointers have taken over two last usages, being as efficient and
safer.
 
S

Stefan Ram

James Kanze said:
There's never any reason to use stringstream for internal
interfaces. You should be using struct. As long as the
interface is internal, there's no reason to format; both sides
understand the same internal representation.

Think of an interface »account« containing the function

withdraw( double amount )

. Eventually someone notices that they want to change the
internal representation to a type »decimal« instead of
double. But sadly, the interface still uses double.

Only interfaces that only use strings for all values
really encapsulate the internal representation so that
it can be changed without breaking the interface:

withdraw( string amount )

Admittedly, permanent internal serializing and
deserialization is reducing the execution speed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top