1

While learning more about standard library, I came across put_money. My code:

 std::cout.imbue(std::locale("en_US.UTF-8"));
    std::cout << std::left << std::showbase << std::setfill('*')
              << "flt: " << std::setw(15) << -9.87 << '\n'
              << "hex: " << std::setw(15) << 41 << '\n'
              << " $: " << std::setw(15) << std::put_money(367, false) << '\n'
              << "usd: " << std::setw(15) << std::put_money(367, true) << '\n'
              << "usd: " << std::setw(15)
              << std::setfill(' ') << std::put_money(367, false) << '\n';

But while compiling this code I received an error stating:

C:\Users\tbhar\Documents\C++ codes>cd "c:\Users\tbhar\Documents\C++ codes\" && g++ codetester.cpp -Wall -Wextra -o codetester && "c:\Users\tbhar\Documents\C++ codes\"codetester
terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid   

Similar error is occuring while using functions like: std::put_money, std::get_time, and std::put_time. I don't know why I am receiving this error.

  • 3
    You say that this is a compile error, but it looks like a runtime error. Please clarify, and indicate which line the error occurs at. – Raymond Chen Dec 21 '20 at 19:15
  • 1
    Related: [https://stackoverflow.com/questions/18686466/stdlocalefacet-s-create-c-locale-name-not-valid](https://stackoverflow.com/questions/18686466/stdlocalefacet-s-create-c-locale-name-not-valid) – drescherjm Dec 21 '20 at 19:16
  • 5
    The error seems to imply that the locale you named doesn't exist or, at least, isn't accessible to the C++ program. I'd recommend first trying with a known to exist locale (the only locale require required by the C++ standard is named `"C"`) and then research where kind of locales exist on your system. – Dietmar Kühl Dec 21 '20 at 19:17
  • @DietmarKühl How to search for the kind of locales that exist on my system? – Tushar Bharti Dec 21 '20 at 19:23
  • 2
    If you are using MS Windows: [https://stackoverflow.com/questions/27614666/print-all-stdlocale-names-windows/27615711#27615711](https://stackoverflow.com/questions/27614666/print-all-stdlocale-names-windows/27615711#27615711) if you are not typing `locale -a` on the terminal probably will tell you. – drescherjm Dec 21 '20 at 19:24
  • 1
    _@Tushar_ Put a [mcve] reproducing the problem [into your quesiton](https://stackoverflow.com/posts/65398643/edit) as required here please. As is we cannot really help in diagnosing the real source of the problem. – πάντα ῥεῖ Dec 21 '20 at 19:24
  • @DietmarKühl I searched for the locales that exists in my system and I found that en-US exists in my system and using that as my locale I am still getting the same error. – Tushar Bharti Dec 21 '20 at 19:46
  • @TusharBharti: The C++ standard doesn't define a way to list existing locales and I never bothered to find out how systems actually determine these. The error message you get is quite clear, though. If you think a locale should exist you may need to research your compiler/library's documentation to find out how it finds its locales. – Dietmar Kühl Dec 21 '20 at 20:06

1 Answers1

3

As @Dietmar Kühl commented, this seems to be a problem with your installation simply lacking the locale you've asked it to use. I added enough to get it to compile to get:

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

int main() { 
    std::cout.imbue(std::locale("en_US.UTF-8"));
    std::cout << std::left << std::showbase << std::setfill('*')
              << "flt: " << std::setw(15) << -9.87 << '\n'
              << "hex: " << std::setw(15) << 41 << '\n'
              << " $: " << std::setw(15) << std::put_money(367, false) << '\n'
              << "usd: " << std::setw(15) << std::put_money(367, true) << '\n'
              << "usd: " << std::setw(15)
              << std::setfill(' ') << std::put_money(367, false) << '\n';
}

...and when I ran it, got the following output:

flt: -9.87**********
hex: 41*************
 $: $3.67**********
usd: USD *3.67******
usd: $3.67   

His suggestion to use the "C" locale is sort of reasonable (it is guaranteed to exist), but will often give different results, such as:

flt: -9.87**********
hex: 41*************
 $: 367************
usd: 367************
usd: 367            

You could also try the locale that shall remain nameless (std::cout.imbue(std::locale(""));). I believe this is also guaranteed to exist, and is intended to choose the native locale for which the OS is configured (but could end up the same as the "C" locale). In this case (on my machine) it produces the same results as en_US, but if your vendor happens to spell the name differently, "" may work when some non-empty string fails.

On Windows (using Microsoft VC++ 2019) it seems to work for me as well:

flt: -9.87**********
hex: 41*************
 $: $3.67**********
usd: USD3.67********
usd: $3.67

Perhaps you're using MinGW? Doing a quick test, it only seems to support the "C" locale. The "" locale ends up the same as the C locale, and any other name I try crashes (though I get a slightly different error message than you've shown).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Yes I am using MinGW and as I stated in the comments above that en-US exists in my system, I don't understand bro why I am still getting the same error – Tushar Bharti Dec 21 '20 at 19:51
  • @TusharBharti: as I said, MinGW seems to lack support for anything but the "C" locale. VC++ works fine, but on the same system, MinGW fails completely (and the fact that it's "" locale is identical to its "C" locale is a pretty strong indication, at least to me, that regardless of the rest of the system, *it* only supports the "C" locale. – Jerry Coffin Dec 21 '20 at 19:56