printing in C++

Discussion in 'C++' started by Stefan Ram, Mar 14, 2013.

  1. Stefan Ram

    Stefan Ram Guest

    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.)
    Stefan Ram, Mar 14, 2013
    #1
    1. Advertising

  2. Stefan Ram

    Stefan Ram Guest

    Christian Gollwitzer <> writes:
    >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.
    Stefan Ram, Mar 14, 2013
    #2
    1. Advertising

  3. Stefan Ram

    Rui Maciel Guest

    Christian Gollwitzer wrote:

    > 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
    Rui Maciel, Mar 14, 2013
    #3
  4. Stefan Ram

    James Kanze Guest

    On Thursday, March 14, 2013 6:43:38 AM UTC, Stefan Ram wrote:
    > Christian Gollwitzer <> writes:


    > >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.


    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).

    --
    James
    James Kanze, Mar 14, 2013
    #4
  5. Stefan Ram

    James Kanze Guest

    On Thursday, March 14, 2013 7:28:50 AM UTC, Juha Nieminen wrote:
    > Stefan Ram <-berlin.de> wrote:


    > > 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; }


    > 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.)

    --
    James
    James Kanze, Mar 14, 2013
    #5
  6. Stefan Ram

    Luca Risolia Guest

    On 14/03/2013 06:32, Stefan Ram wrote:
    > 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';
    }
    Luca Risolia, Mar 14, 2013
    #6
  7. Stefan Ram

    Rui Maciel Guest

    Christian Gollwitzer wrote:

    > 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
    Rui Maciel, Mar 14, 2013
    #7
  8. Stefan Ram

    Öö Tiib Guest

    On Thursday, 14 March 2013 21:01:47 UTC+2, Juha Nieminen wrote:
    > James Kanze <> wrote:
    > >> 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.

    >
    > 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, Mar 14, 2013
    #8
  9. Stefan Ram

    Öö Tiib Guest

    On Thursday, 14 March 2013 23:16:38 UTC+2, Öö Tiib wrote:
    > 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, Mar 14, 2013
    #9
  10. Stefan Ram

    Öö Tiib Guest

    On Friday, 15 March 2013 11:05:54 UTC+2, Andy Champ wrote:
    > On 14/03/2013 21:16, Öö Tiib wrote:
    > > 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*'.

    >
    > 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.
    Öö Tiib, Mar 15, 2013
    #10
  11. On 2013-03-14 15:23, Öö Tiib wrote:
    >
    > http://boost-log.svn.sourceforge.ne...y/string_literal.hpp?revision=848&view=markup


    It looks like something that std::basic_string should have been
    derived from.

    Another similar example is StringRef from LLVM:
    http://www.llvm.org/docs/ProgrammersManual.html#llvm-adt-stringref-h
    http://www.llvm.org/doxygen/classllvm_1_1StringRef.html

    It is sad to see how the omission of such a class from the standard
    library has caused proliferation of similar variants here and there.

    --
    Seungbeom Kim
    Seungbeom Kim, Mar 15, 2013
    #11
  12. On 2013-03-15 23:10, Paavo Helde wrote:
    > Seungbeom Kim <> wrote in
    > news:ki07hb$87d$:
    >
    >> On 2013-03-14 15:23, Öö Tiib wrote:
    >>>
    >>> http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/
    >>> boost/log/utility/string_literal.hpp?revision=848&view=markup

    >>
    >> It looks like something that std::basic_string should have been
    >> derived from.

    >
    > 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.

    --
    Seungbeom Kim
    Seungbeom Kim, Mar 16, 2013
    #12
  13. Stefan Ram

    James Kanze Guest

    On Saturday, March 16, 2013 6:10:38 AM UTC, Paavo Helde wrote:
    > Seungbeom Kim <> wrote in
    > news:ki07hb$87d$:
    >
    > > On 2013-03-14 15:23, Öö Tiib wrote:
    > >>
    > >> http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/
    > >> boost/log/utility/string_literal.hpp?revision=848&view=markup

    > >
    > > It looks like something that std::basic_string should have been
    > > derived from.

    >
    > 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.

    --
    James
    James Kanze, Mar 16, 2013
    #13
  14. Stefan Ram

    Öö Tiib Guest

    On Saturday, 16 March 2013 17:55:23 UTC+2, Seungbeom Kim wrote:
    > On 2013-03-15 23:10, Paavo Helde wrote:
    > > Seungbeom Kim <> wrote:
    > >> On 2013-03-14 15:23, Öö Tiib wrote:
    > >>>
    > >>> http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/
    > >>> boost/log/utility/string_literal.hpp?revision=848&view=markup
    > >>
    > >> It looks like something that std::basic_string should have been
    > >> derived from.

    > >
    > > 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.


    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, Mar 16, 2013
    #14
  15. Stefan Ram

    Öö Tiib Guest

    On Saturday, 16 March 2013 18:47:14 UTC+2, James Kanze wrote:
    > On Saturday, March 16, 2013 6:10:38 AM UTC, Paavo Helde wrote:
    > > Seungbeom Kim <> wrote:
    > > > On 2013-03-14 15:23, Öö Tiib wrote:
    > > >> http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/
    > > >> boost/log/utility/string_literal.hpp?revision=848&view=markup
    > > >
    > > > It looks like something that std::basic_string should have been
    > > > derived from.

    > >
    > > 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?


    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.
    Öö Tiib, Mar 16, 2013
    #15
  16. Stefan Ram

    James Kanze Guest

    On Saturday, March 16, 2013 4:56:16 PM UTC, Öö Tiib wrote:
    > On Saturday, 16 March 2013 17:55:23 UTC+2, Seungbeom Kim wrote:


    > 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.

    --
    James
    James Kanze, Mar 16, 2013
    #16
  17. Stefan Ram

    James Kanze Guest

    On Saturday, March 16, 2013 5:46:30 PM UTC, Öö Tiib wrote:
    > On Saturday, 16 March 2013 18:47:14 UTC+2, James Kanze wrote:
    > > > 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?


    > 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.


    If str<n> are pointers, then it will work. If they aren't
    pointers, then we're not speaking about concatenation.

    > > 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
    > ... 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 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.


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

    --
    James
    James Kanze, Mar 16, 2013
    #17
  18. Stefan Ram

    Ian Collins Guest

    James Kanze wrote:
    > On Saturday, March 16, 2013 4:56:16 PM UTC, Öö Tiib wrote:
    >> On Saturday, 16 March 2013 17:55:23 UTC+2, Seungbeom Kim wrote:

    >
    >> 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.


    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.

    --
    Ian Collins
    Ian Collins, Mar 16, 2013
    #18
  19. Stefan Ram

    Öö Tiib Guest

    On Sunday, 17 March 2013 00:17:48 UTC+2, James Kanze wrote:
    > On Saturday, March 16, 2013 4:56:16 PM UTC, Öö Tiib wrote:
    > > 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.


    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.
    Öö Tiib, Mar 16, 2013
    #19
  20. Stefan Ram

    Stefan Ram Guest

    James Kanze <> writes:
    >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.
    Stefan Ram, Mar 16, 2013
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jon B
    Replies:
    7
    Views:
    7,500
    =?Utf-8?B?SmFzb25DaG9p?=
    Jan 30, 2006
  2. JustSomeGuy
    Replies:
    13
    Views:
    506
    msalters
    Dec 9, 2004
  3. iffy agbim
    Replies:
    1
    Views:
    105
    Mark Andrews
    May 24, 2004
  4. iffy agbim
    Replies:
    0
    Views:
    101
    iffy agbim
    May 21, 2004
Loading...

Share This Page