Я пытаюсь использовать механизм std::locale
в С++ 11 для подсчета слов на разных языках. В частности, у меня есть std::wstringstream
, который содержит название знаменитого русского романа ( "Преступление и наказание" на английском языке). Я хочу использовать соответствующий язык (ru_RU.utf8
на моей машине Linux) для чтения строкового потока, подсчета слов и печати результатов. Я также должен заметить, что моя система настроена на использование локали en_US.utf8
.
Желаемый результат:
0: "Преступление"
1: "и"
2: "наказание"
I counted 3 words.
and the last word was "наказание"
Это работает, когда я устанавливаю глобальную локаль, но не при попытке imbue
потока wcout
. Когда я попробую это, я получаю этот результат вместо:
0: "????????????"
1: "?"
2: "?????????"
I counted 3 words.
and the last word was "?????????"
Кроме того, когда я пытаюсь использовать решение, предлагаемое в комментариях (которое можно активировать, изменив #define USE_CODECVT 0
на #define USE_CODECVT 1
), я получаю ошибку, упомянутую в этой другой вопрос.
Те, кто заинтересован в эксперименте с кодом или с настройками компилятора или иными, могут захотеть использовать этот живой код.
Мои вопросы
- Почему это не работает? Это потому, что
wcout
уже открыт? - Есть ли способ использовать
imbue
вместо того, чтобы устанавливать глобальную локаль, чтобы делать то, что я хочу?
Если это имеет значение, я использую g++ 4.8.3. Полный код показан ниже.
getwords.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <locale>
#define USE_CODECVT 0
#define USE_IMBUE 1
#if USE_CODECVT
#include <codecvt>
#endif
using namespace std;
int main()
{
#if USE_CODECVT
locale ru("ru_RU.utf8",
new codecvt_utf8<wchar_t, 0x10ffff, consume_header>{});
#else
locale ru("ru_RU.utf8");
#endif
#if USE_IMBUE
wcout.imbue(ru);
#else
locale::global(ru);
#endif
wstringstream in{L"Преступление и наказание"};
in.imbue(ru);
wstring word;
unsigned wordcount = 0;
while (in >> word) {
wcout << wordcount << ": \"" << word << "\"\n";
++wordcount;
}
wcout << "\nI counted " << wordcount << " words.\n"
<< "and the last word was \"" << word << "\"\n";
}