Qsort of dynamically allocated array of dynamically allocated strings by string length 动态分配的字符串数组按字符串长度排序

Qsort of dynamically allocated array of dynamically allocated strings by string length

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

#define N 20

int compare(const void* a, const void* b) {
    return strlen((char*)a) - strlen((char*)b);
}

int main() {
    int i, n;
    scanf("%d", &n);
    char** strings = malloc(n*sizeof(char*));
    for(i=0; i<n;i++) {
        strings[i]=(char*)malloc(sizeof(char*));
        scanf("%s", strings[i]);
    }
    qsort(strings, n, sizeof(char*), compare);
    for(i=0; i<n;i++)
        printf("%s\n", strings[i]);
    for(i=0; i<n;i++)
        free(strings[i]);
    free(strings);
    return 0;
}

所以我尝试这样做,但它 returns 是一个未排序的数组,我不知道应该更改什么,有人知道该怎么做吗?


[更新 :]

忘了说了,应该是按字符串长度排序的

来自C11 Standard (draft) on the qsort() function(我强调):

The contents of the array are sorted into ascending order according to a comparison function pointed to by compar, which is called with two arguments that point to the objects being compared.

显示的代码想要比较 C-"strings",因此比较函数获得传递给 C-"strings" 的指针,即 char**(此处)。

您的代码将参数视为 char *

要修复此更改:

int compare(const void* a, const void* b) {
  return strlen((char*)a) - strlen((char*)b);
}

成为:

int compare(const void * pv1, const void * pv2) {
  char * ps1 = *(char **) pv1;
  char * ps2 = *(char **) pv2;

  return strlen(ps1) - strlen(ps2);
}

或者(避免转换)做:

int compare(const void * pv1, const void * pv2) {
  char ** ppc1 = pv1;
  char ** ppc2 = pv2;

  return strlen(*ppc1) - strlen(*ppc2);
}

注意:以上两个片段都默默地假定 strings 中没有元素是 NULL


另外,当分配给 char* 时,分配大小为 char* 点的块,即 *(char*),即 char.

所以改变这个:

   strings[i]=(char*)malloc(sizeof(char*));

成为:

   strings[i] = malloc(sizeof(char));

的甚至更好(因为 sizeof (char)1 的定义):

   strings[i] = malloc(1);

只剩下 1 char 的 "string",它只允许您存储空字符串 ("")。

你可能想要 N chars?

也是

   strings[i] = malloc(N + 1); /* 1+ for the 0-terminator. */

注意:在 C 中不需要强制转换 malloc() (& Friends) 的结果,也不推荐。


最后确保用户在输入过程中不会溢出目标变量。

所以你想改变这个

  scanf("%s", strings[i]);

成为

  scanf("%20s", strings[i]);