【问题标题】:How to compare char's when char's contain emoji's?当char包含表情符号时如何比较char?
【发布时间】:2023-04-04 15:59:01
【问题描述】:

一般概述:

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

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

Emoji 字符总是被评估为 ...有趣...char 值,当使用如上所述的排序算法时,emoji 字符总是被排序在 之前 字母数字字符。

目标: 在纯字母数字字符串之前或之后对表情符号字符串或仅以表情符号开头的字符串进行排序是任意的。我希望能够控制按字母顺序排列表情符号字符/字符串的位置:在 '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 &gt; secondCharAsInt 就有意义了,因此函数返回true,并且表情符号字符串被排序到“Abc”字符串之前。同样,我希望能够将表情符号按字母数字字符排序——问题是,如何?

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

谢谢

【问题讨论】:

    标签: c++ string sorting


    【解决方案1】:

    回答我提出的方法:表情符号不是独一无二的,因为它们的“char as int”值为负数。

    其他符号(例如“§”)的计算结果也为负数,在本例中为 -62,因此排在字母数字字符之前。

    检查这些负值并以它们为目标以影响它们的排序顺序将有助于改变表情符号的排序顺序,但它也会改变其他无关字符的排序顺序 这使得这种方法无法完美地解决最初的目标。

    一个简单而干净的方法是将“char as int”值转换为unsigned ints。在二进制补码之后,负值将被转换为高正值,因此排在其他正值之后。

    【讨论】:

      【解决方案2】:

      表情符号是 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 &lt; s2

      Live demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多