Visual C++:越野车 towupper

Posted

技术标签:

【中文标题】Visual C++:越野车 towupper【英文标题】:Visual C++: buggy towupper 【发布时间】:2014-02-12 07:58:13 【问题描述】:

给定以下代码:

#include <iostream>
#include <cwctype>
#include <clocale>

int main()

    wchar_t c = L'\u00ff'; // ÿ LATIN SMALL LETTER Y WITH DIAERESIS
                // → 0178 Ÿ latin capital letter y with diaeresis

    std::cout << std::hex << std::showbase;
#ifdef WIN32
    const char * lcc = setlocale(LC_ALL, "English");
#else
    const char * lcc = std::setlocale(LC_ALL, "en_US.cp1252");
#endif
    if(lcc) 
        std::cout << "set locale: " << lcc << std::endl;
        std::cout << "towupper(" << (std::wint_t)c << ") = " << towupper(c) << '\n';
     else 
        std::cout << "failed to set locale" << std::endl;
    

如果我在 Visual Studio 2010(也是 2013)中编译并运行它,结果是:

set locale: English_United States.1252
towupper(0xff) = 0x9f

在带有 gcc 的 Linux 上:

set locale: en_US.cp1252
towupper(0xff) = 0x178

towupper 的结果在两个平台上是不同的,linux/gcc 给出的答案对我来说似乎是正确的,因为 0x178 (Ÿ) 是 0xff (ÿ) 的正确大写 Unicode 代码点。

不过,0x9f 也是 Ÿ 的代码点,但在使用的 Windows-1252 代码页中。所以看起来好像 Visual C 的 towupper 会将输入视为窄字符,并根据预设的代码页进行解释。

就我的理解而言,宽字符应始终被解释为 Unicode 码位,在 Windows/VC 上为 UTF-16,在 Linux/gcc 上为 UTF-32。我在这里错了吗,或者它真的是微软实施中的一个错误?还是只是在这种情况下规范不够严格,两者都可以视为正确的结果?

【问题讨论】:

您将语言环境明确设置为 CP1252,这是一种 8 位编码。如果有的话,我会说异常版本是 Linux 版本,因为在 0xff 之外应该没有可用的字符(而且你会为 wstring 中的每个字符浪费至少 1 个字节)。 记录在案的 MSVC CRT 行为:“towupper 的大小写转换是特定于区域设置的”。对于 Linux:“这个函数不太适合处理 Unicode 字符”。 @user846250 据我了解,towupper 应该将输入视为 Unicode 代码点,因此不根据任何代码页对其进行解释。所以语言环境的代码页设置应该是无关紧要的。有一个 toupper 变体(没有'w')应该根据代码页解释输入。 @HansPassant 这可能是一个原因,因为它没有详细说明依赖于 towupper 语言环境的术语。但我认为它的语言环境依赖性是正确处理土耳其点和无点 i:I/ı 和 İ/i 等情况,而不是英语 I/i 大写/小写对。而且,Unicode 代码点 U+009F 是一个控制字符,不应该是任何其他字符的大写对。 您认为 C 语言适合 Unicode 的假设是错误的。这不可避免地会让某些人感到不安,ISO 委员会倾向于发现更容易给每个人带来不便。使用 ICU。 【参考方案1】:

从问题上的cmets看来,似乎没有“真正”的解决方案; C 或 C++ 标准在字符编码方面不够严格,因此我们无法对区域设置敏感的结果抱有真正的期望。

对于我在 Windows 上的特定用例,CharUpperW 被证明是一个可行的选择,尽管它取决于平台。

【讨论】:

以上是关于Visual C++:越野车 towupper的主要内容,如果未能解决你的问题,请参考以下文章

visual c++是啥?

Skia 越野车颜色混合

apache_conf 越野车PuPHPet

visual c++ 是啥软件

在 Visual C++ 2005 中开发的 Visual C++ 项目 - 在 Visual C++ 2010 中,打开菜单时调试断言失败,但发布模式有效,如何解决?

曝光强大越野基因,越野性能测试极限炫酷特技!太牛了