我正在创建一个将字符更改为大写/小写的函数。但是,我使用模板来允许使用任何字符类型(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;
}
答案 0 :(得分:3)
std::islower()
和std::tolower()
对当前语言环境中表达的char
数据进行操作。还有std::iswlower()
和std::towlower()
函数可用于wchar_t
数据(请注意,它们不支持UTF-16代理)。
您必须将输入字符串转换为wchar_t
或本地化char
,根据需要进行小写比较/转换,然后在完成后将结果转换回原始编码。
请记住:
与本地化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);
}