Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Formatting Ouput with Punctuation (Commas)

75 views
Skip to first unread message

MikeCopeland

unread,
Aug 7, 2016, 9:14:09 PM8/7/16
to
Given: a value of 17234987, is there a (good) way to format it for
output as 17,234,987? I would have thought that stream i/o would
support such formatting, but I can't find anything that seems to show
how to do it.
Please advise. TIA


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

Öö Tiib

unread,
Aug 7, 2016, 9:31:18 PM8/7/16
to
On Monday, 8 August 2016 04:14:09 UTC+3, MikeCopeland wrote:
> Given: a value of 17234987, is there a (good) way to format it for
> output as 17,234,987? I would have thought that stream i/o would
> support such formatting, but I can't find anything that seems to show
> how to do it.
> Please advise. TIA

You have to use 'std::locale' and 'std::put_money' read up on those
for details. Teaser example:

#include <iostream> // for std::cout
#include <iomanip> // std::put_money and other utilities

int main(int argc, char **argv)
{
const int amount = 1000000; // in cents

std::cout.imbue(std::locale("en_US.UTF-8"));

std::cout << std::showbase << std::put_money(amount) << '\n';
}

That should output ...

$10,000.00

MikeCopeland

unread,
Aug 7, 2016, 11:36:26 PM8/7/16
to
Not quite wqhat I'm looking for: I'm not working with money data, but
large integer values. With your solution, there's no way to format
integers >999 with punctuation. Am I missing something?

Öö Tiib

unread,
Aug 8, 2016, 3:24:39 AM8/8/16
to
Indeed, you missed my remark that it was example and my suggestion to read
up on the things involved. You hate to read? OK I will complete it
for you:

#include <iostream> // for std::cout
#include <iomanip> // std::put_money and other utilities

int main(int argc, char **argv)
{
const int amount = 17234987; // in cents

std::cout.imbue(std::locale("ja_JP.UTF-8"));

std::cout << std::put_money(amount) << '\n';
}

Done, 17,234,987 exactly as specified. Was it that hard?

Alf P. Steinbach

unread,
Aug 8, 2016, 4:56:39 AM8/8/16
to
UTF-8 for byte streams is not supported in Windows.

So that's very non-portable code. ;-)

Also, consider `num_put`. Mike's example indicates that it's just a
number, not a monetary amount.


Cheers!,

- Alf

Öö Tiib

unread,
Aug 8, 2016, 9:55:06 AM8/8/16
to
On Monday, 8 August 2016 11:56:39 UTC+3, Alf P. Steinbach wrote:
> On 08.08.2016 03:31, Öö Tiib wrote:
> > On Monday, 8 August 2016 04:14:09 UTC+3, MikeCopeland wrote:
> >> Given: a value of 17234987, is there a (good) way to format it for
> >> output as 17,234,987? I would have thought that stream i/o would
> >> support such formatting, but I can't find anything that seems to show
> >> how to do it.
> >> Please advise. TIA
> >
> > You have to use 'std::locale' and 'std::put_money' read up on those
> > for details. Teaser example:
> >
> > #include <iostream> // for std::cout
> > #include <iomanip> // std::put_money and other utilities
> >
> > int main(int argc, char **argv)
> > {
> > const int amount = 1000000; // in cents
> >
> > std::cout.imbue(std::locale("en_US.UTF-8"));
> >
> > std::cout << std::showbase << std::put_money(amount) << '\n';
> > }
> >
> > That should output ...
> >
> > $10,000.00
> >
>
> UTF-8 for byte streams is not supported in Windows.
>
> So that's very non-portable code. ;-)

UTF-8 is right now 83% - 87% of all web content ... so if Windows
can't even byte stream that then what is it useful for? Perhaps
something like "English_Australia.1252" will work there then. :-)

>
> Also, consider `num_put`. Mike's example indicates that it's just a
> number, not a monetary amount.

Perhaps 'num_put' is indeed best. I wondered how he can't find
*anything* in stream I/O and so I just pointed direction. If he
wants to use I/O utilities then he has quite lot to read there.

Rick C. Hodgin

unread,
Aug 8, 2016, 10:33:30 AM8/8/16
to
On Sunday, August 7, 2016 at 9:14:09 PM UTC-4, MikeCopeland wrote:
> Given: a value of 17234987, is there a (good) way to format it for
> output as 17,234,987? I would have thought that stream i/o would
> support such formatting, but I can't find anything that seems to show
> how to do it.
> Please advise. TIA

auto amt1 = amount % 1000;
auto amt2 = (amount % 1000000) / 1000;
auto amt3 = (amount % 1000000000) / 1000000;

if (amount < 1000)
cout << amt1;
else if (amount < 1000000)
cout << amt2 << "," << amt1;
else if (amount < 1000000000)
cout << amt3 << "," << amt2 << "," << amt1;

Something like that.

Best regards,
Rick C. Hodgin

Scott Lurndal

unread,
Aug 8, 2016, 10:48:57 AM8/8/16
to
MikeCopeland <mrc...@cox.net> writes:
> Given: a value of 17234987, is there a (good) way to format it for
>output as 17,234,987? I would have thought that stream i/o would
>support such formatting, but I can't find anything that seems to show
>how to do it.
> Please advise. TIA

Use 'snprintf'. The ' formatting flag will use the grouping
character from the locale to group digits appropriately.

http://pubs.opengroup.org/onlinepubs/7908799/xsh/fprintf.html

Öö Tiib

unread,
Aug 8, 2016, 10:55:21 AM8/8/16
to
*Bzzzzt*, wrong, but thank you for playing.
What it will output on case of amount = 17004087?

Rick C. Hodgin

unread,
Aug 8, 2016, 10:59:29 AM8/8/16
to
I don't know how in C++ to make it work with values < 100 the lower
amounts. It will produce weird things like "1,23,456" for 1,023,456".
I'd have to use what I know. :-)

int amount = 1023045;
char buf1[4], buf2[4];
sprintf(buf1, "%03d", amount % 1000);
sprintf(buf2, "%03d", (amount % 1000000) / 1000);
auto amt1 = amount % 1000;
auto amt2 = (amount % 1000000) / 1000;
auto amt3 = (amount % 1000000000) / 1000000;

if (amount < 1000)
cout << amt1;
else if (amount < 1000000)
cout << amt2 << "," << buf1;
else if (amount < 1000000000)
cout << amt3 << "," << buf2 << "," << buf1;

Rick C. Hodgin

unread,
Aug 8, 2016, 11:00:53 AM8/8/16
to
I appreciate your kindness in pointing out my mistake. It reveals much
about your character.

> What it will output on case of amount = 17004087?

17,4,87.

Alf P. Steinbach

unread,
Aug 8, 2016, 12:46:38 PM8/8/16
to
On 08.08.2016 15:54, Öö Tiib wrote:
> On Monday, 8 August 2016 11:56:39 UTC+3, Alf P. Steinbach wrote:
>> On 08.08.2016 03:31, Öö Tiib wrote:
>>> On Monday, 8 August 2016 04:14:09 UTC+3, MikeCopeland wrote:
>>>> Given: a value of 17234987, is there a (good) way to format it for
>>>> output as 17,234,987? I would have thought that stream i/o would
>>>> support such formatting, but I can't find anything that seems to show
>>>> how to do it.
>>>> Please advise. TIA
>>>
>>> You have to use 'std::locale' and 'std::put_money' read up on those
>>> for details. Teaser example:
>>>
>>> #include <iostream> // for std::cout
>>> #include <iomanip> // std::put_money and other utilities
>>>
>>> int main(int argc, char **argv)
>>> {
>>> const int amount = 1000000; // in cents
>>>
>>> std::cout.imbue(std::locale("en_US.UTF-8"));
>>>
>>> std::cout << std::showbase << std::put_money(amount) << '\n';
>>> }
>>>
>>> That should output ...
>>>
>>> $10,000.00
>>>
>>
>> UTF-8 for byte streams is not supported in Windows.
>>
>> So that's very non-portable code. ;-)
>
> UTF-8 is right now 83% - 87% of all web content ... so if Windows
> can't even byte stream that then what is it useful for?

It's not Windows, it's standard library implementations for Windows, and
it's not byte streams, it's the C++ narrow streams.

The proper standard-conforming portable way in C++ to produce or consume
UTF-8 is to use wide streams (they're designed to convert to/from
external bytes), with a properly translating buffer.

To be honest I think the whole C++ i/o design sucks. More than miss
Lovelace. And I'm not talking about Ada Lovelace.


> Perhaps
> something like "English_Australia.1252" will work there then. :-)

Maybe.

The only two standard locale names in C++ are "C" and "", where the
former is the C and C++ default locale, and the latter denotes the
user's default locale.

This is part of the low pressure area effect noted above.


>> Also, consider `num_put`. Mike's example indicates that it's just a
>> number, not a monetary amount.
>
> Perhaps 'num_put' is indeed best. I wondered how he can't find
> *anything* in stream I/O and so I just pointed direction. If he
> wants to use I/O utilities then he has quite lot to read there.

Yes, I wish the infamous Someone™ could come up with something better…


Cheers!,

- Alf

Good Guy

unread,
Aug 8, 2016, 1:15:30 PM8/8/16
to
On 08/08/2016 04:36, MikeCopeland wrote:
Not quite wqhat I'm looking for: I'm not working with money data, but large integer values. With your solution, there's no way to format integers >999 with punctuation. Am I missing something? --- 

Try the method given in this video.  You'll need to adapt the technique to suit your project.

<https://www.youtube.com/watch?v=n9_3MbIjQbE>



--
With over 350 million devices now running Windows 10, customer satisfaction is higher than any previous version of windows.

red floyd

unread,
Aug 8, 2016, 1:44:05 PM8/8/16
to
On 8/8/2016 10:15 AM, Good Guy wrote:
> On 08/08/2016 04:36, MikeCopeland wrote:
>> Not quite wqhat I'm looking for: I'm not working with money data, but
>> large integer values. With your solution, there's no way to format
>> integers >999 with punctuation. Am I missing something? ---
>
> Try the method given in this video. You'll need to adapt the technique
> to suit your project.
>
> <https://www.youtube.com/watch?v=n9_3MbIjQbE>
>
>

Dude, please don't post that ugly HTML here. Plain text ASCII, please.

Good Guy

unread,
Aug 8, 2016, 1:54:04 PM8/8/16
to
this one works:

// main.cpp

#include <iomanip>
#include <locale>
#include <iostream>
#include <sstream>

using namespace std;

class AndysCommaNumPunct : public numpunct <char>
{
protected:
    virtual char do_thousands_sep() const
    {
        return ',';
    }

    virtual string do_grouping() const
    {
        return "\003";
    }
};

template <class T>
string AndyFormatWithCommas(T value)
{
    stringstream ss;
    locale AndyCommaLoc( locale(), new AndysCommaNumPunct() );
    ss.imbue(AndyCommaLoc);
    ss << setprecision(2) << fixed << value;
    return ss.str();
}

int main()
{
    int anInt = 31235;
    
    cout << "int:    " << AndyFormatWithCommas(anInt) << endl;
    
    float aFloat = 31235.47987;
    
    cout << "float:  " << AndyFormatWithCommas(aFloat) << endl;
    
    long aLong = 987654321;
    
    cout << "long:   " << AndyFormatWithCommas(aLong) << endl;
    
    double aDouble = 987654321.126456789;
    
    cout << "double: " << AndyFormatWithCommas(aDouble) << endl;
    
    return 0;
}


Source: <https://www.youtube.com/watch?v=9SubQGhfgJQ>


red floyd

unread,
Aug 8, 2016, 4:19:12 PM8/8/16
to
On 8/8/2016 10:53 AM, Good Guy wrote:
[html redacted]

WTF do you have against plain text, dude?

Good Guy

unread,
Aug 8, 2016, 5:21:57 PM8/8/16
to

Actually there is a wonderful tool called Google that has most of the answers - some good and some not so good but it requires some effort to make them work.





--

If you want to filter all of my posts then please read this article:
<https://support.mozilla.org/en-US/kb/organize-your-messages-using-filters>
In step 7 select "Delete"

red floyd

unread,
Aug 8, 2016, 7:55:01 PM8/8/16
to
On 8/8/2016 2:21 PM, Good Guy wrote:
[red floyd wrote] WTF do you have against plain text, dude?
>
> Actually there is a wonderful tool called Google that has most of the
> answers - some good and some not so good but it requires some effort to
> make them work.

Do you even READ the posts you are replying to?

Alf P. Steinbach

unread,
Aug 9, 2016, 12:07:05 AM8/9/16
to
It's an ad bot.

Cheers!,

- Alf

Geoff

unread,
Aug 9, 2016, 2:33:58 AM8/9/16
to
On Sun, 7 Aug 2016 18:13:57 -0700, MikeCopeland <mrc...@cox.net> wrote:

> Given: a value of 17234987, is there a (good) way to format it for
>output as 17,234,987? I would have thought that stream i/o would
>support such formatting, but I can't find anything that seems to show
>how to do it.
> Please advise. TIA
>
>

I don't know if this is a "good" way and it's Microsoft C++ and CRT dependent
but I wrote this quite a while ago and have not had to touch it since:

//
//============================================================================
// Turns an unsigned long long into a string with localized separators
//============================================================================
//
std::string LocalizeNumber(unsigned long long number)
{
std::string str;
TCHAR temp[64], num[64];

_ui64toa_s(number, temp, sizeof temp, 10);
GetNumberFormat(LOCALE_USER_DEFAULT, 0, temp, NULL, num, sizeof num);
str.assign ( num );
return str;
}

red floyd

unread,
Aug 9, 2016, 2:23:27 PM8/9/16
to
On 8/8/2016 9:06 PM, Alf P. Steinbach wrote:
>
> It's an ad bot.

Doh!!!!

How could I be so stupid to miss that! Thanks, Alf!



Vir Campestris

unread,
Aug 9, 2016, 4:16:49 PM8/9/16
to
It is? But it's far too stupid for that...

Back to the OP - remember that when you and I see 123.456 it's a hundred
and something, to some nationalities that full stop is a thousands
separator and the value is over a hundred thousand... number formatting
brings nightmares. Nearly as bad as dates.

Andy

0 new messages