Qsort基于c-string中的列?

时间:2009-09-19 19:27:11

标签: c++ c qsort

类项目涉及对字符串数组进行排序,每个字符串包含相同数量的列,如下所示:

Cartwright   Wendy    93
Williamson   Mark     81
Thompson     Mark     100
Anderson     John     76
Turner       Dennis   56

程序接受一个命令行参数,要对哪个列进行排序,并且应该打印出未修改的已排序字符串。

我想使用strtok将每个字符串的副本分解为列,并为每一行创建结构,如下所示:

struct line {
    char * line;
    char column_to_sort_on[MAX_COLUMN];
}

我的问题出在qsort作为arg的比较函数指针中。如果我理解正确,比较函数必须将两个const void指针带到要排序的项,并返回一个int。这意味着我无法将指向结构的指针传递给比较函数,因为这不是qsort将要排序的内容。我无法传入列号来排序比较函数,因为它只能取两个参数。如何根据特定列对这些字符串进行排序?

编辑:如果我真的想要,排序仅限于qsort或我自己。给出选择,我选择qsort。 :)

编辑#2:协商一致似乎要么使用列号的全局变量,要么只使用qsort对结构数组进行排序。我没有想过只是对结构进行排序,并使用其中的指针打印出原始字符串。我想这就是我要做的。感谢大家的帮助!

4 个答案:

答案 0 :(得分:2)

假设您不限于使用qsort,您可以使用std :: sort,以及存储列号的functor对象。如果你必须使用qsort,一个快速而肮脏的解决方案是将列号存储在一个全局变量中,并在comparisson函数中使用它。

答案 1 :(得分:2)

不同的比较器函数,所有这些函数都采用整个结构,但每个函数只使用一列进行比较。

答案 2 :(得分:2)

您可以传递这样的结构:

struct line {
    char * line;
    char column_to_sort_on[MAX_COLUMN];
}
...

line*  Lines[max_lines]; // here you store the structs

int
cmp_lines( const void *elem1, const void *elem2 )
{
    line*  line1 = *(line**)elem1;
    line*  line2 = *(line**)elem2;
    // do the comparisons
}

qsort(Lines, max_lines, sizeof(line*), cmp_lines);

答案 3 :(得分:1)

C ++或C?根据你的标签,我认为它是C ++。我们试试STL吧。

您应该使用std::sort代替qsortstd::sort不仅可以使用函数指针(与其C替代),还可以使用任何可以作为函数调用的对象。您可能知道可以使用operator()将类实例称为函数。然后解决方案很简单:创建一个“functor”类,它将在构造时创建不同的功能。然后排序调用看起来像这样:

std::sort(array, array+size, comparator(2 /* sort by column #2 */));

仿函数类有效地创建了一个所谓的“闭包”:一个动态创建的功能对象,它具有局部变量,但不与这种方式创建的其他功能对象共享。它看起来像这样:

class comparator{
  private: unsigned int field_n;
  public: comparator(unsigned int _field_n) : field_n(_field_n) {};
  public: int operator () (char const *  lhs, char const * rhs)
       { /* compare here fields with index field_n */ };
};

请注意,代替void指针比较“function”(即您创建的类实例)具有char *个参数,因此您不必为类型转换而烦恼。

在C中,遗憾的是,除了创建全局变量之外,你不能这样做。