我对c很新,并且正在努力正确使用C stdlib qsort()函数。
这与教育有关,因此我只允许使用C99和标准库,如果这很重要的话。
我有一个从HashTable中获取并放入HashItem **数组的项目列表,但是在排序时我正在努力使用compare函数,我无法从结构中获取正确的值。我环顾四周,看到了一些解决方案,但它们似乎都导致了
[Error] dereferencing pointer to incomplete type
这是结构:
typedef struct {
char *word;
int occurences;
} HashItem;
我有兴趣根据出现的值进行比较和排序。
以下是调用qsort的代码:
int n = array->number_of_values;
HashItem **standard_array = array_getarray(array);
qsort(standard_array, n, sizeof(HashItem*), compare_func);
以下是比较功能:
int compare_func(const void *a, const void *b){
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if(val_1 == val_2){
return 0;
}else if(val_1 > val_2){
return 1;
}else{
return -1;
}
}
对不起格式化,我是新来的问题。
我希望你能帮助你。
数组代码:
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
/*Method to create a new dynamic array and return it */
DynArray* array_new(int file_size){
DynArray *array = malloc(sizeof(DynArray));
array->number_of_values = 0;
array->capacity = file_size / 10;
printf("capacity is %d " , array->capacity);
array->items = malloc(sizeof(HashItem*)* array->capacity);
}
/*Method used to increase the size of the array and reallocate memory*/
void array_increase_if_full(DynArray *array){
if (array->number_of_values >= array->capacity){
array->capacity *= 1.25;
array->items = realloc(array->items, sizeof(HashItem)*array->capacity);
}
}
/*Method to add a string to the dynamic array specified */
void array_append(DynArray *array, HashItem *item){
array_increase_if_full(array);
array->items[array->number_of_values] = item;
//printf("item %s added \n at position %d ", array->items[array->number_of_values]->word, array->number_of_values);
array->number_of_values++;
}
/*Method used to get value at specified position for given array*/
HashItem *array_get(DynArray *array, int position){
if(position >= array->number_of_values || position <0){
printf("Index specified out of range");
exit(1);
}
//printf("item %s at position %d retrieved", array->items[position]->word, position);
return array->items[position];
}
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
从main打印数组会给出正确的未排序值:occurences
编辑:
感谢所有花时间提供帮助的人,现在它处于Michaels建议的工作状态,我不再使用array_getarray()方法而是使用:
int n = array->number_of_values;
int i;
HashItem **standard_array = malloc(n*sizeof(HashItem*));
for(i = 0; i < n; i++){
standard_array[i] = array_get(array, i);
printf("%s : %d \n" , standard_array[i]->word, standard_array[i]->occurences);
}
答案 0 :(得分:1)
您构建声明:
typedef struct {
char *word;
int occurences;
} HashItem;
声明匿名结构的typedef名称。 HashItem
类型是结构,但没有struct HashItem
类型。
因此,当您的compare_func()
具有以下声明时:
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
那些struct HashItem*
变量是指向前面声明的struct HashItem
的指针,它与上面的HashItem结构没有关系。
只需将这些变量声明更改为:
const HashItem* aa = (HashItem*)a;
const HashItem* bb = (HashItem*)b;
和/或将结构声明更改为:
typedef struct HashItem {
char *word;
int occurences;
} HashItem;
然而,还有另一个问题(正如其他答案中所提到的):您显然正在排序指向HashItem
个对象的指针数组,但您的compare_function()
正在编写,就像您正在对数组进行排序一样对象(不是指针)。
解决这个问题:
int compare_func(const void *a, const void *b)
{
// get HashItem*'s from the HashItem**'s
const HashItem* aa = *((HashItem**)a);
const HashItem* bb = *((HashItem**)b);
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if (val_1 == val_2) {
return 0;
} else if (val_1 > val_2) {
return 1;
} else {
return -1;
}
}
最后(现在无论如何),此函数将地址返回到本地数组,因此它指向的数据不再有效:
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
我认为您需要使用malloc()
或calloc()
或其他内容分配您正在重新调整的数组。但我真正认为你需要做的是退后一步,创建一些数据结构图,并考虑它们中包含的各种对象的生命周期,以及如何跟踪这些生命周期,以便你没有泄漏,双重释放,或指针解引用不再有效的对象。
答案 1 :(得分:0)
现在我认为你的问题都是从第一个定义中产生的。
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
我认为items
没有理由成为双指针。注释说它应该包含值,但是指向数组的双指针将包含指针,而不是最终值。我认为这个最初的失误导致你到处去其他地方。将其更改为
...
HashItem *items;
...
,其余的应该更自然地流动。
答案 2 :(得分:0)
将qsort(standard_array, n, sizeof(HashItem), compare_func);
更改为
qsort(standard_array, n, sizeof(HashItem*), compare_func);
在函数void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
第三个参数size_t size
代表:
数组中每个元素的字节大小。