Question

I have the following C++ code

char* locale = setlocale(LC_ALL, "German"); // Get the CRT's current locale.
std::locale lollocale(locale);
setlocale(LC_ALL, locale); // Restore the CRT.
wcout.imbue(lollocale); // Now set the std::wcout to have the locale that we got from the CRT.

COORD cur = { 0, 0 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);
wcout << L"Enemy " << this->enemyStrengthLeft << L"/" << this->enemyStrength << endl;
wcout << L"◄";
for (int i = 0; i < 20; i++) {
  if (i % 2 == 0)
    wcout << L"■";
  else
    wcout << L" ";
}
wcout << L"►" << endl;

When I execute it, the unicode characters are not in the cmd windows, how can I fix it?

EDIT

I use Lucida Console as font.

EDIT 2

If it helps, I am running Visual Studio 2013 Express for Desktop under Windows 7 Enterprise SP1 64bit

Was it helpful?

Solution

Windows doesn't support Unicode through the standard library very well. Printing arbitrary Unicode to the console via the standard library can be done but it's not very convenient and all the methods I know of have unpleasant side effects.

Just use the Windows API:

std::wstring s = L"◄ ■ ►";
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), s.c_str(), s.size(), nullptr, nullptr);

On a side note, your code to get the locale and restore it isn't doing what you think, and there's a better way.

char* locale = setlocale(LC_ALL, "German"); // Get the CRT's current locale.
std::locale lollocale(locale);
setlocale(LC_ALL, locale); // Restore the CRT.

setlocale returns the locale name in effect after the function runs. So you're always going to get the name of a German locale, and the global locale will not get restored to its original value. If you really want to get the currently set locale then you can do so by passing nullptr instead of a locale name:

char const *locale = std::setlocale(LC_ALL, nullptr);

This gets the current locale without changing it.

However you should know that unless the locale is changed at some point then it will be the "C" locale. C and C++ programs always start in this locale. The "C" locale does not necessarily let you use characters outside the basic source character set (which does not even include all of ASCII, let alone characters like 'ä', 'ö', 'ü', 'ß', '◄', '■', and '►'.

If you want to get the locale that the user's machine is configured to use then you can use an empty string as the name. You can also imbue a stream with this locale without bothering with the global locale.

cout.imbue(std::locale("")); // just imbue a stream

char const *locale = std::setlocale(LC_ALL, ""); // set global locale to user's preferred locale, and get the name of that locale.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top