wcout没有按照需要输出

时间:2018-04-26 23:52:28

标签: c++ windows utf-8 iostream widestring

我一直在尝试为项目编写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";
    }
}

输出是'Class:Bili',没有别的。程序甚至不会尝试输出其他条目而只是挂起。我在使用G ++ 6.3.0的Windows上。我没有使用Windows的cmd,我使用mingw的bash,所以编码不会有问题(或者不是吗?)。有什么建议吗?

编辑:源代码编码也不是问题,只需检查它是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输出它们不会产生任何问题。

2 个答案:

答案 0 :(得分:1)

以下代码适用于我,在MSYS2 Bash和Windows CMD中使用MinGW-w64 7.3.0;并且源编码为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)
  • {li> imbue codecvt_utf8_utf16实现此目标;但是你还需要禁用sync_with_stdio,否则流甚至不会使用facet,它只是推迟到有类似问题的stdout

为了写入其他文件,我发现相同的技术可以编写UTF-8。要编写UTF-16文件,您需要为wofstream填充UTF-16方面see example here,并手动编写BOM。

评论:由于这些问题,许多人只是完全避免尝试完全使用广泛的iostream。

您可以使用窄流编写UTF-8文件;如果您在内部使用wstring,则在代码中进行函数调用以将wstring转换为UTF-8;你当然可以在内部使用UTF-8。

当然,您也可以使用窄流编写UTF-16文件,而不是使用operator<<中的wstring

答案 1 :(得分:0)

如果您至少具有Windows 10 1903(2019年5月),并且至少具有 Windows Terminal 0.3.2142(2019年8月)。然后设置Unicode:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"OEMCP"="65001"

,然后重新启动。之后,您可以使用以下代码:

#include <iostream>

int main() {
   std::string a[] = {
      "Bilişim Sistemleri Mühendisliğine Giriş",
      "Türk Dili 1",
      "İş Sağlığı ve Güvenliği",
      "ıiÖöUuÜü",
      "☺☻♥♦♣♠•◘○"
   };

   for (auto s: a) {
      std::cout << s << std::endl;
   }
}