C++降低特殊字符,例如 ü

C++ tolower on special characters such as ü

本文关键字:例如 特殊字符 C++      更新时间:2023-10-16

我很难用C 中的Tolower()函数将字符串转换为小写。使用普通字符串,它可以按预期工作,但是特殊字符并未成功转换。

我如何使用功能:

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

例如:

  1. 测试 ->测试
  2. test2-> test2
  3. grüßen-> gr ??? en
  4. (§) ->()

3和4无法如预期的那样工作,您可以看到

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

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的指导是"将字符串正常于大写",因此您可以使用touppertowupper

请记住,字符转换可能对某些语言不错。例如,使用德国在德国所说的德语,使grüßen 所有上案例都将其变成grüessen(尽管现在有一个Capital ßβ)。还有许多其他"问题"这样的组合字符。如果您正在与字符串进行真正的"生产"工作,那么您确实想要一种完全不同的方法。

最后,C 对管理语言环境有更复杂的支持,请参见<locale>

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

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

将语言环境设置为程序运行的任何正在使用的地方,并且会影响标准字符转换例程(std :: mbsrtowcs&amp; std :: wcsrtombs),它们在多字节和广泛的字符之间转换。<<<<<<<<<<<<<<<<<</p>

然后,您可以使用这些函数从系统/用户选择的多字节字符(例如UTF-8)转换为系统标准宽字符代码,这些字符可以在一个诸如std::tolower之类的函数中使用,该功能一次在一个字符上操作。<<<<<<<<<<<<<</p>

这很重要,因为可以使用std::tolower()等单个字符操作将多字节字符集(例如UTF-8)进行转换。

一旦将宽字符串版本转换为上/下情况,就可以将其转换回系统/用户多键字符集以打印到控制台。

// 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;
}

代码未经过深入测试

使用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]);
}