当字符包含表情符号时如何比较字符?



概述:

我有一个名字列表,每个名字都是一个string&.想要对字符串列表执行的常见操作是按字母顺序对字符串进行排序。

一种方法是将两个字符串转换为相同的大小写,从每个字符串中的第一个字符开始,并计算字符以查看字母表中哪个if (char1 > char2)行排在第一位,重复直到被比较的两个字符不相等或直到到达较短字符串中的最后一个字符。

表情符号字符总是评估为...有意思...char值,当使用上述排序算法时,表情符号字符始终排序为字母数字字符之前

目标:在纯字母数字字符串之前或之后对表情符号字符串或仅以表情符号开头的字符串进行排序是任意的。 我希望能够控制表情符号字符/字符串的字母顺序排序:选择在"Z"/"z"之后"A"/"a"之前。

(我并不是说我想控制它们的排序位置,将它们放置在其他任意字符(如"p"和"q")之间,我也不是说我的目标是控制表情符号与其他表情符号相比的排序方式,只是为了清楚起见。

一些代码来演示:

bool compareStringsIgnoreCase(std::string& str1, std::string& str2)
{
int i = 0;
while (i < str1.length() && i < str2.length())
{
char firstChar = tolower(first[i]);
char secondChar = tolower(second[i]);
int firstCharAsInt = firstChar;
int secondCharAsInt = secondChar;
if (firstCharAsInt < secondCharAsInt)
return true;
else if (firstCharAsInt > secondCharAsInt)
return false;
i++;
}
return (str1.length() < str2.length());
}

如果使用str1 = "Abc"str2 = 👍,那么当i = 0,其他值如下:firstChar = 'a'

secondChar = 'xf0'

firstCharAsInt = 97

secondCharAsInt = -16

有了这些值,firstCharAsInt > secondCharAsInt是有意义的,因此函数返回true,并且表情符号字符串被排序为在"Abc"字符串之前。同样,我希望能够做的是将表情符号排序在字母数字字符之后 - 问题是,如何?

我尝试了一些表情符号,它们的"char as int"值总是负数。表情符号与其他char不同吗?如果是这样,这可能是一个简单易行的检查,可以识别它们以将它们放在其他字符之后。也对其他方法持开放态度。

谢谢

表情符号是Unicode字符,因此假设您的字符串被编码为UTF-8,那么比较它们的最简单方法是将它们转换为std::wstring。 您可以使用std::codecvt. 尽管这在 C++17 中已弃用,但目前没有方便的替代品。

因此,可以执行以下操作:

#include <string>
#include <codecvt>
#include <locale>
#include <cctype>
std::wstring widen (const std::string &s)
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>, wchar_t> convert;
return convert.from_bytes (s);
}
void lower_case_string (std::wstring &ws)
{
for (auto &ch : ws)
ch = tolower (ch);
}
// Return true if s1 == s2 (UTF-8, case insensitive)
bool compare (const std::string &s1, const std::string &s2)
{
std::wstring ws1 = widen (s1);
lower_case_string (ws1);
std::wstring ws2 = widen (s2);
lower_case_string (ws2);
return ws1 == ws2;
}

尽管请注意,用于排序的比较功能将是s1 < s2

现场演示

回答我提出的方法:表情符号并不是唯一的,因为它们的"char as int"值是负的。

其他符号,例如"§",也计算为负数,在本例中为 -62,因此在字母数字字符之前排序。

检查这些负值并针对它们以影响其排序顺序将改变表情符号的排序顺序,但它也会改变其他无关字符的排序顺序,这使得这种方法成为原始目标的不完美解决方案。

一种简单而干净的方法是将"char as int"值转换为unsigned ints。负值将在 2 的补码之后转换为高正值,从而在其他正值之后排序。