是否可以统一VSVC和GCC中的std :: wstring行为?

时间:2019-02-26 22:38:40

标签: c++ gcc visual-c++ utf-8 wstring

下面是一些从UFT-8文件读取一行的代码:

#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <locale>
#include <fstream>
#include <codecvt>

int main()
{
    _setmode(_fileno(stdout), _O_U8TEXT);

    auto inputFileStream = std::wifstream("input.txt");
    const auto utf8Locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>());
    inputFileStream.imbue(utf8Locale);

    std::wstring line;
    std::getline(inputFileStream, line);
    std::wcout << line << std::endl;

    inputFileStream.close();
    return 0;
}

当我使用Visual Studio Visual C ++编译器构建它时,得到了下一个结果:

  

测试τεστтест

符合预期。

当我将MinGW与GCC编译器一起使用时,我得到了

  

琀攀猀琀쐃딃쌃쐃䈄㔄䄄䈄

如您所知,这不是预期的结果。

  1. 是否存在任何简单方法将GCC的输出固定为预期的字符串?

OR

  1. 是否存在任何简单方法将UTF-8用于MSVC和GCC?

答案(感谢 Igor Tandetnik Remy Lebeau ): 似乎,我们必须明确指定字节序模式,因为MSVC和GCC具有不同的默认值。所以

new std::codecvt_utf8<wchar_t, 0x10ffff, std::little_endian>()

应该使用。

固定代码:

#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <locale>
#include <fstream>
#include <codecvt>

int main()
{
    _setmode(_fileno(stdout), _O_U8TEXT);

    auto inputFileStream = std::wifstream("input.txt");
    const auto utf8Locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t, 0x10ffff, std::little_endian>());
    inputFileStream.imbue(utf8Locale);

    std::wstring line;
    std::getline(inputFileStream, line);
    std::wcout << line << std::endl;

    inputFileStream.close();
    return 0;
}

1 个答案:

答案 0 :(得分:0)

对于第二个问题,一个选择是将utf16和带有std::w前缀的东西的使用限制为需要与操作系统交换utf16编码的字符串的情况。当您在wmain中接收参数,使用_wfopen打开文件,调用Windows API函数等时,会发生这种情况。否则,您将使用{{1来存储,从用户那里获取并返回到用户utf8字符串。 }}类型(charchar*等)。可以使用std::stringMultiByteToWideChar完成utf8和utf16之间的转换,绕过了延迟的c ++编码api。效果不好的地方是控制台输入/输出。总体而言,如果用户设置了WideCharToMultiByte和ttf字体,则可以将utf8输出到控制台。至少在Windows 7中,还必须确保不要在两个写调用之间分割字符,否则它将无法正确打印(这也意味着您不能使用chcp 65001,因为msvcrt会调用{{1} }分别用于每个字节,而您需要使用std::coutputc等);我听说这在Windows 10中已修复,但无法确认。据我所知,使用文件api从控制台读取utf8无效;如果需要的话,您需要检测stdin是否已附加到控制台,并改用控制台api。