0

I'm on Mac OS X, using clang++ 6.0.

I can print an std::string of Thai characters to my console. I can convert it to an array of wide characters using mbsrtowcs(). But printing character by character shows only question marks '?'. I must not understand something about it.

Could someone kindly advise how I can print each character, or is it possible? I know the system knows the characters, because it can print them in an array of wide characters (see output below).

The code:

#include <iostream>
using namespace std;

int main ()
{
    cout << "Your prefered locale is: " << locale("").name() << endl;
    cout << "Your default locale is: " << locale().name() << endl;

    // you need to imbue wcout with en_US.UTF-8, since fileencoding is en_US.UTF-8, and so these wide characters are too. 
    wcout.imbue(locale("en_US.UTF-8") );

    // The full  name of Bangkok.
    const string s{"กรุงเทพมหานคร อมรรัตนโกสินทร์ มหินทรายุธยา มหาดิลกภพ  นพรัตนราชธานีบูรีรมย์ อุดมราชนิเวศน์มหาสถาน อมรพิมานอวตารสถิต  สักกะทัตติยวิษณุกรรมประสิทธิ์"};
    cout << s << endl;

    // Let's try to convert this.
    mbstate_t mbs;
    char const *p = s.c_str();
    wchar_t wc[s.length()];
    size_t wchars_written = mbsrtowcs(wc,&p,s.length(),&mbs);

    wcout.imbue(locale());
    if (NULL == p) cout << "Problem with mbsrtowcs : " << p << endl;
    else cout << "mbsrtowcs success! number of wchars written: " <<  wchars_written << endl;

    wcout << "The converted string: " << endl << wc << endl;
    cout << "The converted characters: " << endl ; 
    for (auto&& c: wc) wcout << c << L'\t';
    cout <<endl;
    return 0;
}

The output:

Your prefered locale is: 
Your default locale is: C
กรุงเทพมหานคร อมรรัตนโกสินทร์ มหินทรายุธยา มหาดิลกภพ  นพรัตนราชธานีบูรีรมย์ อุดมราชนิเวศน์มหาสถาน อมรพิมานอวตารสถิต  สักกะทัตติยวิษณุกรรมประสิทธิ์
mbsrtowcs success! number of wchars written: 420
The converted string: 
กรุงเทพมหานคร อมรรัตนโกสินทร์ มหินทรายุธยา มหาดิลกภพ  นพรัตนราชธานีบูรีรมย์ อุดมราชนิเวศน์มหาสถาน อมรพิมานอวตารสถิต  สักกะทัตติยวิษณุกรรมประสิทธิ์
The converted characters: 
?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?   ?
  • Your `string s` variable is not UTF-8 encoded, unless your source file is saved as UTF-8. Better to use `u8"..."` to force UTF-8 regardless of source encoding. Also, `wchar_t wc[s.length()];` is not portable code, try using `std::wstring_convert` instead of `mbsrtowcs()`. – Remy Lebeau Jul 16 '18 at 21:59
  • In any case, since you are dealing with Unicode, printing out a `std::wstring` or `wchar_t[]` in one go has access to all of the UTF surrogate data (assuming your compiler uses UTF-16 for `wchar_t` strings) so strings can be decoded back to Unicode properly for re-encoding to the console's output encoding. Outputting individual `wchar_t` characters one at a time does not have that same access. That could easily account for the `?` you see in the output. – Remy Lebeau Jul 16 '18 at 22:02

0 Answers0