По сути, код "Hello World" немного модифицирован, должен быть корректно работать
#include <iostream>
#include <fstream>
using namespace std;
int main(){ wcout<<L"GoodMorning Καλημέρα"<<endl;return 0; }
я слишком много прошу? Это рассказ!
Длинная: Моя платформа - ubuntu и g++.
Как я недавно понял, потоки могут быть открыты в двоичном или текстовом режиме.
Когда мы используем wcout для печати wstring, режим должен быть текстовым, потому что широкая строка символов (по существу utf32) должна быть преобразована во время передачи из потока в "файл", чтобы получить кодовую страницу терминала (на самом деле это "кодовая страница" - utf8 - но может быть любой, например, в конкретном случае ISO8859-7).
Поэтому, когда мы используем:
std::wcout<<L"καλημέρα"<<std::endl;
если режим wcout является текстовым режимом, строка преобразуется из utf32 (linux - в условиях) или строки UCS2 (windows) в кодовую страницу терминала (linux utf8) в соответствии со стандартом std::locale::global
или к имбулу используемый в потоке.
Поэтому, чтобы работать с wcout, режим должен быть TEXT, а не BINARY. Но моя система открывает его в BINARY, а не в тексте, поэтому текст отображается неправильно.
Как изменить способ wcout
?
Текстовый или двоичный режим управляет только тем, преобразуется ли символ новой строки '\n'
в конец последовательности строк в системах, где текстовый файл имеет ограниченный успех и последовательность строк. В системах POSIX текст по сравнению с двоичным режимом не влияет. Тем не менее, нет стандартного способа управления текстовым и двоичным режимами. В системах POSIX вы, вероятно, можете просто заменить файловый дескриптор 1. Однако это не изменит используемую кодировку.
Когда вы чувствуете, что вам нужно играть с трюками с кодировками, вы почти наверняка получите поддержку при использовании потоков fike. Если вы хотите иметь дело с кодировками для других потоков, вам нужно реализовать собственный буфер потока, делающий конверсии.
Я индивидуализировал проблему, выход был использован внутри main следующим образом:
int main(){
std::locale::global(std::locale("en_US.utf-8"));
std::wcout<<L"Ελληνικά"<<std::endl;
Хотя широкая печать относится к числу первых инструкций по ее использованию, выход был неправильным. Я предположил, что, возможно, где-то внутри программы (могут быть инициализации) доступ к cout или wcout и поэтому установлен в двоичном режиме.
Я изменил его следующим образом:
#include <string>
#include <locale>
#include <iostream>
struct initLocale{
initLocale(){
std::locale::global(std::locale("en_US.utf-8"));
std::wcout<<L"Ελληνικά"<<std::endl;
}
Область действия заключается в создании фиктивной переменной сразу после включения с единственной областью для вывода чего-то в wcout, чтобы первым использовать ее. С этим изменением вывод правильный, как только я прокомментирую строку std::wcout<<L"Ελληνικά"<<std::endl;
выход снова ошибочен. Вы также можете изменить std::wcout<<L"Ελληνικά"<<std::endl;
в std::wcout<<std::endl
и он работает. Хотя я решил свою проблему, это должно быть каким-то образом и каким-либо образом указать вопрос о том, как изменить двоичное или текстовое поведение wcout.
Это хорошо работает для меня, используя g++ 4.8.1 в некотором старом Ubuntu:
#include <iostream>
#include <fstream>
#include <locale.h>
using namespace std;
int main()
{
setlocale( LC_ALL, "" );
wcout<<L"GoodMorning Καλημέρα"<<endl;
}
В Windows вам нужно вместо вызова _setmode
(и, если использовать g++, -U
символ макроса no-gcc-extensions-please).
Как уже отмечал Дитмар, режим текстового потока C не имеет к этому никакого отношения.
L
(как и ваш) - это не UTF32, это строка широких символов , именно так, как этого хочетstd::wcout
. Строка UTF32 в C ++ будет иметь префиксU
(см., Например, Википедию на C ++ 11 ). И нет, вы не можете изменить способ открытия стандартных потоков, если не хотите создать несовместимую нестандартную библиотеку C ++?