C ++对诸如ü等特殊字符赋权

时间:2017-03-14 16:27:45

标签: c++ character-encoding htmlspecialchars

我无法使用C ++中的tolower()函数将字符串转换为小写。使用普通字符串时,它会按预期工作,但不会成功转换特殊字符。

我如何使用我的功能:

string NotLowerCase = "Grüßen";
string LowerCase = "";
for (unsigned int i = 0; i < NotLowerCase.length(); i++) {
    LowerCase += tolower(NotLowerCase[i]);
    }

例如:

  1. 测试 - &gt;测试
  2. TeST2 - &gt; TEST2
  3. Grüßen - &gt;克????烯
  4. (§) - &gt; ()
  5. 3和4无法正常工作,因为您可以看到

    如何解决此问题?我必须保留特殊的字符,但是小写。

3 个答案:

答案 0 :(得分:5)

来自tolower的示例代码(如下)显示了您如何解决此问题;你必须使用默认的“C”语言环境以外的东西。

#include <iostream>
#include <cctype>
#include <clocale>

int main()
{
    unsigned char c = '\xb4'; // the character Ž in ISO-8859-15
                              // but ´ (acute accent) in ISO-8859-1 

    std::setlocale(LC_ALL, "en_US.iso88591");
    std::cout << std::hex << std::showbase;
    std::cout << "in iso8859-1, tolower('0xb4') gives "
              << std::tolower(c) << '\n';
    std::setlocale(LC_ALL, "en_US.iso885915");
    std::cout << "in iso8859-15, tolower('0xb4') gives "
              << std::tolower(c) << '\n';
}

您可能还会将std::string更改为std::wstring,这是许多C ++实现中的Unicode。

wstring NotLowerCase = L"Grüßen";
wstring LowerCase;
for (auto&& ch : NotLowerCase) {
    LowerCase += towlower(ch);
    }

Microsoft的指导是“Normalize strings to uppercase”,因此您可以改为使用touppertowupper

请记住,逐字符转换可能不适用于某些语言。例如,在德国使用德语,使Grüßen全部为大写,将其转换为GRÜESSEN(尽管现在有capital )。还有许多其他“问题”,如组合字符;如果你正在用字符串进行真正的“生产”工作,你真的想要一种完全不同的方法。

最后,C ++对管理语言环境提供了更为复杂的支持,有关详细信息,请参阅<locale>

答案 1 :(得分:1)

我认为最便携的方法是使用用户选择的语言环境,这是通过将语言环境设置为""(空字符串)来实现的。

std::locale::global(std::locale("")); 

将语言环境设置为程序运行时使用的任何语言环境,它会影响在多字节和宽字符字符之间进行转换的标准字符转换例程(std::mbsrtowcs&amp; std::wcsrtombs

然后,您可以使用这些函数将系统/用户选择的多字节字符(例如UTF-8)转换为系统标准宽字符代码,这些代码可用于运行std::tolower的函数一次一个角色。

这很重要,因为像UTF-8这样的多字节字符集无法使用std::tolower()之类的单字符操作进行转换。

将宽字符串版本转换为大写/小写后,可以将其转换回系统/用户多字节字符集,以便打印到控制台。

// Convert from multi-byte codes to wide string codes
std::wstring mb_to_ws(std::string const& mb)
{
    std::wstring ws;
    std::mbstate_t ps{};
    char const* src = mb.data();

    std::size_t len = 1 + mbsrtowcs(0, &src, 3, &ps);

    ws.resize(len);
    src = mb.data();

    mbsrtowcs(&ws[0], &src, ws.size(), &ps);

    if(src)
        throw std::runtime_error("invalid multibyte character after: '"
            + std::string(mb.data(), src) + "'");

    ws.pop_back();

    return ws;
}

// Convert from wide string codes to multi-byte codes
std::string ws_to_mb(std::wstring const& ws)
{
    std::string mb;
    std::mbstate_t ps{};
    wchar_t const* src = ws.data();

    std::size_t len = 1 + wcsrtombs(0, &src, 0, &ps);

    mb.resize(len);
    src = ws.data();

    wcsrtombs(&mb[0], &src, mb.size(), &ps);

    if(src)
        throw std::runtime_error("invalid wide character");

    mb.pop_back();

    return mb;
}

int main()
{
    // set locale to the one chosen by the user
    // (or the one set by the system default)
    std::locale::global(std::locale(""));

    try
    {
        string NotLowerCase = "Grüßen";

        std::cout << NotLowerCase << '\n';

        // convert system/user multibyte character codes
        // to wide string versions
        std::wstring ws1 = mb_to_ws(NotLowerCase);
        std::wstring ws2;

        for(unsigned int i = 0; i < ws1.length(); i++) {
            // use the system/user locale
            ws2 += std::tolower(ws1[i], std::locale("")); 
        }

        // convert wide string character codes back
        // to system/user multibyte versions
        string LowerCase = ws_to_mb(ws2);

        std::cout << LowerCase << '\n';
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }
    catch(...)
    {
        std::cerr << "Unknown exception." << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

代码未经过严格测试

答案 2 :(得分:-6)

使用ASCII

string NotLowerCase = "Grüßen";
string LowerCase = "";
for (unsigned int i = 0; i < NotLowerCase.length(); i++) {
    if(NotLowerCase[i]<65||NotLowerCase[i]>122)
    {
        LowerCase+='?';
    }
    else
        LowerCase += tolower(NotLowerCase[i]);
}