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

时间:2013-04-08 21:59:12

标签: c++ unicode locale lowercase wchar-t

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

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

我可以用另一种方法改为小写吗?

3 个答案:

答案 0 :(得分: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;
}

打印:

The letter is: Я => я

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

答案 1 :(得分:5)

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

  

towlower的大小写转换是特定于语言环境的。只有与当前相关的字符   区域设置更改以防万一。没有_l后缀的函数使用当前设置的区域设置。

第二个是源文件编码。根据源文件的编码方式,L'Я'可能表示不同的内容。例如,如果你在UTF-8中拥有它,它将无法工作。确保你在UTF-16中拥有它。或者删除任何可能的混淆,如'\u042F'

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

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

_wsetlocale(LC_ALL, L"ru-RU");

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

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

答案 2 :(得分:0)

它的伤害是否比拖曳更轻? J / K。我不熟悉反转的R,但是我知道如果角色没有小写等效,则(w)lower将返回原始角色。 http://en.cppreference.com/w/c/string/wide/towlower