将一种字符类型转换为另一种字符

时间:2015-07-16 17:55:09

标签: c++

我正在创建一个将字符更改为大写/小写的函数。但是,我使用模板来允许使用任何字符类型(char/wchar/char16_t/char32_t)。

我的问题是如何将wchar_t/char16_t/char32_t转换为char,以便可以使用std::islower(...)std::tolower(...)以及等效的大写函数进行检查和转换,然后将它们更改回原始的char类型。

template<typename CharT>
CharT* UpperCase(CharT* str) {
    CharT* out;

    //Conversion goes here

    for(Uint i = 0; i < std::char_traits<CharT>::length(str); i++)
        std::strcat(string, str[i]);

    //Conversion goes here

    return out;
}

1 个答案:

答案 0 :(得分:3)

std::islower()std::tolower()对当前语言环境中表达的char数据进行操作。还有std::iswlower()std::towlower()函数可用于wchar_t数据(请注意,它们不支持UTF-16代理)。

您必须将输入字符串转换为wchar_t或本地化char,根据需要进行小写比较/转换,然后在完成后将结果转换回原始编码。

请记住:

    对于非ASCII字符,
  • 与本地化char之间的转换可能会有损失,具体取决于区域设置。

  • char之间的转换(仅限UTF-7/8)&lt; - &gt; wchar_t(UTF-16或UTF-32,具体取决于平台)&lt; - &gt; char16_t(UTF-16)&lt; - &gt; char32_t(UTF-32)是无损的,因为所有UTF都代表整个Unicode指令,专为无损转换而设计。

因此,为了尽量减少数据丢失,我建议您使用std::iswlower() / std::towlower(),然后创建一些额外的模板,以帮助您从CharT&lt; - &gt;转换字符串。 wchar_t使用适当的转化。您可以为codecvt使用标准的与区域设置无关的char类(仅限UTF-8)/ char16_t / char32_t&lt; - &gt;转化wchar_t次。对于char&lt; - &gt;对wchar_t数据进行本地化的char次转化,您可以使用std::mbtowc() / std::mbrtowc()或区域设置相关的codecvt类。没有标准的函数/类来处理UTF-7,你必须手动实现它。

例如:

std::wstring toWString(const std::basic_string<char> &str)
{
    // if output is UTF-8, use std::codecvt_utf8 or std::codecvt_utf8_utf16 instead...
    std::wstring_convert<std::codecvt<wchar_t, char>> conv;
    return conv.from_bytes(str);
}

std::basic_string<char> fromWString(const std::wstring &str)
{
    // if output is UTF-8, use std::codecvt_utf8 or std::codecvt_utf8_utf16 instead...
    std::wstring_convert<std::codecvt<wchar_t, char>> conv;
    return conv.to_bytes(str);
}

std::wstring toWString(const std::basic_string<wchar_t> &str)
{
    return str;
}

std::basic_string<wchar_t> fromWString(const std::wstring &str)
{
    return str;
}

std::wstring toWString(const std::basic_string<char16_t> &str)
{
    std::wstring_convert<std::codecvt_utf16<char16_t>> conv;
    const char16_t *ptr = str.c_str();
    return conv.from_bytes( reinterpret_cast<const char*>(ptr), reinterpret_cast<const char*>(ptr + str.length()) );
}

std::basic_string<char16_t> fromWString(const std::wstring &str)
{
    std::wstring_convert<std::codecvt_utf16<char16_t>> conv;
    std::string tmp = conv.to_bytes(str);
    return std::u16string( reinterpret_cast<const char16_t*>(tmp.c_str()), tmp.length() * sizeof(char16_t) );
}

std::wstring toWString(const std::basic_string<char32_t> &str)
{
    std::wstring_convert<std::codecvt_utf16<char32_t>> conv;
    const char32_t *ptr = str.c_str();
    return conv.from_bytes( reinterpret_cast<const char*>(ptr), reinterpret_cast<const char*>(ptr + str.length()) );
}

std::basic_string<char32_t> fromWString(const std::wstring &str)
{
    std::wstring_convert<std::codecvt_utf16<char32_t>> conv;
    std::string tmp = conv.to_bytes(str);
    return std::u32string( reinterpret_cast<const char32_t*>(tmp.c_str()), tmp.length() * sizeof(char32_t) );
}

template<typename CharT>
std::basic_string<CharT> UpperCase(const std::basic_string<CharT> &str)
{
    std::wstring tmp = toWString(str);
    std::transform(tmp.begin(), tmp.end(), tmp.begin(), std::towlower);
    return fromWString(tmp);
}