c - 在 qsort() 的比较函数中使用结构体中的值 - C99 - 取消引用指向不完整类型的指针

标签 c pointers struct c99 qsort

我对 C 相当陌生,正在努力正确使用 C stdlib qsort() 函数。

这与教育相关,因此,如果这很重要,我只能使用 C99 和标准库。

我有一个从 HashTable 中取出的项目列表,并将其放入 HashItem **array 中,但是当对其进行排序时,我正在使用比较函数,我无法从结构中获取正确的值。我环顾四周并看到了一些解决方案,但它们似乎都导致了

[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 中打印数组给出了正确的未排序的 word:occurrences 值

编辑:

感谢大家花时间提供帮助,现在在 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);
}

最佳答案

您构建声明:

    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() 或其他方法来分配要重新调整的数组。但我真正认为你需要做的是退后一步,创建一些数据结构的绘图,并考虑其中包含的各种对象的生命周期,以及如何跟踪和管理这些生命周期,这样就不会出现泄漏,双重释放,或指针取消引用不再有效的对象。

关于c - 在 qsort() 的比较函数中使用结构体中的值 - C99 - 取消引用指向不完整类型的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22854025/

相关文章:

c++ - 结构错误表达式必须有 bool 类型

c++ - 在 C++ 中,将 int 拆分为位的正确术语是什么

CMock - 多重定义

c - 永远不会达成 Else 子句

java - 处理与 JNI 的关联

c - 返回指针的函数

c - 为什么要通过if语句?

向函数调用 typedef 结构?

c - 如何允许在执行过程中读取空格?

c++ - 在类或结构中使用运算符?