【问题标题】:Sort a 2D character Array using sort() in C++在 C++ 中使用 sort() 对二维字符数组进行排序
【发布时间】:2015-10-22 06:20:43
【问题描述】:

我有一个二维字符数组(我不想使用 std::string 数组)。如何使用 std::sort() 根据字符串的长度对字符串 (char*) 进行升序排序?

我尝试了以下方法。但它不起作用。

char names[100][30];

bool comp(const char* a, const char* b){
    return strlen(a)<strlen(b);
}

int main(){
    ...
    //I want to sort the first n strings 
    sort(names,names+n,comp); //n<=100
    ...
}

我发现了这些错误:

1>e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3128) : error C2075: '_Val' : array initialization needs curly braces
1>        e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3150) : see reference to function template instantiation 'void std::_Insertion_sort1<_BidIt,bool(__cdecl *)(const char *,const char *),char[30]>(_BidIt,_BidIt,_Pr,_Ty (*))' being compiled
1>        with
1>        [
1>            _BidIt=char (*)[30],
1>            _Pr=bool (__cdecl *)(const char *,const char *),
1>            _Ty=char [30]
1>        ]
1>        e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3270) : see reference to function template instantiation 'void std::_Insertion_sort<_RanIt,bool(__cdecl *)(const char *,const char *)>(_BidIt,_BidIt,_Pr)' being compiled
1>        with
1>        [
1>            _RanIt=char (*)[30],
1>            _BidIt=char (*)[30],
1>            _Pr=bool (__cdecl *)(const char *,const char *)
1>        ]
1>        e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3279) : see reference to function template instantiation 'void std::_Sort<char(*)[30],int,bool(__cdecl *)(const char *,const char *)>(_RanIt,_RanIt,_Diff,_Pr)' being compiled
1>        with
1>        [
1>            _RanIt=char (*)[30],
1>            _Diff=int,
1>            _Pr=bool (__cdecl *)(const char *,const char *)
1>        ]
1>        e:\projects visual studio2008\sample\sample\sorting.cpp(51) : see reference to function template instantiation 'void std::sort<char(*)[30],bool(__cdecl *)(const char *,const char *)>(_RanIt,_RanIt,_Pr)' being compiled
1>        with
1>        [
1>            _RanIt=char (*)[30],
1>            _Pr=bool (__cdecl *)(const char *,const char *)
1>        ]
1>e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3133) : error C2106: '=' : left operand must be l-value
1>e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3140) : error C2106: '=' : left operand must be l-value
1>e:\program files (x86) in e\microsoft visual studio 9.0\vc\include\algorithm(3141) : error C2106: '=' : left operand must be l-value
1>Build log was saved at "file://e:\projects visual studio2008\sample\sample\Debug\BuildLog.htm"
1>sample - 4 error(s), 3 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

【问题讨论】:

  • 不起作用不是错误说明。也就是说,使用std::vectorstd::arraystd::string,就可以了。
  • @UlrichEckhardt 不幸的是,没有使用其中任何一个的等效二维数组。当然,人们总是可以用一个数组/向量/任何东西作为存储来编写一个二维数组类。
  • FRR:您甚至没有提到错误消息,更不用说提供一个最小的示例了。 @juanchopanza:这只是一个固定长度字符串的一维数组,如果我理解正确的话,因为这里的信息有限。
  • sort 将尝试使用 comp 的结果交换 abchar[30] 不能很好地工作。
  • names 的元素不是指针(char*),它们是数组(char[30])。 char* names[100] 会起作用。

标签: c++ arrays sorting


【解决方案1】:

如果您的数据在

char names[100][30];

那么您无法对“指针”进行排序,因为该数据结构根本没有指针……只有 100*30 = 3000 个字符一个接一个。 因此,要进行排序,您需要实际移动 100 行的所有内容。

std::sort 不能直接使用,因为数据结构是数组的数组,而数组是 C++ 二等公民(例如不能将数组分配给另一个数组)。

【讨论】:

    【解决方案2】:

    std::sort 要求它的迭代器类型参数必须是:

    • ValueSwappable 和 RandomAccessIterator。

    解引用的迭代器类型必须满足以下要求:

    • MoveAssignable 和 MoveConstructible。

    不幸的是,数组不可交换(即,您不能将一个分配给另一个)。因此,您不能将std::sort 与数组一起使用。

    您可以通过以下方式使用std::array&lt;std::array&lt;char, N&gt;, M&gt;

    template<std::size_t N, std::size_t M>
    void custom_sort(std::array<std::array<char, M>, N> &arrs) {
      std::sort(std::begin(arrs), std::end(arrs), [](auto const &a, auto const &b){ return strnlen(a.data(), M) < strnlen(b.data(), M); });
    }
    

    LIVE DEMO

    感谢@Jarod42对代码的改进

    【讨论】:

    • strnlen(a.data(), M) &lt; strnlen(b.data(), M) 以避免可能的越界访问。
    • 并且缺少参考以避免不必要的复制。
    • @Jarod42 谢谢我什至不知道strnlen :)
    【解决方案3】:

    如前所述,不能分配数组。可以分配结构,因此这可能接近您想要的。可以填充结构数组以进行对齐。在 Visual Studio 2015 的情况下,结构数组没有被填充,因此内存布局与二维数组相同。

    更新 - 按照 Jarod42 的建议,更改为使用比较参数的引用并切换到 strnlen。

    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    typedef struct
    {
        char name[30];
    }name;
    
    name names[4] = { { "12345678" },{ "123" },{ "12345" },{ "12" } };
    
    bool comp(const name &a, const name &b)
    {
        return strnlen(a.name,30) < strnlen(b.name,30);
    }
    
    int main(){
        sort(names, names+4, comp);
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      你可以试试这个:

      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      #define M 10000
      
      int main()
      {
          char names[M][15];
          int n, i;
          scanf("%d", &n);
          for (i = 0; i < n; i++)
              scanf("%s", names[i]);
          qsort(names, n, 15, (int (*)(const void *, const void *))strcmp);
      
          for(i = 0; i < n; i++)
              printf("%s\n", names[i]);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-09
        • 1970-01-01
        • 1970-01-01
        • 2011-02-17
        • 1970-01-01
        • 1970-01-01
        • 2021-08-16
        • 2014-08-10
        相关资源
        最近更新 更多