wcout не выводит по желанию - PullRequest
0 голосов
/ 27 апреля 2018

Я пытался написать приложение на c ++ для проекта и столкнулся с этой проблемой. В основном:

class OBSClass
{
public:
    wstring ClassName;
    uint8_t Credit;
    uint8_t Level;

    OBSClass() : ClassName(), Credit(), Level() {}
    OBSClass(wstring name, uint8_t credit, uint8_t hyear)
    : ClassName(name), Credit(credit), Level(hyear)
    {}
};

В другом файле:

vector<OBSClass> AllClasses;
...
AllClasses.push_back(OBSClass(L"Bilişim Sistemleri Mühendisliğine Giriş", 3, 1));
AllClasses.push_back(OBSClass(L"İş Sağlığı ve Güvenliği", 3, 1));
AllClasses.push_back(OBSClass(L"Türk Dili 1", 2, 1));
... (rest omitted, some of entries have non-ASCII characters like 'ş' and 'İ')

У меня есть функция, в основном выводит все в AllClasses, проблема в том, что wcout не выводит как нужно.

void PrintClasses()
{
    for (size_t i = 0; i < AllClasses.size(); i++)
    {
        wcout << "Class: " << AllClasses[i].ClassName << "\n";
    }
}

Вывод «Класс: Били» и ничего больше. Программа даже не пытается вывести другие записи и просто зависает. Я на Windows, используя G ++ 6.3.0. И я не использую Windows 'cmd, я использую bash от mingw, поэтому кодирование не будет проблемой (или нет?). Любой совет?

Редактировать: Кодировка исходного кода также не является проблемой, только что проверил, что это UTF8, по умолчанию VSCode

Редактировать: Также только что проверил, если проблема со строковыми литералами

wstring test;
wcin >> test;
wcout << test;

Введено несколько не-ASCII символов, таких как 'ö' и 'ş', все работает отлично. В чем проблема с широкими строковыми литералами?

Редактировать: Вот, пожалуйста,

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<wstring> testvec;

int main()
{
    testvec.push_back(L"Bilişim Sistemleri Mühendisliğine Giriş");
    testvec.push_back(L"ıiÖöUuÜü");
    testvec.push_back(L"☺☻♥♦♣♠•◘○");
    for (size_t i = 0; i < testvec.size(); i++)
        wcout << testvec[i] << "\n";
    return 0;
}

Компиляция с G ++: g ++ file.cc -O3

Этот код выводит только 'Bili'. Должно быть что-то с тем, что g ++ испортил двоичную кодировку (?), Поскольку ввод значений с wcin и вывод их с wcout не создает никаких проблем.

1 Ответ

0 голосов
/ 27 апреля 2018

Следующий код работает для меня, используя MinGW-w64 7.3.0 в MSYS2 Bash и Windows CMD; и с источником, закодированным как UTF-8:

#include <iostream>
#include <locale>
#include <string>
#include <codecvt>

int main()
{
    std::ios_base::sync_with_stdio(false);

    std::locale utf8( std::locale(), new std::codecvt_utf8_utf16<wchar_t> );
    std::wcout.imbue(utf8);

    std::wstring w(L"Bilişim Sistemleri Mühendisliğine Giriş");
    std::wcout << w << '\n';
}

Пояснение:

  • Консоль Windows не поддерживает 16-битный вывод; это только ANSI и частичная поддержка UTF-8. Поэтому вам необходимо настроить wcout для преобразования вывода в UTF-8. Это значение по умолчанию для целей обратной совместимости, хотя Windows 10 1803 добавляет опцию для установки этого значения в UTF-8 (ref) .
  • imbue с codecvt_utf8_utf16 достигает этого; однако вам также необходимо отключить sync_with_stdio, иначе поток даже не использует фасет, он просто переносит на stdout, что имеет аналогичную проблему.

Для записи в другие файлы я обнаружил, что та же техника работает для написания UTF-8. Для записи файла UTF-16 вам необходимо наполнить wofstream фасетом UTF-16, , см. Пример здесь , и вручную написать спецификацию.


Комментарий: Многие люди просто избегают попытки полностью использовать широкие потоки из-за этих проблем.

Вы можете записать файл UTF-8, используя узкий поток; и иметь вызовы функций в вашем коде для преобразования wstring в UTF-8, если вы используете wstring для внутреннего использования; Вы, конечно, можете использовать UTF-8 для внутреннего использования.

Конечно, вы также можете написать файл UTF-16, используя узкий поток, но не с operator<< из wstring.

...