如何qsort char **?

时间:2018-02-07 16:59:56

标签: c arrays string sorting pointers

我想对声明如下的字符串数组进行排序:

char** s;
s = calloc(4, sizeof(char *));
s[0] = "Banana";
s[1] = "Apple";
s[2] = "Grape";
s[3] = "Strawberry";

为此,我使用了qsort函数:

size_t len = sizeof(s) / sizeof(char *);
qsort(s, len, sizeof(char *), cmp);

cmp看起来像这样:

int cmp(const void* s1, const void* s2)
{
    const char** a = (const char**) s1;
    const char** b = (const char**) s2;
    return strcmp(*a, *b);
}

但是,对于此代码,没有任何内容被排序,输出的顺序与数组中的顺序相同。问题是,我用另一种方式检查了它,我将数组声明为(qsort和cmp保持不变):

char* s[] = {"Banana", "Apple", "Grape", "Strawberry"};

并且输出完美排序。我有点理解它是因为,第一个方法是double(指向指针)指针而第二个是指向数组的指针,但它们的工作原理是相同的。任何想法如何排序char **?先谢谢

3 个答案:

答案 0 :(得分:1)

此代码是正确的代码。char* s[] = {"Banana", "Apple", "Grape", "Strawberry"};是正确的,并且会按照您的预期行事。

要明确声明 - 您对sizeof的使用是有效的,并且不会成为问题。当用作sizeof的操作数时,数组不会在此处衰减

char **确实是正确的。每个元素的地址都传递给cmp函数。

故障是: -

如果char** s = calloc ...使用sizeof是错误的,因为它是一个包含已分配块的地址的指针。你无法知道分配给它的内存量。因此,当您使用char**s = calloc ..代码时,请指定数组的大小(不使用sizeof),这样就可以了。

有没有办法让len成为char**案例所需的大小?

是。您需要将其单独保存在变量中。您无法应用 sizeof 并从指针变量中获取已分配的内存大小。

如何使两者都有效?

如前所述,其他所有内容(比较器功能等)都是相同的,除非您现在必须跟踪分配的数量并将其传递给qsort。您已使用硬编码值4分配内存量。创建一个变量const int size = 4,然后保留它并相应地使用它。

长话短说 - 问题在于获得您想要排序的元素数量的大小。

答案 1 :(得分:1)

您遇到的问题是变量len。如果要通过malloc()calloc()等函数分配内存,最好使用变量来分配内存大小。所以不要写:

char** s;
s = calloc(4, sizeof(char *));

写:

size_t szAlloc = 4;
char **s = calloc(szAlloc, sizeof(char *));

这样,您可以跟踪分配的内存,并在需要时使用此值。由于变量s被声明为指针,因此在其上应用运算符sizeof()将产生该指针的大小,而不是calloc()分配的内存大小,并将其除以sizeof(char *)会给1作为结果。

使用变量szAlloc,您可以将qsort()称为:

qsort(s, szAlloc, sizeof(char *), cmp);

这应该给出正确的结果。

答案 2 :(得分:0)

在第一种情况下,由于s是一个指针,sizeof(s)会给你指针的大小,而不是它所指向的。这当然导致len等于1(指针的大小除以指针的大小)。

在第二种情况下,s不再是指针,而是四个元素的数组。它的类型是char*[4]

你只能使用sizeof-division"技巧"与实际数组。

如果你想使用指针并动态分配"数组"你需要自己跟踪元素的数量。