3

Given a number 12456789, I need to output 12,456,789 without much coding. Are there any built-in functions in either C, C++, or JavaScript I can use to do that?

Anonymous
  • 4,133
  • 10
  • 31
  • 38

6 Answers6

24

Yes this can be done automatically in C++ by setting the correct facet on the locale.

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


template<typename CharT>
struct Sep : public std::numpunct<CharT>
{
    virtual std::string do_grouping()      const   {return "\003";}
};

int main()
{
    std::cout.imbue(std::locale(std::cout.getloc(), new Sep <char>()));

    std::cout << 123456789 << "\n";

}

Note: The C-locale (The locale used when your application does not specifically set one) does not use a thousands separator. If you set the locale of your application to a specific language then it will pick up the languages specific method of grouping (without having to do anything fancy like the above). If you want to set the locale to what your machines current language settings (as defined by the OS) rather than a specific locale then use "" (empty string) as the locale.

So to set the locale based on your OS specific settings:

int main()
{
    std::cout.imbue(std::locale(""));

    std::cout << 123456789 << "\n";
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • better than the accepted answer here http://stackoverflow.com/questions/7276826/c-format-number-with-commas, which does not work without extensive study and jiggering. – Reb.Cabin Sep 01 '15 at 13:20
15

In C++ you'd typically use something like this:

std::locale loc("");
std::cout.imbue(loc);

std::cout << 1234567;

The locale with an empty name like this uses won't necessarily format the number exactly as you've specified above. Instead, it picks up the locale from the rest of the system, and formats appropriately, so for me (with my system set up for the US) it would produce "1,234,567", but if the system was set up for (most parts of) Europe, it would produce "1.234.567" instead.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • +1 can't get any easier than this :) I like C++ ^^ – default Aug 13 '10 at 18:55
  • This is not a precise answer, it depends on the default locale on the system. `std::locale loc("en_US.UTF-8");` may be more robust. – prehistoricpenguin Mar 27 '20 at 02:33
  • 1
    @prehistoricpenguin: I suppose that depends on how you define "robust". If you mean "may sometimes do something desirable, but other times fail completely", then yeah, that would be accurate (e.g., fails with minGW). But the point of the answer is that most of the time you should be trying to tailor the output to the user's desires, which is what the nameless locale tries to provide. – Jerry Coffin Mar 27 '20 at 04:49
3

In some C compiler implementations, and extension is provided for the printf familiy of functions such that a single-quote/apostrophe character used as a modifier in a numeric format specifier will perform 'thousands grouping':

#include <stdio.h>
#include <locale.h>

int main(void)
{
    printf( "%'d\n", 1234567);

    setlocale(LC_NUMERIC, "en_US");
    printf( "%'d\n", 1234567);

    return 0;
}

will produce (with GCC 4.4.1 anyway):

1234567
1,234,567

Unfortunately, this extension isn't particularly widely supported.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
2

For C++, you can try:

std::locale get_numpunct_locale(std::locale locale = std::locale(""))
{
#if defined(_MSC_VER) && defined(_ADDFAC) && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 403)
    // Workaround for older implementations
    std::_ADDFAC(locale, new std::numpunct<char>());
    return locale;
#else
    return std::locale(locale, new std::numpunct<TCHAR>());
#endif
}

template<class T>
std::string nformat(T value)
{
    std::ostringstream ss;
    ss.imbue(get_numpunct_locale());
    ss << value;
    return ss.str();
}
user541686
  • 205,094
  • 128
  • 528
  • 886
2

// Another javascript method, works on numbers

Number.prototype.withCommas= function(){    
    return String(this).replace(/\B(?=(?:\d{3})+(?!\d))/g,',')
}

var n=12456789.25;
alert(n.withCommas());

/* returned value: (String) 12,456,789.25 */

kennebec
  • 102,654
  • 32
  • 106
  • 127
1

I found this little javascript function that would work (source):

function addCommas(nStr){
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}
Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
micmoo
  • 5,991
  • 3
  • 22
  • 16