我想对声明如下的字符串数组进行排序:
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 **?先谢谢
答案 0 :(得分:1)
此代码是正确的代码。char* s[] = {"Banana", "Apple", "Grape", "Strawberry"};
是正确的,并且会按照您的预期行事。
要明确声明 - 您对sizeof
的使用是有效的,并且不会成为问题。当用作sizeof
的操作数时,数组不会在此处衰减。
char **
确实是正确的。每个元素的地址都传递给cmp
函数。
故障是: -
如果char** s = calloc ...
使用sizeof
是错误的,因为它是一个包含已分配块的地址的指针。你无法知道分配给它的内存量。因此,当您使用char**s = calloc ..
代码时,请指定数组的大小(不使用sizeof
),这样就可以了。
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"技巧"与实际数组。
如果你想使用指针并动态分配"数组"你需要自己跟踪元素的数量。