在 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
快得多(两到三倍快速是相当普遍的)。
我正在尝试从 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
快得多(两到三倍快速是相当普遍的)。