【问题标题】:Sorting a vector of strings by the first letter in non-ascii order in C++在C ++中按非ASCII顺序的第一个字母对字符串向量进行排序
【发布时间】:2016-10-11 06:32:50
【问题描述】:

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

我使用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;
      }
    }
  }
}

【问题讨论】:

  • 您是否正在实施自己的冒泡排序作为练习?如果没有,你应该使用std::sort并实现比较功能。
  • 是的,我正在尝试使用冒泡排序按 A a B b 等顺序对向量进行排序,即使在 ascii 中 a 大于 B,这是我一直遇到的问题有。

标签: c++ sorting vector ascii bubble-sort


【解决方案1】:

不要重新发明轮子。只需修改默认比较函数,使 aA

编辑我使用了错误的比较函数。对于&lt;,它应该返回true,对于&gt;=,它应该返回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;
  }  
});

【讨论】:

    【解决方案2】:

    首先,摆脱硬编码的 ASCII 主义。 C 和 C++ 早就有判断一个字符是字母、数字、大写还是小写等的函数了,查一下。

    其次,清楚地描述决定您希望结果的顺序的因素。

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

    【讨论】:

      【解决方案3】:

      您可以使用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;
      });
      

      【讨论】:

      • 在使用at()之前最好检查空字符串。
      • @FrerichRaabe:你说得对,只是提供了一个 sn-p,甚至没有测试代码。 std::compare 可以用于比较,但 OP 坚持第一个字母
      【解决方案4】:

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

      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 &amp;&amp; *s1 == *s2) {++s1; ++s2;}

      【讨论】:

        猜你喜欢
        • 2012-11-02
        • 1970-01-01
        • 2018-11-20
        • 1970-01-01
        • 1970-01-01
        • 2015-07-23
        • 2017-02-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多