0

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

卡特赖特温迪 93
威廉姆森马克 81
汤普森马克 100
安德森约翰 76
特纳丹尼斯 56

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

我想使用 strtok 将每个字符串的副本分解为列,并为每一行制作这样的结构:

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

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

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

编辑#2:共识似乎是使用全局变量作为列号,或者只使用 qsort 对结构数组进行排序。我没想过只是对结构进行排序,然后使用其中的指针打印出原始字符串。我想这就是我要做的。感谢大家的帮助!

4

4 回答 4

2

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

于 2009-09-19T19:34:25.363 回答
2

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

于 2009-09-19T19:36:41.083 回答
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);
于 2009-09-19T19:48:53.883 回答
1

C++ 还是 C?根据您的标签,我认为它是 C++。让我们尝试 STL 方式。

您应该使用std::sort而不是qsort. std::sort不仅可以采用函数指针(与其 C 替代方案相比),还可以采用任何可以作为函数调用的对象。你可能知道类实例可以作为函数调用operator()。然后解决方案很简单:创建一个“仿函数”类,该类将在构造时创建不同的函数。然后排序调用将如下所示:

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 指针比较“函数”(即您创建的类实例)具有char *参数,因此您不必为类型转换而烦恼。

不幸的是,在 C 语言中,除了创建全局变量之外,您无法做到这一点。

于 2009-09-19T19:46:37.057 回答