为什么towlower()功能不能将Я转换为小写я?

Joh*_*nic 8 c++ unicode locale wchar-t lowercase

该功能towlower()似乎在Visual Studio 2012中不起作用.以下是一个示例:

#include <string>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <wctype.h>

using namespace std;

int main()
{
    _setmode(_fileno(stdout), _O_U8TEXT);
    wcout << (wchar_t)towlower(L'?') << endl;
    system("pause");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

角色仍然是大写字母.之前已经问过类似的问题,但我找不到任何解决方案.

我可以使用另一种方法来改变小写吗?

Ker*_* SB 6

使用区域设置感知版本tolower,但不要忘记也设置C语言环境.

例如:

#include <clocale>
#include <locale>
#include <iostream>

int main()
{
    std::setlocale(LC_CTYPE, "");
    std::wcout << L"The letter is: " << L'?' << L" => "
               << std::tolower(L'?', std::locale("")) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这打印:

The letter is: ? => ?
Run Code Online (Sandbox Code Playgroud)

在iostreams中使用locales是一项棘手的工作,并且在这背后隐藏着一个完整的Pandora盒子.例如,您可以使用语言环境填充流,并且您可以一次管理多个语言环境,特别是每个线程可以有一个(这可能是有状态字符串编码转换所必需的)...有人应该写一本关于该语言的书(或者改为使用Boost.Locale).


det*_*zed 5

我看到两种可能性.第一个是未正确设置区域设置.来自MSDN:

案例转换towlower是特定于语言环境的.只有与当前区域设置相关的字符才会被更改.没有_l后缀的函数使用当前设置的语言环境.

第二个是源文件编码.L'?'根据源文件的编码方式,可能意味着不同的东西.例如,如果你有它,它将无法工作UTF-8.确保你有它UTF-16.或者删除任何可能的混淆,就像这样'\u042F'

更新:第二个想法L是整个业务都很棘手.如果编译器正确理解编码,例如通过BOM,它可能没问题UTF-8或任何其他编码.重要的是它应该知道编码是什么.它必须是非常具体的实现.

另一个更新:要解决问题,请尝试通过以下方式设置区域设置:

_wsetlocale(LC_ALL, L"ru-RU");
Run Code Online (Sandbox Code Playgroud)

或使用将语言环境作为参数(_towlower_l)的版本.

而且还有一个pragma,它告诉编译器如何处理文件中的非ASCII字符串文字.