【发布时间】:2019-09-16 11:28:09
【问题描述】:
这是我的程序:
#include <iostream>
#include <string>
#include <locale>
#include <clocale>
#include <codecvt>
#include <io.h>
#include <fcntl.h>
int main()
{
fflush(stdout);
_setmode(_fileno(stdout), _O_U16TEXT);
std::ios_base::sync_with_stdio(false);
std::setlocale(LC_ALL, "el_GR.utf8");
std::locale loc{ "el_GR.utf8" };
std::locale::global(loc); // apparently this does not set the global locale
//std::wcout.imbue(loc);
//std::wcin.imbue(loc);
std::wstring yes;
std::wcout << L"It's all good γεια ναί" << L'\n';
std::wcin >> yes;
std::wcout << yes << L'\n';
return 0;
}
假设我想支持希腊编码(对于 both 输入和输出)。如果我设置了适当的编码并且当然删除了fflush(stdout) 和_setmode(),这个程序可以在Linux 上完美运行各种输出和输入语言。
所以在 Windows 上,当我使用 std::locale::global(loc) 时,该程序将正确输出希腊语(和英语),但它不会接受我从键盘输入的希腊语输入。如果我输入希腊语,std::wcout << yes 会输出乱码或问号。显然::global 在 Windows 上不是真正的全局变量?
所以我在wcout 和wcin(也适用于Linux)上尝试了.imbue() 方法,您在此处看到注释掉了。当我使用这两个语句中的任何一个并运行程序时,它会(正确编译)向我显示一个提示,当我按 w/e 然后按“输入”时,它会简单地退出而没有错误或诸如此类。
我尝试了一些特定于 Windows 的命令,但后来我也感到困惑。我不清楚我应该在 Windows 上尝试什么以及何时尝试。
所以问题是我如何才能像上面的程序一样在 Windows 中正确输入和输出希腊文本?我使用 MSVS 2017 最新更新。提前致谢。
【问题讨论】:
-
编辑“给我一个提示,当我按下时”:它不会给我一个提示。它不会给我任何东西。控制台只允许我输入,当我按 enter 时它只是退出。请注意,我还在 MSVS 上设置了“使用 Unicode 字符集”,并且还有 Lucida 控制台。
-
Streams 默认为 ANSI 模式,对于控制台,这使用其旧代码页 API,因此读取希腊输入取决于控制台输入代码页是 737 还是 1253,可以通过
SetConsoleCP设置。我认为 CRT 的最新版本允许通过其宽字符 UTF-16 API 从控制台读取。试试_setmode(_fileno(stdin), _O_U16TEXT)。 -
@ErykSun 是的!有用!我不需要
SetConsoleCP,只是_setmode(_fileno(stdin), _O_U16TEXT)做到了。但是,当我在std::wcout和std::wcin上.imbue时,它会输出错误:“Debug Assertion Failed! Program: ... File: minkernel\crts\ucrt\src\appcrt\stdio\fgetc.cpp line: 50表达式: ((_Stream.is_string_backed())) || (fn = _fileno(_Stream.public_stream()), ((_textmode_safe(fn) == __crt_lowio_text_mode::ansi) && !_tm_unicode_safe(fn)))) ..` -
@Nikos,备份几个 cmets 到我讨论通过
GetConsoleMode检测控制台的地方(成功)。如果我们有控制台,那么我们必须使用_O_U16TEXT,因为通常不支持将 UTF-8 与控制台的旧代码页 API 一起使用。 (Windows 8+ 通过代码页 65001 支持 UTF-8 输出,但所有版本的 UTF-8 输入仍然中断。) -
您可以以 UTF16 格式读取/写入用户数据,并以 UTF8 格式读取/写入文件以实现兼容性。使用
WideCharToMultiByte(CP_UTF8,...)/MultiByteToWideChar进行UTF16/UTF8 转换。
标签: c++ windows winapi locale facet