在c++中按非ascii顺序的首字母对字符串向量进行排序

Sorting a vector of strings by the first letter in non-ascii order in C++

本文关键字:字符串 向量 排序 c++ ascii 顺序      更新时间:2023-10-16

我有一个包含单词列表的文本文件。

我使用ifstream将这些单词读入vector,现在我正试图以类似的顺序对它们进行排序:

A a B b C c [...]

我尝试使用气泡搜索算法中的第三个for循环来实现这一点,以查看每个单词的第一个字符(我知道这远远不是最有效的方法,特别是如果我使用的是大型数据集)

然后检查该字母和下一个字母是大写还是小写,如果大写字母与当前字母相同,则切换,但这似乎不起作用。

void bubble_Sort (vector <string> & words)
{
  for (unsigned i = words.size(); i >= 2; --i)
  {
    for (unsigned k = 0; k + 1 < i; k++)
    {
      int hi = k+1;
      string temp1 = words[hi];
      string temp2 = words[k];
      int smallsize = words[hi].size();
      int smallprecedence = 0;
      if (words[k].size() < words[hi].size())
        smallsize = words[k].size();
      for (unsigned j = 0; j < smallsize; j++)
      {
        if (temp1[j] >= 'A' && temp1[j] <= 'Z')
        {
          if (temp2[j] >='a' && temp2[j] <= 'z')
          {
            char lowercase1 = temp1[j] + 32;
            if (lowercase1 == temp2[j])
            {
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            }
          }
          else if (temp2[j] >= 'A' && temp2[j] <= 'Z')
          {
            if (temp1[j] < temp2[j])
            {
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            }
          }
        }
        if (temp1[j] >= 'a' && temp1[j] <= 'z')
        {
          if (temp2[j] >= 'A' && temp2[j] <= 'Z')
          {
            char uppercase1 = temp1[j] - 32;
            if (uppercase1 < temp2[j])
            {
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            }
          }
          else if (temp2[j] >= 'a' && temp2[j] <= 'z')
          {
            if (temp1[j] < temp2[j])
            {
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            }
          }
        }
        else if (temp1[j] == temp2[j] && temp1.size() < temp2.size())
          ++smallprecedence;
      }
      if (smallprecedence == smallsize)
      {
        string temporary = words[k];
        words[k] = words[hi];
        words[hi] = temporary;
      }
    }
  }
}

别白费力气了。只需修改默认的比较函数aA <bB(不论情况)和A><一。>

我使用了错误的比较函数。它应该为<返回true,为>=返回false
std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{ 
   const char* s1=lhs.c_str();
   const char* s2=rhs.c_str();
   while(true) {
     // first ignore case
     if ( std::toupper(*s1) < std::toupper(*s2) ) return true;
     if ( std::toupper(*s1) > std::toupper(*s2) ) return false;
     // end of both strings, exact match
     if ( *s1 == 0 && *s2 == 0 ) return false;
     // compare upper case vs lower case ('A' vs 'a')
     if ( *s1 > *s2) return false;
     if ( *s1 < *s2) return true;
     ++s1; ++s2;
  }  
});

首先,去掉硬编码的ascii。很早以前,C和c++就有函数来确定一个字符是字母、数字、大写还是小写等等。查一下。

第二,清楚地描述是什么决定了你想要的结果的顺序。

第三,根据上述描述,编写一个函数,它接受两个字符串,并告诉您第一个字符串是否应该出现在第二个字符串之前。在排序中使用函数

您可以使用std::sort对矢量进行排序,并使用std::string::at():

获取对std::string中第一个字符的引用。
std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{ 
    char l_ch, r_ch;
    l_ch = lhs.at(0);
    r_ch = rhs.at(0);
    return l_ch < r_ch;
});

我认为跳过完全相等的前缀,然后用大写字母比较一次就足够了:

std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{ 
  const char* s1=lhs.c_str();
  const char* s2=rhs.c_str();
  while(*s1 && *s1 == *s2) {++s1; ++s2;}  
  int rc = toupper(*s1) - toupper(*s2);
  if (rc) return rc;
  return *s1 - *s2;
});

如果您只需要比较首字母,只需删除while(*s1 && *s1 == *s2) {++s1; ++s2;}