In MSVC++, if you create a new Visual Studio console application (x64 platform, running on Windows 8.1, x64), and set it to a Unicode character set with the following code in main:
int _tmain(int argc, _TCHAR* argv[])
{
stringstream stream;
stream << _T("Testing Unicode. English - Ελληνικά - Español.") << std::endl;
string str = stream.str();
std::wcout << str.c_str();
cin.get();
}
It outputs this:
00007FF616443E50
I would like it to output this instead:
Testing Unicode. English - Ελληνικά - Español.
How can this be achieved?
Edit: With wstringstream and wstring instead:
wstringstream stream; stream << _T("Testing Unicode. English - Ελληνικά - Español.") << std::endl;
wstring str = stream.str();
std::wcout << str.c_str();
The output is truncated:
Testing Unicode. English -
Setting the mode like so: _setmode(_fileno(stdout), _O_U16TEXT);
The output is still undesirable because not all characters get rendered properly:
Testing Unicode. English - ???????? - Español.
Setting the output CP like so: SetConsoleOutputCP(CP_UTF8);
The output is again truncated:
Testing Unicode. English -
Using the following just doesn't work alone.. What you must also do is right click the Visual Studio console that pops up. Click Default Properties. Click the Fonts tab and set the font to Lucida Consolas. Then the below code will run just fine. Without the overloads of the << operator
for windows, it will NOT work. You may also want to make an overload for char
or wchar_t
or simply make this a template overload..
If you do not like the overloads, you may use _setmode(_fileno(stdout), _O_U16TEXT);
or _setmode(_fileno(stdout), _O_U8TEXT);
for UTF16 and UTF8 respectfully.
// Unicode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <sstream>
#include <iostream>
#if defined _WIN32 || defined _WIN64
#include <Windows.h>
#else
#include <io.h>
#include <fcntl.h>
#endif
#if defined _WIN32 || defined _WIN64
std::ostream& operator << (std::ostream& os, const char* data)
{
SetConsoleOutputCP(CP_UTF8);
DWORD slen = strlen(data);
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), data, slen, &slen, nullptr);
return os;
}
std::ostream& operator << (std::ostream& os, const std::string& data)
{
SetConsoleOutputCP(CP_UTF8);
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), data.c_str(), data.size(), nullptr, nullptr);
return os;
}
std::wostream& operator <<(std::wostream& os, const wchar_t* data)
{
DWORD slen = wcslen(data);
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), data, slen, &slen, nullptr);
return os;
}
std::wostream& operator <<(std::wostream& os, const std::wstring& data)
{
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), data.c_str(), data.size(), nullptr, nullptr);
return os;
}
#endif
int _tmain(int argc, _TCHAR* argv[])
{
std::wstringstream stream;
stream << _T("Testing Unicode. English - Ελληνικά - Español.") << std::endl;
#if !defined _WIN32 && !defined _WIN64
_setmode(_fileno(stdout), _O_U16TEXT);
#endif
std::wstring str = stream.str();
std::wcout << str;
std::wcin.get();
return 0;
}
On Windows there is ONE more thing that can help render fonts in ANY language.. I found this was not posted anywhere else on the net.. I navigated to Control Panel\Appearance and Personalization\Fonts
. I clicked Font Settings
and then unchecked Hide fonts based on language settings
. Saved the options. This will allow you to write Japanese and Chinese characters as well as arabic and whatever other languages you want. Seems to work with the default console fonts as well.. I had to restart for it to take effect though. Not sure if it actually works for anyone else..