为什么towlower()函数不将Я转换为小写的字符?

Why does the towlower() function not convert the Я to a lower-case я?

本文关键字:字符 转换 towlower 函数 为什么      更新时间:2023-10-16

函数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;
}

字符保持大写。以前这里也有人问过类似的问题,但我找不到任何解决办法。

是否有其他方法可以将其改为小写?

使用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;
}
这个打印

:

The letter is: Я => я

在iostreams中使用区域设置是一件棘手的事情,这背后隐藏着一个完整的潘多拉魔盒。例如,你可以用一个语言环境注入流,你可以一次管理多个语言环境,特别是你可以每个线程有一个(这可能是有状态字符串编码转换所必需的)…应该有人写一本关于这个的书(或者使用Boost.Locale)。

我认为有两种可能性。第一个是locale设置不正确。从MSDN:

towlower的大小写转换与语言环境有关。只有与当前相关的字符区域设置在情况下会改变。没有_l后缀的函数使用当前设置的区域设置。

第二个是源文件编码。L'Я'可能意味着不同的东西,这取决于源文件的编码方式。它不会工作,例如,如果你有它在UTF-8。确保你把它放在UTF-16。或者为了消除任何可能的混淆,像这样写'u042F'

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

另一个更新:要解决这个问题,请尝试通过:

设置区域设置
_wsetlocale(LC_ALL, L"ru-RU");

或者使用将区域设置作为参数的版本(_towlower_l)。

上面还有一个pragma,告诉编译器如何处理文件中的非ascii字符串。

它造成的伤害比更高吗?j/k。我不熟悉反转的R,但我知道如果字符没有对应的小写字母,to(w)lower将返回原始字符。http://en.cppreference.com/w/c/string/wide/towlower