在 C++ 中对对象数组进行排序

Sorting an array of objects in C++

我正在尝试从 class 中创建一个按字母顺序排序的对象数组,其中还包含另一个 int 变量,但我无法使工作 qsort 正常运行。 这是我的代码:

#include <iostream>
#include <stdlib.h>
#include <string.h>

int cmp (char **str1 , char **str2 )
{
  return strcmp(*str1,*str2);
}

class myclass
{
 int id;
 char text[50];
 public: 
  void add(char a[], int i) { strcpy(text,a); id=i; }
  void show(void) { std::cout<<text<<std::endl; }
};


int main (void)
{
  myclass * myobject[4];
  myobject[0] = new myclass;
  myobject[1] = new myclass;
  myobject[2] = new myclass;
  myobject[3] = new myclass;
  myobject[0]->add("zoom",1);
  myobject[1]->add("zoo",2);
  myobject[2]->add("animal",3);
  myobject[3]->add("bull",4);

  qsort (myobject,4,sizeof(char *), (int (*)(const void *, const void *)) cmp);

  for (int i=0; i < 4; i++) 
    myobject[i]->show();

  return 0;
}

你的比较函数有误。它接收一个指向每个数组元素的指针,它是指向 myclass 的指针,而不是 text。你也不应该在调用 qsort 时转换函数指针,你应该转换参数在比较函数中。

int cmp (void *a, void *b) {
    myclass **c1 = (myclass **)a;
    myclass **c2 = (myclass **)b;
    return strcmp((*c1)->text, (*c2)->text);
}

首先,你的比较函数需要能够访问myclass的私有成员text

您可以创建 文本 public 或添加

friend int cmp (const void *, const void*);

在 class 定义中。

其次,你的比较功能是错误的。它需要指向要排序的数组成员的指针。你应该这样写:

int cmp (const void *ptr1 , const void *ptr2)
{
    myclass *m1 = *(myclass**)ptr1;
    myclass *m2 = *(myclass**)ptr2;

    return strcmp(m1->text, m2->text);
}

现在,您的代码看起来像是 C 代码的变形版本,其中的 C++ "sprinkled" 足以阻止它与 C 编译器一起工作。至少在 IMO 中,这几乎是两个世界中最糟糕的部分——它删除了 C 的大部分最佳功能和 C++ 的最佳功能。如果你打算写 C++,就写 C++,而不是扭曲的 C。

要在 C++ 中创建和排序对象集合,您可能应该更像这样编写代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

class myclass
{
    int id;
    std::string text;
public:
    myclass(std::string const &a, int i) : id(i), text(a) {}

    bool operator<(myclass const &other) {
        return text < other.text;
    }

    friend std::ostream &operator << (std::ostream &os, myclass const &m) {
        return std::cout << m.text << "\n";
    }
};


int main()
{
    std::vector<myclass> myobjects{
        { "zoom", 1 },
        { "zoo", 2 },
        { "animal", 3 },
        { "bull", 4 }
    };

    std::sort(myobjects.begin(), myobjects.end());

    for (auto const &o : myobjects)
        std::cout << o;
}

至少在我看来,这样比较简单易懂。它不会泄漏内存。如果(例如)我们将另一个项目添加到项目集合中,我们就不必重写其他代码来适应它。

可能比以上任何一项都更重要,至少对我而言,这会导致更快、更容易、更无错误的开发。例如,上面的代码在第一次编译时没有错误(工作正常)。除了修复几个明显的拼写错误(例如,我将 operator 误输入为 opertor)之外,它的编译和 运行 与我最初输入的完全一样。作为一个小小的奖励,它可能比类 C 版本运行得更快。只有 4 个项目,速度上的差异不会很明显,但如果你有(例如)数千个项目,std::sort 几乎肯定会比 qsort 快得多(两到三倍快速是相当普遍的)。