使用 stdlib 的 qsort() 对字符串数组进行排序

Posted

技术标签:

【中文标题】使用 stdlib 的 qsort() 对字符串数组进行排序【英文标题】:Using stdlib's qsort() to sort an array of strings 【发布时间】:2011-07-19 06:00:48 【问题描述】:

一些前言:我是一名计算机工程专业的学生,​​在学习了 3 个学期的 Java(直至数据结构)后,我正在上 C 的第一堂课。这个问题与家庭作业有关,但离我解决它还有几个步骤。

我有一个读入内存的输入文件,它存储在 char[9][500] 中。我最多读入 500 个最大长度为 8 的字符串。我正在尝试使用 stdlib 内置的 qsort() 函数对该数组进行排序,但出现了一些内存错误。

重要的sn-ps代码:

char data[4][500][60];
char debug[500][9];
size_t count = 0;

/* initialize file, open for reading */
FILE* pUserlog;
pUserlog = fopen("userlog","r");

while(!feof(pUserlog))

    fscanf(pUserlog, "%9s %8s %16s",debug[count], data[1][count], data[2][count]);
    fgets(data[3][count], 60, pUserlog);
    count++;

本节将数据读入数组。这部分感兴趣的数组是“调试”。这是上面指定的数组。这是我对 qsort 的比较函数:

int compare(const void* a, const void* b)

    const char **ia = (const char **)a;
    const char **ib = (const char **)b;
    puts("I'm in compare!");
    return strncmp(*ia, *ib,8);

这是我尝试调用 qsort:

size_t debug_len = sizeof(debug)/sizeof(char*);
printf("debug len: %d, count: %d, sizeof(char*): %d\n",debug_len,count,sizeof(char*));
qsort(debug,count, sizeof(char *), compare);

我尝试在 count 所在的调用中替换 debug_len,但仍然存在段错误。这是输出:

$ ./测试 调试长度:1125,计数:453,sizeof(char*):4 我在比较! 分段错误(核心转储)

谢谢!

【问题讨论】:

while( !feof() ) 是错误的。 feof 将返回 false,进入循环,scanf 将无法读取数据,debug[count] 将包含虚假数据,然后 feof 将返回 true。您可以通过在循环之后执行 count-- 来解决这种情况,但一般来说,您不应该简单地执行 while(!feof()) 段错误在哪里?检查核心转储以确定段错误发生的位置是一个很好的练习,因为这通常可以告诉您问题所在。 【参考方案1】:

这里发生的是:你有 500 个字符串。现在您将所有 500 个传递给 qsort,然后它依次将每个作为第一个和第二个参数传递给您的比较函数。有点像这样写:

compare(debug[0], debug[1])

C 编译器传递地址,当然不是实际值。但是现在您将指向 void 的指针解释为指向字符的指针。现在,您的代码在调用 strncmp 时会取消引用,但这会使 (前 4 个字节)被视为 strncmp 中的指针。但是strncmp 现在将反过来尝试取消引用垃圾“指针”(它由您的一个字符串的一部分组成),这使得 bang

要解决此问题,请使用 char * 而不是 char **

int compare(const void* a, const void* b)

    puts("I'm in compare!");
    return strncmp((const char *)a, (const char *)b, 8);

【讨论】:

【参考方案2】:

比较函数将接收指向被比较元素的指针。您正在有效地尝试使用strncmp() 比较字符。由于您有指向每个字符串的指针,因此将其转换为 char * 并进行比较。

int compare(const void* a, const void* b)

    const char *ia = (const char *)a;
    const char *ib = (const char *)b;
    puts("I'm in compare!");
    return strncmp(ia, ib, 9);

还要记住,它是一个数组数组,而不是一个指针数组。所以元素的大小应该是数组的大小,9,而不是指针的大小,4。此时,使用sizeof debug[0] 会更容易,因为它是一个二维数组。如果您没有使用正确的大小来执行此操作,qsort() 只会破坏您的数组。

size_t elemsize = sizeof debug[0];      /*   9 - size of each element */
size_t count = sizeof(debug)/elemsize;  /* 500 - number of elements in array */
qsort(debug, count, elemsize, compare);

【讨论】:

以上是关于使用 stdlib 的 qsort() 对字符串数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

使用 qSort 对字符串进行排序

如何在c中使用qsort比较C++字符串?

使用 qsort() 对指向包含字符串的结构的指针进行排序

C语言之qsort函数进行排序

C语言中利用qsort函数对字符串数组按ASC码进行排序并输出、

为啥 stdlib 中的 qsort 不适用于双精度值? [C]