function for printing formatted number

Discussion in 'C++' started by wang, Aug 22, 2010.

  1. wang

    wang Guest

    Hi all
    is there a function for converting a number such as 1234567.89 into a
    string presentation as "1,234,567.89" for printing? Thanks for any
    hints!
    kwwang
     
    wang, Aug 22, 2010
    #1
    1. Advertising

  2. wang <>, on 21/08/2010 18:37:18, wrote:

    > Hi all
    > is there a function for converting a number such as 1234567.89 into a
    > string presentation as "1,234,567.89" for printing? Thanks for any
    > hints!
    > kwwang


    Nothing straight out of the standard C++ box.

    Make a search in boost, there could be an appropriate "format" function,
    although such a simple function can be created in almost no time. Why
    don't you give it a shot and post your code here? You might find that
    instructive.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 22, 2010
    #2
    1. Advertising

  3. wang

    Öö Tiib Guest

    On 22 aug, 04:37, wang <> wrote:
    > is there a function for converting a number such as 1234567.89 into a
    > string presentation as "1,234,567.89" for printing? Thanks for any
    > hints!


    Such things are in C++ standard library. Hints are such:

    class std::locale, template class std::numpunct, template class
    std::basic_ios, especially the function imbue().

    If you google for these you probably find tons of example code
    snippets. I am not sure if they work with MSVC 6.0 however, with 2005
    they did work.
     
    Öö Tiib, Aug 22, 2010
    #3
  4. wang

    Phlip Guest

    Francesco S. Carta wrote:

    > > Hi all
    > > is there a function for converting a number such as 1234567.89 into a
    > > string presentation as "1,234,567.89" for printing? Thanks for any
    > > hints!
    > > kwwang

    >
    > Nothing straight out of the standard C++ box.


    This is one of those perennial FAQs that everyone needs and nobody
    covers. The locale/facets system in iostreams is apparently a kit for
    you to assemble.

    The ultimate problem appears to be some undiscovered culture somewhere
    might separate hundreds, or ten-thousands, so a locale cannot simply
    assume thousands and then ask what delimiter goes there!

    http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-on-console-output.html

    #include <sstream>
    #include <iostream>
    #include <locale>
    #include <string>

    // custom numeric punctuation facet
    struct Punct: std::numpunct<char>
    {
    char do_thousands_sep () const
    {
    return ',';
    }
    std::string do_grouping () const
    {
    return "\3";
    }
    };

    std::string toStr(int x,std::locale const& l)
    {
    std::stringstream stream;
    stream.imbue(l);

    stream << x;
    return stream.str();
    }


    int main()
    {
    // construct a custom punctuation facet
    std::numpunct<char>* punct = new Punct;

    // construct a locale containing the custom facet
    const std::locale locale(std::cout.getloc(),punct);

    std::cout.imbue(locale);
    std::cout << "Val: " << 1234556 << std::endl;
    std::cout << "From String: " << toStr(123456789,locale) <<
    std::endl;
    }

    That thread then gets the James Kanze treatment, so read his prose to
    learn what horrors I just pasted in, untested!

    --
    Phlip
     
    Phlip, Aug 22, 2010
    #4
  5. Phlip <>, on 21/08/2010 21:14:31, wrote:

    > Francesco S. Carta wrote:
    >
    >>> Hi all
    >>> is there a function for converting a number such as 1234567.89 into a
    >>> string presentation as "1,234,567.89" for printing? Thanks for any
    >>> hints!
    >>> kwwang

    >>
    >> Nothing straight out of the standard C++ box.

    >
    > This is one of those perennial FAQs that everyone needs and nobody
    > covers. The locale/facets system in iostreams is apparently a kit for
    > you to assemble.
    >
    > The ultimate problem appears to be some undiscovered culture somewhere
    > might separate hundreds, or ten-thousands, so a locale cannot simply
    > assume thousands and then ask what delimiter goes there!
    >
    > http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-on-console-output.html
    >
    > #include<sstream>
    > #include<iostream>
    > #include<locale>
    > #include<string>
    >
    > // custom numeric punctuation facet
    > struct Punct: std::numpunct<char>
    > {
    > char do_thousands_sep () const
    > {
    > return ',';
    > }
    > std::string do_grouping () const
    > {
    > return "\3";
    > }
    > };
    >
    > std::string toStr(int x,std::locale const& l)
    > {
    > std::stringstream stream;
    > stream.imbue(l);
    >
    > stream<< x;
    > return stream.str();
    > }
    >
    >
    > int main()
    > {
    > // construct a custom punctuation facet
    > std::numpunct<char>* punct = new Punct;
    >
    > // construct a locale containing the custom facet
    > const std::locale locale(std::cout.getloc(),punct);
    >
    > std::cout.imbue(locale);
    > std::cout<< "Val: "<< 1234556<< std::endl;
    > std::cout<< "From String: "<< toStr(123456789,locale)<<
    > std::endl;
    > }
    >
    > That thread then gets the James Kanze treatment, so read his prose to
    > learn what horrors I just pasted in, untested!


    All of what you have written was somewhere in the background of my
    "Nothing straight out of the standard C++ box" reply.

    It's far easier to lookup an ad-hoc function or to write a simple one
    instead of delving into the complexity of assembling your own locale,
    for such a simple task.

    Granted, if one is accustomed to deal with them, one can come up with
    something like the above straight from the top of one's head.

    As I see it, it just feels like shooting flies with a cannon, with the
    further downside that I need to assemble it.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 22, 2010
    #5
  6. wang

    osmium Guest

    "Öö Tiib" wrote:

    > On 22 aug, 04:37, wang <> wrote:
    >> is there a function for converting a number such as 1234567.89 into a
    >> string presentation as "1,234,567.89" for printing? Thanks for any
    >> hints!

    >
    > Such things are in C++ standard library. Hints are such:
    >
    > class std::locale, template class std::numpunct, template class
    > std::basic_ios, especially the function imbue().


    That also answers the question, "Can I learn C++ in 21 days?"
     
    osmium, Aug 22, 2010
    #6
  7. wang

    Öö Tiib Guest

    On 22 aug, 13:41, "Francesco S. Carta" <> wrote:
    > Phlip <>, on 21/08/2010 21:14:31, wrote:
    >
    >
    >
    > > Francesco S. Carta wrote:

    >
    > >>> Hi all
    > >>> is there a function for converting a number such as 1234567.89 into a
    > >>> string presentation as "1,234,567.89" for printing? Thanks for any
    > >>> hints!
    > >>> kwwang

    >
    > >> Nothing straight out of the standard C++ box.

    >
    > > This is one of those perennial FAQs that everyone needs and nobody
    > > covers. The locale/facets system in iostreams is apparently a kit for
    > > you to assemble.

    >
    > > The ultimate problem appears to be some undiscovered culture somewhere
    > > might separate hundreds, or ten-thousands, so a locale cannot simply
    > > assume thousands and then ask what delimiter goes there!

    >
    > >http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-...

    >
    > > #include<sstream>
    > > #include<iostream>
    > > #include<locale>
    > > #include<string>

    >
    > > // custom numeric punctuation facet
    > > struct Punct: std::numpunct<char>
    > > {
    > > char do_thousands_sep () const
    > > {
    > > return ',';
    > > }
    > > std::string do_grouping () const
    > > {
    > > return "\3";
    > > }
    > > };

    >
    > > std::string toStr(int x,std::locale const&  l)
    > > {
    > > std::stringstream stream;
    > > stream.imbue(l);

    >
    > > stream<<  x;
    > > return stream.str();
    > > }

    >
    > > int main()
    > > {
    > > // construct a custom punctuation facet
    > > std::numpunct<char>* punct = new Punct;

    >
    > > // construct a locale containing the custom facet
    > > const std::locale locale(std::cout.getloc(),punct);

    >
    > > std::cout.imbue(locale);
    > > std::cout<<  "Val: "<<  1234556<<  std::endl;
    > > std::cout<<  "From String: "<<  toStr(123456789,locale)<<
    > > std::endl;
    > > }

    >
    > > That thread then gets the James Kanze treatment, so read his prose to
    > > learn what horrors I just pasted in, untested!

    >
    > All of what you have written was somewhere in the background of my
    > "Nothing straight out of the standard C++ box" reply.
    >
    > It's far easier to lookup an ad-hoc function or to write a simple one
    > instead of delving into the complexity of assembling your own locale,
    > for such a simple task.
    >
    > Granted, if one is accustomed to deal with them, one can come up with
    > something like the above straight from the top of one's head.
    >
    > As I see it, it just feels like shooting flies with a cannon, with the
    > further downside that I need to assemble it.


    Usually you have that cannon constructed already if you work for shop
    that writes C++ for international market. The problem is heavily
    localization related. For you "1,234,567.89" is may be natural so you
    think it is a "fly" to achieve it. German-speaking nations often like
    it other way around, like "1.234.567,89". Some Hindi-speaking guy does
    not understand thousand separator, for them there is hundreds
    separators. So the solution to have same number readable for all of
    them is to have locales, or what else you suggest to do? Hack it ad-
    hoc until it is unreadable blob of crap?
     
    Öö Tiib, Aug 22, 2010
    #7
  8. Öö Tiib <>, on 22/08/2010 09:09:15, wrote:

    > On 22 aug, 13:41, "Francesco S. Carta"<> wrote:
    >> Phlip<>, on 21/08/2010 21:14:31, wrote:
    >>
    >>
    >>
    >>> Francesco S. Carta wrote:

    >>
    >>>>> Hi all
    >>>>> is there a function for converting a number such as 1234567.89 into a
    >>>>> string presentation as "1,234,567.89" for printing? Thanks for any
    >>>>> hints!
    >>>>> kwwang

    >>
    >>>> Nothing straight out of the standard C++ box.

    >>
    >>> This is one of those perennial FAQs that everyone needs and nobody
    >>> covers. The locale/facets system in iostreams is apparently a kit for
    >>> you to assemble.

    >>
    >>> The ultimate problem appears to be some undiscovered culture somewhere
    >>> might separate hundreds, or ten-thousands, so a locale cannot simply
    >>> assume thousands and then ask what delimiter goes there!

    >>
    >>> http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-...

    >>
    >>> #include<sstream>
    >>> #include<iostream>
    >>> #include<locale>
    >>> #include<string>

    >>
    >>> // custom numeric punctuation facet
    >>> struct Punct: std::numpunct<char>
    >>> {
    >>> char do_thousands_sep () const
    >>> {
    >>> return ',';
    >>> }
    >>> std::string do_grouping () const
    >>> {
    >>> return "\3";
    >>> }
    >>> };

    >>
    >>> std::string toStr(int x,std::locale const& l)
    >>> {
    >>> std::stringstream stream;
    >>> stream.imbue(l);

    >>
    >>> stream<< x;
    >>> return stream.str();
    >>> }

    >>
    >>> int main()
    >>> {
    >>> // construct a custom punctuation facet
    >>> std::numpunct<char>* punct = new Punct;

    >>
    >>> // construct a locale containing the custom facet
    >>> const std::locale locale(std::cout.getloc(),punct);

    >>
    >>> std::cout.imbue(locale);
    >>> std::cout<< "Val: "<< 1234556<< std::endl;
    >>> std::cout<< "From String: "<< toStr(123456789,locale)<<
    >>> std::endl;
    >>> }

    >>
    >>> That thread then gets the James Kanze treatment, so read his prose to
    >>> learn what horrors I just pasted in, untested!

    >>
    >> All of what you have written was somewhere in the background of my
    >> "Nothing straight out of the standard C++ box" reply.
    >>
    >> It's far easier to lookup an ad-hoc function or to write a simple one
    >> instead of delving into the complexity of assembling your own locale,
    >> for such a simple task.
    >>
    >> Granted, if one is accustomed to deal with them, one can come up with
    >> something like the above straight from the top of one's head.
    >>
    >> As I see it, it just feels like shooting flies with a cannon, with the
    >> further downside that I need to assemble it.

    >
    > Usually you have that cannon constructed already if you work for shop
    > that writes C++ for international market. The problem is heavily
    > localization related. For you "1,234,567.89" is may be natural so you
    > think it is a "fly" to achieve it. German-speaking nations often like
    > it other way around, like "1.234.567,89". Some Hindi-speaking guy does
    > not understand thousand separator, for them there is hundreds
    > separators. So the solution to have same number readable for all of
    > them is to have locales, or what else you suggest to do? Hack it ad-
    > hoc until it is unreadable blob of crap?


    Of course not. Using std::locale or an existing in-house version of them
    is the way to go in such cases.

    It all depends on the target one wants to achieve.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 22, 2010
    #8
  9. wang

    Öö Tiib Guest

    On 22 aug, 19:16, "Francesco S. Carta" <> wrote:
    > Öö Tiib <>, on 22/08/2010 09:09:15, wrote:
    >
    >
    >
    > > On 22 aug, 13:41, "Francesco S. Carta"<>  wrote:
    > >> Phlip<>, on 21/08/2010 21:14:31, wrote:

    >
    > >>> Francesco S. Carta wrote:

    >
    > >>>>> Hi all
    > >>>>> is there a function for converting a number such as 1234567.89 into a
    > >>>>> string presentation as "1,234,567.89" for printing? Thanks for any
    > >>>>> hints!
    > >>>>> kwwang

    >
    > >>>> Nothing straight out of the standard C++ box.

    >
    > >>> This is one of those perennial FAQs that everyone needs and nobody
    > >>> covers. The locale/facets system in iostreams is apparently a kit for
    > >>> you to assemble.

    >
    > >>> The ultimate problem appears to be some undiscovered culture somewhere
    > >>> might separate hundreds, or ten-thousands, so a locale cannot simply
    > >>> assume thousands and then ask what delimiter goes there!

    >
    > >>>http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-....

    >
    > >>> #include<sstream>
    > >>> #include<iostream>
    > >>> #include<locale>
    > >>> #include<string>

    >
    > >>> // custom numeric punctuation facet
    > >>> struct Punct: std::numpunct<char>
    > >>> {
    > >>> char do_thousands_sep () const
    > >>> {
    > >>> return ',';
    > >>> }
    > >>> std::string do_grouping () const
    > >>> {
    > >>> return "\3";
    > >>> }
    > >>> };

    >
    > >>> std::string toStr(int x,std::locale const&    l)
    > >>> {
    > >>> std::stringstream stream;
    > >>> stream.imbue(l);

    >
    > >>> stream<<    x;
    > >>> return stream.str();
    > >>> }

    >
    > >>> int main()
    > >>> {
    > >>> // construct a custom punctuation facet
    > >>> std::numpunct<char>* punct = new Punct;

    >
    > >>> // construct a locale containing the custom facet
    > >>> const std::locale locale(std::cout.getloc(),punct);

    >
    > >>> std::cout.imbue(locale);
    > >>> std::cout<<    "Val: "<<    1234556<<    std::endl;
    > >>> std::cout<<    "From String: "<<    toStr(123456789,locale)<<
    > >>> std::endl;
    > >>> }

    >
    > >>> That thread then gets the James Kanze treatment, so read his prose to
    > >>> learn what horrors I just pasted in, untested!

    >
    > >> All of what you have written was somewhere in the background of my
    > >> "Nothing straight out of the standard C++ box" reply.

    >
    > >> It's far easier to lookup an ad-hoc function or to write a simple one
    > >> instead of delving into the complexity of assembling your own locale,
    > >> for such a simple task.

    >
    > >> Granted, if one is accustomed to deal with them, one can come up with
    > >> something like the above straight from the top of one's head.

    >
    > >> As I see it, it just feels like shooting flies with a cannon, with the
    > >> further downside that I need to assemble it.

    >
    > > Usually you have that cannon constructed already if you work for shop
    > > that writes C++ for international market. The problem is heavily
    > > localization related. For you "1,234,567.89" is may be natural so you
    > > think it is a "fly" to achieve it. German-speaking nations often like
    > > it other way around, like "1.234.567,89". Some Hindi-speaking guy does
    > > not understand thousand separator, for them there is hundreds
    > > separators. So the solution to have same number readable for all of
    > > them is to have locales, or what else you suggest to do? Hack it ad-
    > > hoc until it is unreadable blob of crap?

    >
    > Of course not. Using std::locale or an existing in-house version of them
    > is the way to go in such cases.
    >
    > It all depends on the target one wants to achieve.


    Yes and target is to format the output *exactly* with all
    peculiarities like expected. And these peculiarities are: notation?,
    decimal point?, precision?, padding?, thousands or hundreds
    separation?, with what separator?, plus sign for positives?,
    parentheses around negatives? and so on just name it. Been a bit
    around in industry you notice that these damn peculiarities will
    change immediately when your bosses sell it not only to neighbour of
    yours but few blocks farther too. And then you see how sweet is to
    just use locale as a configuration dedicated for next set of poor
    fatsos who bought it. There are lot more interesting things to hack
    than numeric formats, really.
     
    Öö Tiib, Aug 22, 2010
    #9
  10. Öö Tiib <>, on 22/08/2010 10:06:08, wrote:

    > On 22 aug, 19:16, "Francesco S. Carta"<> wrote:
    >> Öö Tiib<>, on 22/08/2010 09:09:15, wrote:
    >>
    >>
    >>
    >>> On 22 aug, 13:41, "Francesco S. Carta"<> wrote:
    >>>> Phlip<>, on 21/08/2010 21:14:31, wrote:

    >>
    >>>>> Francesco S. Carta wrote:

    >>
    >>>>>>> Hi all
    >>>>>>> is there a function for converting a number such as 1234567.89 into a
    >>>>>>> string presentation as "1,234,567.89" for printing? Thanks for any
    >>>>>>> hints!
    >>>>>>> kwwang

    >>
    >>>>>> Nothing straight out of the standard C++ box.

    >>
    >>>>> This is one of those perennial FAQs that everyone needs and nobody
    >>>>> covers. The locale/facets system in iostreams is apparently a kit for
    >>>>> you to assemble.

    >>
    >>>>> The ultimate problem appears to be some undiscovered culture somewhere
    >>>>> might separate hundreds, or ten-thousands, so a locale cannot simply
    >>>>> assume thousands and then ask what delimiter goes there!

    >>
    >>>>> http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-...

    >>
    >>>>> #include<sstream>
    >>>>> #include<iostream>
    >>>>> #include<locale>
    >>>>> #include<string>

    >>
    >>>>> // custom numeric punctuation facet
    >>>>> struct Punct: std::numpunct<char>
    >>>>> {
    >>>>> char do_thousands_sep () const
    >>>>> {
    >>>>> return ',';
    >>>>> }
    >>>>> std::string do_grouping () const
    >>>>> {
    >>>>> return "\3";
    >>>>> }
    >>>>> };

    >>
    >>>>> std::string toStr(int x,std::locale const& l)
    >>>>> {
    >>>>> std::stringstream stream;
    >>>>> stream.imbue(l);

    >>
    >>>>> stream<< x;
    >>>>> return stream.str();
    >>>>> }

    >>
    >>>>> int main()
    >>>>> {
    >>>>> // construct a custom punctuation facet
    >>>>> std::numpunct<char>* punct = new Punct;

    >>
    >>>>> // construct a locale containing the custom facet
    >>>>> const std::locale locale(std::cout.getloc(),punct);

    >>
    >>>>> std::cout.imbue(locale);
    >>>>> std::cout<< "Val: "<< 1234556<< std::endl;
    >>>>> std::cout<< "From String: "<< toStr(123456789,locale)<<
    >>>>> std::endl;
    >>>>> }

    >>
    >>>>> That thread then gets the James Kanze treatment, so read his prose to
    >>>>> learn what horrors I just pasted in, untested!

    >>
    >>>> All of what you have written was somewhere in the background of my
    >>>> "Nothing straight out of the standard C++ box" reply.

    >>
    >>>> It's far easier to lookup an ad-hoc function or to write a simple one
    >>>> instead of delving into the complexity of assembling your own locale,
    >>>> for such a simple task.

    >>
    >>>> Granted, if one is accustomed to deal with them, one can come up with
    >>>> something like the above straight from the top of one's head.

    >>
    >>>> As I see it, it just feels like shooting flies with a cannon, with the
    >>>> further downside that I need to assemble it.

    >>
    >>> Usually you have that cannon constructed already if you work for shop
    >>> that writes C++ for international market. The problem is heavily
    >>> localization related. For you "1,234,567.89" is may be natural so you
    >>> think it is a "fly" to achieve it. German-speaking nations often like
    >>> it other way around, like "1.234.567,89". Some Hindi-speaking guy does
    >>> not understand thousand separator, for them there is hundreds
    >>> separators. So the solution to have same number readable for all of
    >>> them is to have locales, or what else you suggest to do? Hack it ad-
    >>> hoc until it is unreadable blob of crap?

    >>
    >> Of course not. Using std::locale or an existing in-house version of them
    >> is the way to go in such cases.
    >>
    >> It all depends on the target one wants to achieve.

    >
    > Yes and target is to format the output *exactly* with all
    > peculiarities like expected.


    No, the target was just to format a number following the example given
    by the OP. Don't take it for pedantry or for playing word games, all you
    are trying to do with me amounts to breaking through an open door: I'll
    repeat it, if one needs to take care of all those details, then
    std::locale is the way to go, I fully agree with you.

    The next time I'll take care of mentioning locales in my replies just to
    avoid this kind of discussions, although I'm very well accustomed to see
    a question replied by several people from different points of view, to
    the advantage of the OP.

    > And these peculiarities are: notation?,
    > decimal point?, precision?, padding?, thousands or hundreds
    > separation?, with what separator?, plus sign for positives?,
    > parentheses around negatives? and so on just name it. Been a bit
    > around in industry you notice that these damn peculiarities will
    > change immediately when your bosses sell it not only to neighbour of
    > yours but few blocks farther too. And then you see how sweet is to
    > just use locale as a configuration dedicated for next set of poor
    > fatsos who bought it. There are lot more interesting things to hack
    > than numeric formats, really.


    Nothing new under my sky, and the same surely stands under yours. But
    what about the OP? If one comes here asking for a formatting function,
    chances are that one might learn something by hacking numeric formats,
    as you pose it.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 22, 2010
    #10
  11. wang

    Jorgen Grahn Guest

    On Sun, 2010-08-22, osmium wrote:
    > "Öö Tiib" wrote:
    >
    >> On 22 aug, 04:37, wang <> wrote:
    >>> is there a function for converting a number such as 1234567.89 into a
    >>> string presentation as "1,234,567.89" for printing? Thanks for any
    >>> hints!

    >>
    >> Such things are in C++ standard library. Hints are such:
    >>
    >> class std::locale, template class std::numpunct, template class
    >> std::basic_ios, especially the function imbue().

    >
    > That also answers the question, "Can I learn C++ in 21 days?"


    How often do you have to print numbers with ASCII-style thousands
    separators? I have never had the need to do it. It's when (a) machine
    readability is unimportant, (b) the audience doesn't understand
    scientific notation, (c) it's plain text so a half-width nonbreakable
    space isn't a better choice. Hasn't happened to me so far, and I
    don't think it ever will.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Aug 23, 2010
    #11
  12. wang

    wang Guest

    On 22 Aug., 19:26, "Francesco S. Carta" <> wrote:
    > Öö Tiib <>, on 22/08/2010 10:06:08, wrote:
    >
    >
    >
    >
    >
    > > On 22 aug, 19:16, "Francesco S. Carta"<>  wrote:
    > >> Öö Tiib<>, on 22/08/2010 09:09:15, wrote:

    >
    > >>> On 22 aug, 13:41, "Francesco S. Carta"<>    wrote:
    > >>>> Phlip<>, on 21/08/2010 21:14:31, wrote:

    >
    > >>>>> Francesco S. Carta wrote:

    >
    > >>>>>>> Hi all
    > >>>>>>> is there a function for converting a number such as 1234567.89 into a
    > >>>>>>> string presentation as "1,234,567.89" for printing? Thanks for any
    > >>>>>>> hints!
    > >>>>>>> kwwang

    >
    > >>>>>> Nothing straight out of the standard C++ box.

    >
    > >>>>> This is one of those perennial FAQs that everyone needs and nobody
    > >>>>> covers. The locale/facets system in iostreams is apparently a kit for
    > >>>>> you to assemble.

    >
    > >>>>> The ultimate problem appears to be some undiscovered culture somewhere
    > >>>>> might separate hundreds, or ten-thousands, so a locale cannot simply
    > >>>>> assume thousands and then ask what delimiter goes there!

    >
    > >>>>>http://www.velocityreviews.com/forums/t603778-help-add-commas-to-int-...

    >
    > >>>>> #include<sstream>
    > >>>>> #include<iostream>
    > >>>>> #include<locale>
    > >>>>> #include<string>

    >
    > >>>>> // custom numeric punctuation facet
    > >>>>> struct Punct: std::numpunct<char>
    > >>>>> {
    > >>>>> char do_thousands_sep () const
    > >>>>> {
    > >>>>> return ',';
    > >>>>> }
    > >>>>> std::string do_grouping () const
    > >>>>> {
    > >>>>> return "\3";
    > >>>>> }
    > >>>>> };

    >
    > >>>>> std::string toStr(int x,std::locale const&      l)
    > >>>>> {
    > >>>>> std::stringstream stream;
    > >>>>> stream.imbue(l);

    >
    > >>>>> stream<<      x;
    > >>>>> return stream.str();
    > >>>>> }

    >
    > >>>>> int main()
    > >>>>> {
    > >>>>> // construct a custom punctuation facet
    > >>>>> std::numpunct<char>* punct = new Punct;

    >
    > >>>>> // construct a locale containing the custom facet
    > >>>>> const std::locale locale(std::cout.getloc(),punct);

    >
    > >>>>> std::cout.imbue(locale);
    > >>>>> std::cout<<      "Val: "<<      1234556<<      std::endl;
    > >>>>> std::cout<<      "From String: "<<      toStr(123456789,locale)<<
    > >>>>> std::endl;
    > >>>>> }

    >
    > >>>>> That thread then gets the James Kanze treatment, so read his prose to
    > >>>>> learn what horrors I just pasted in, untested!

    >
    > >>>> All of what you have written was somewhere in the background of my
    > >>>> "Nothing straight out of the standard C++ box" reply.

    >
    > >>>> It's far easier to lookup an ad-hoc function or to write a simple one
    > >>>> instead of delving into the complexity of assembling your own locale,
    > >>>> for such a simple task.

    >
    > >>>> Granted, if one is accustomed to deal with them, one can come up with
    > >>>> something like the above straight from the top of one's head.

    >
    > >>>> As I see it, it just feels like shooting flies with a cannon, with the
    > >>>> further downside that I need to assemble it.

    >
    > >>> Usually you have that cannon constructed already if you work for shop
    > >>> that writes C++ for international market. The problem is heavily
    > >>> localization related. For you "1,234,567.89" is may be natural so you
    > >>> think it is a "fly" to achieve it. German-speaking nations often like
    > >>> it other way around, like "1.234.567,89". Some Hindi-speaking guy does
    > >>> not understand thousand separator, for them there is hundreds
    > >>> separators. So the solution to have same number readable for all of
    > >>> them is to have locales, or what else you suggest to do? Hack it ad-
    > >>> hoc until it is unreadable blob of crap?

    >
    > >> Of course not. Using std::locale or an existing in-house version of them
    > >> is the way to go in such cases.

    >
    > >> It all depends on the target one wants to achieve.

    >
    > > Yes and target is to format the output *exactly* with all
    > > peculiarities like expected.

    >
    > No, the target was just to format a number following the example given
    > by the OP. Don't take it for pedantry or for playing word games, all you
    > are trying to do with me amounts to breaking through an open door: I'll
    > repeat it, if one needs to take care of all those details, then
    > std::locale is the way to go, I fully agree with you.
    >
    > The next time I'll take care of mentioning locales in my replies just to
    > avoid this kind of discussions, although I'm very well accustomed to see
    > a question replied by several people from different points of view, to
    > the advantage of the OP.
    >
    > > And these peculiarities are: notation?,
    > > decimal point?, precision?, padding?, thousands or hundreds
    > > separation?, with what separator?, plus sign for positives?,
    > > parentheses around negatives? and so on just name it. Been a bit
    > > around in industry you notice that these damn peculiarities will
    > > change immediately when your bosses sell it not only to neighbour of
    > > yours but few blocks farther too. And then you see how sweet is to
    > > just use locale as a configuration dedicated for next set of poor
    > > fatsos who bought it. There are lot more interesting things to hack
    > > than numeric formats, really.

    >
    > Nothing new under my sky, and the same surely stands under yours. But
    > what about the OP? If one comes here asking for a formatting function,
    > chances are that one might learn something by hacking numeric formats,
    > as you pose it.
    >
    > --
    >   FSC -http://userscripts.org/scripts/show/59948
    >  http://fscode.altervista.org-http://sardinias.com- Zitierten Text ausblenden -
    >
    > - Zitierten Text anzeigen -


    It's interesting to read the whole discussion. But the material is
    overwhelming. I've never heard of locale or the like. I feel happy if
    I can write code in c++ instead of ANSI C. Before I begin to learn all
    these, I prefer to write my own simple function (maybe I should say
    method), learning locale etc must be planned for the future.
    Here is my code. I use it to format currency amount, which should
    contain 2 fraction digits (padded with "0").
    kwwang

    string bigNumberFormat(double num, short frclen, bool inter)
    {
    /* num: positive number to be formatted,
    frclen: Length of fraction part,
    inter: true for international (12,345,678.920), false for German
    (12.345.678,920) */
    string separator, point;
    ostringstream oss;
    if (inter) {
    separator = ",";
    point = ".";
    } else {
    separator = ".";
    point = ",";
    }
    oss << (long)num;
    string tmp, result = "";
    tmp = oss.str();
    short len = tmp.size(), remainder, repeat;
    remainder = len % 3;
    repeat = len / 3;
    if (remainder) {
    result += tmp.substr(0, remainder);
    for (int i = 0; i < repeat; i++)
    result += separator + tmp.substr(remainder + i * 3, 3);
    } else {
    for (int i = 0; i < repeat; i++)
    result += (i?separator:"") + tmp.substr(i * 3, 3);
    }
    if (frclen)
    result += point;
    num = num - (long)num;
    ostringstream oss1;
    oss1 << num;
    tmp = oss1.str() + string(frclen + 1, '0');
    result += tmp.substr(2, frclen);
    return result;
    }
     
    wang, Aug 24, 2010
    #12
  13. wang <>, on 23/08/2010 18:39:04, wrote:

    > It's interesting to read the whole discussion. But the material is
    > overwhelming. I've never heard of locale or the like. I feel happy if
    > I can write code in c++ instead of ANSI C. Before I begin to learn all
    > these, I prefer to write my own simple function (maybe I should say
    > method), learning locale etc must be planned for the future.
    > Here is my code. I use it to format currency amount, which should
    > contain 2 fraction digits (padded with "0").
    > kwwang


    OK, don't worry, you'll be able to cover all the material step by step.

    Reading your code it seems that I was right, you can learn something
    from writing such a simple function, before diving into more advanced
    subjects - I'm sure you'll take my notes in the right way, I'm starting
    to dive into C myself and I feel just fine knowing that I _don't know_
    and getting advices.

    I'll snip all of your code, I think you know your stuff in C, you only
    need to straighten out some concepts to learn the C++ way, hence I'll
    post here some sparse comments.

    Don't use C-style casts, and even less use them for doing simple
    conversions: use "long(value)" instead of "(long)value", and chances are
    that you don't even need them in this case. More about this later.

    Decide the exact behaviour expected by your code: as it is now it
    truncates decimals instead of rounding them upon the amount requested by
    the caller.

    You're hardcoding the separators and their frequency by setting just two
    styles via one flag, you could make it more flexible by passing those
    separators and frequency and so on as separate parameters, and with some
    struggle you could give some memory to that function using static
    locals, but I'd suggest you to start at once by creating a class.

    A skeleton you can adapt to your task:

    //-------

    #include <iostream>
    #include <sstream>

    class NumberFormatter {
    public:
    NumberFormatter(int decimals = 2,
    char separator = '.' )
    : decimals(decimals),
    separator(separator) {}

    std::string operator()(double value) const;

    private:
    int decimals;
    char separator;
    };

    std::string NumberFormatter::eek:perator()(double value) const {
    std::stringstream result;
    // intentionally silly example
    result << long(value) << separator << decimals;
    return result.str();
    }

    using namespace std;

    int main() {
    NumberFormatter f1;
    NumberFormatter f2(3, '-');
    cout << f1(4.2) << endl;
    cout << f2(7.8) << endl;
    return 0;
    }

    //-------

    There are other things you can improve about your approach and I'll
    eventually come back on them if others don't point them out.

    Give it a shot with the above skeleton, that's an outline of what is
    commonly called a function-object or functor.

    Don't forget that a good book and the FAQ are two very powerful tools
    for your C++ learning and for getting the best help out from this group,
    start by reading sections 5 and 6 of the FAQ to ensure yourself on the
    best track.

    Have fun with C++, on my part I'm trying to have fun with C ;-)

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 24, 2010
    #13
  14. wang

    red floyd Guest

    On Aug 23, 7:33 pm, "Francesco S. Carta" <> wrote:

    > Don't use C-style casts, and even less use them for doing simple
    > conversions: use "long(value)" instead of "(long)value", and chances are
    > that you don't even need them in this case. More about this later.
    >


    And another. Don't use function/constructor style casts.

    Use static_cast here. "static_cast<long>(value)"
     
    red floyd, Aug 24, 2010
    #14
  15. red floyd <>, on 24/08/2010 08:33:53, wrote:

    > On Aug 23, 7:33 pm, "Francesco S. Carta"<> wrote:
    >
    >> Don't use C-style casts, and even less use them for doing simple
    >> conversions: use "long(value)" instead of "(long)value", and chances are
    >> that you don't even need them in this case. More about this later.
    >>

    >
    > And another. Don't use function/constructor style casts.
    >
    > Use static_cast here. "static_cast<long>(value)"


    Well, yes, I've heard that advice a lot of times, and it actually has
    its use in order to quickly find all the places where an explicit
    conversion is made.

    I only think that sometimes that's overkill.

    Consider an explicit conversion to string: I have a function that takes
    a string, somewhere in the code I need to compose a message from a
    string literal and a char to pass to that function:

    foo(string("char ch == ") + ch);

    The above looks more natural, compact and innocuous than:

    foo(static_cast<string>("char ch == ") + ch);

    With the further advantage that, when searching for a possibly
    problematic explicit conversion, you'll avoid having to skip over the
    innocuous ones.

    Also consider an explicit conversion to double when doing a quick
    decimal conversion, assume:

    int cents = 7842;

    Somebody could write:

    cout << "Got " << cents * 0.01 << " euros" << endl;

    I would use the functional-style conversion:

    cout << "Got " << double(cents)/100 << " euros" << endl;

    But this is absolutely overkill:

    cout << "Got " << static_cast<double>(cents)/100 << " euros" << endl;

    And, once more, will pollute the search for problematic explicit
    conversions.

    To resume, as I see it, it's all about coding style customs (if one has
    to work in a team) and about personal needs and considerations (when one
    works on a personal project).

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 24, 2010
    #15
  16. wang

    wang Guest

    On 24 Aug., 04:33, "Francesco S. Carta" <> wrote:
    > wang <>, on 23/08/2010 18:39:04, wrote:
    >
    > > It's interesting to read the whole discussion. But the material is
    > > overwhelming. I've never heard of locale or the like. I feel happy if
    > > I can write code in c++ instead of ANSI C. Before I begin to learn all
    > > these, I prefer to write my own simple function (maybe I should say
    > > method), learning locale etc must be planned for the future.
    > > Here is my code. I use it to format currency amount, which should
    > > contain 2 fraction digits (padded with "0").
    > > kwwang

    >
    > OK, don't worry, you'll be able to cover all the material step by step.
    >
    > Reading your code it seems that I was right, you can learn something
    > from writing such a simple function, before diving into more advanced
    > subjects - I'm sure you'll take my notes in the right way, I'm starting
    > to dive into C myself and I feel just fine knowing that I _don't know_
    > and getting advices.
    >
    > I'll snip all of your code, I think you know your stuff in C, you only
    > need to straighten out some concepts to learn the C++ way, hence I'll
    > post here some sparse comments.
    >
    > Don't use C-style casts, and even less use them for doing simple
    > conversions: use "long(value)" instead of "(long)value", and chances are
    > that you don't even need them in this case. More about this later.
    >
    > Decide the exact behaviour expected by your code: as it is now it
    > truncates decimals instead of rounding them upon the amount requested by
    > the caller.
    >
    > You're hardcoding the separators and their frequency by setting just two
    > styles via one flag, you could make it more flexible by passing those
    > separators and frequency and so on as separate parameters, and with some
    > struggle you could give some memory to that function using static
    > locals, but I'd suggest you to start at once by creating a class.
    >
    > A skeleton you can adapt to your task:
    >
    > //-------
    >
    > #include <iostream>
    > #include <sstream>
    >
    > class NumberFormatter {
    > public:
    >      NumberFormatter(int decimals = 2,
    >                      char separator = '.' )
    >              : decimals(decimals),
    >              separator(separator) {}
    >
    >      std::string operator()(double value) const;
    >
    > private:
    >      int decimals;
    >      char separator;
    >
    > };
    >
    > std::string NumberFormatter::eek:perator()(double value) const {
    >      std::stringstream result;
    >      // intentionally silly example
    >      result << long(value) << separator << decimals;
    >      return result.str();
    >
    > }
    >
    > using namespace std;
    >
    > int main() {
    >      NumberFormatter f1;
    >      NumberFormatter f2(3, '-');
    >      cout << f1(4.2) << endl;
    >      cout << f2(7.8) << endl;
    >      return 0;
    >
    > }
    >
    > //-------
    >
    > There are other things you can improve about your approach and I'll
    > eventually come back on them if others don't point them out.
    >
    > Give it a shot with the above skeleton, that's an outline of what is
    > commonly called a function-object or functor.
    >
    > Don't forget that a good book and the FAQ are two very powerful tools
    > for your C++ learning and for getting the best help out from this group,
    > start by reading sections 5 and 6 of the FAQ to ensure yourself on the
    > best track.
    >
    > Have fun with C++, on my part I'm trying to have fun with C ;-)
    >
    > --
    >   FSC -http://userscripts.org/scripts/show/59948
    >  http://fscode.altervista.org-http://sardinias.com


    Thank you for your patient explaining. I'll come back to this topic
    later, for I must finish the program for the company in the moment.
    kwwang
     
    wang, Aug 24, 2010
    #16
    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. Stuart Woodard

    Server-side Printing With Formatted Text

    Stuart Woodard, Aug 3, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    329
    Stuart Woodard
    Aug 3, 2003
  2. Clint MacDonald

    Borderless formatted Printing from ASP.NET

    Clint MacDonald, May 1, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    872
  3. babo
    Replies:
    9
    Views:
    3,829
    Roedy Green
    Nov 30, 2005
  4. Thomas Philips
    Replies:
    7
    Views:
    357
    Josiah Carlson
    May 21, 2004
  5. Wes Gamble
    Replies:
    8
    Views:
    202
    Wes Gamble
    Mar 21, 2006
Loading...

Share This Page