Используя длинные строки с wcout, простой «Hello World» не работает! (Как мне изменить способ открытия wcout BINARY или TEXT)

0

По сути, код "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?

  • 0
    Строковый литерал с префиксом L (как и ваш) - это не UTF32, это строка широких символов , именно так, как этого хочет std::wcout . Строка UTF32 в C ++ будет иметь префикс U (см., Например, Википедию на C ++ 11 ). И нет, вы не можете изменить способ открытия стандартных потоков, если не хотите создать несовместимую нестандартную библиотеку C ++?
  • 0
    Бывает, что в моей системе sizeof (wchar _) == sizeof (char32_t). Таким образом, данные, которые записываются внутри L "καλημέρα", представляют собой код Unicode для κα λ η µ έ ρα. Если бы это была платформа Windows, коды были бы такими же, но в 2 байтах вместо 4. Код выше не работает в моей системе (не показывает правильную строку).
Показать ещё 3 комментария
Теги:

3 ответа

2

Текстовый или двоичный режим управляет только тем, преобразуется ли символ новой строки '\n' в конец последовательности строк в системах, где текстовый файл имеет ограниченный успех и последовательность строк. В системах POSIX текст по сравнению с двоичным режимом не влияет. Тем не менее, нет стандартного способа управления текстовым и двоичным режимами. В системах POSIX вы, вероятно, можете просто заменить файловый дескриптор 1. Однако это не изменит используемую кодировку.

Когда вы чувствуете, что вам нужно играть с трюками с кодировками, вы почти наверняка получите поддержку при использовании потоков fike. Если вы хотите иметь дело с кодировками для других потоков, вам нужно реализовать собственный буфер потока, делающий конверсии.

  • 0
    Моя задача не в том, чтобы сделать какое-либо преобразование и позволить системе сделать это, это самый правильный способ сделать это.
  • 0
    Я проверил две локали в текстовом режиме и написал одну и ту же строку, например «καλημέρα», в файл один раз, используя локаль «el_GR.utf8», а другую - «el_GR.ISO8859-7». Результат был правильным, я использовал gedit и открыл файл с помощью utf8 в первом случае, когда файл показывался правильно (при использовании второй кодировки для его открытия каждый символ показывал double). Открытие файла, написанного с использованием el_GR.ISO8859-7 с той же кодировкой, файл показывал правильно. Я не знал этих уловок потоков, и я нашел их полезными, чтобы выполнить наименьшее количество работы.
0

Я индивидуализировал проблему, выход был использован внутри 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.

0

Это хорошо работает для меня, используя 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 не имеет к этому никакого отношения.

  • 0
    Ваши комментарии заставляют меня настаивать на том, что потоки C ++ могут использовать непереведенный или переведенный режим. Задача заключается в том, чтобы иметь возможность преобразовывать между внутренними широкими строками внешнюю кодовую страницу. Поэтому, когда вы пишете в файл, вы конвертируете широкую строку во внешнюю кодовую страницу (например, ISO8859-7 или UTF8). И наоборот, вы можете прочитать файл, сохраненный в формате utf-8, и прочитать его в своей строке, просто используя процедуру чтения без беспокоиться о преобразовании между utf8 и utf32. Проверьте это, чтобы поверить!
  • 0
    Да, код работает, потому что есть только этот код.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню