我正在使用我在网上找到的动态数组,其头文件如下所示:
typedef struct {
int size; // slots used so far
int capacity; // total available slots
void **data; // array of data we're storing
} Vector;
void vector_init(Vector *vector);
void vector_append(Vector *vector, void* value);
void* vector_get(Vector *vector, int index);
void vector_set(Vector *vector, int index, void* value);
void vector_double_capacity_if_full(Vector *vector);
void vector_free(Vector *vector);
我有另一个看起来像这样的结构:
typedef struct _item{
char name[MaxNameSize];
float price;
} Item;
我使用
创建了一个矢量Vector vector;
vector_init(&vector);
并使用
添加了许多项目vector_append(&vector, item);
项目属于Item的多次。我现在想按物品价格对动态数组进行排序。我试过这个没有用的
qsort(vector.data, vector.size, sizeof(Item*), compare);
我的比较功能是
int compare(const void* a, const void* b){
Item* first = (Item*)a;
Item* second = (Item*)b;
return first.price - second.price;
}
我出错的地方有什么想法吗?我想这可能是我在qsort中提出的论点。现在它似乎只是跳过了qsort。
答案 0 :(得分:3)
您对Vector
的声明包括数据床(void**
)指向空的指针。在没有看到其余代码的情况下,我必须假设这意味着您正在管理一个指针向量,其中每个指针引用一个不同的对象by-address。您在compare
中收到的地址是data
指针数组中的偏移地址。即实际类型void**
传递为void*
。
因此,您缺少一个间接级别。您的语法错误(例如:first->price
,而不是first.price
)无效,但即使这是正确的,您目前拥有的前提是Item*
传递为void*
是错误的。
你的比较器应该是这样的,假设你的其余代码是正确的:
int compare(const void* a, const void *b)
{
const Item * first = *(const void * const *)a;
const Item * second = *(const void * const *)b;
return first->price < second->price ? -1 : second->price < first->price;
}
同样,这是对你不提供的代码做出相当大的假设,并且除非该代码是可靠的并且满足上述假设,否则无法保证这将有效。但如果您正如上所述管理此向量,它应该可以工作。
我也自由地修正了比较本身。减去值似乎适用于整数类型,但是当转换为最终int
结果时,轮子会快速下降为浮点,如果引入下溢潜力,则轮子会快速下降。对于一个简单的例子:
#include <stdio.h>
int main()
{
printf("%d\n", (int)(1.1f - 1.0f)); // wrong
printf("%d\n", (1.1f < 1.0f ? -1 : 1.0f < 1.1f)); // better
return 0;
}
<强>输出强>
0
1
如果转换较大的整数类型值(假设您减去long long
且结果少而不是INT_MIN
,它也可能最终出现在实现定义的土地上)。坚持我展示的形式避免了陷阱
if (a < b) return -1;
return (b < a); // will be 1 or 0, depending on whether b < a or not.
因此,比较器总是返回-1,0或1,并且在执行此操作时符合qsort
的要求,并避免浮点到int
转换或潜在下溢/溢出的不准确。 / p>
祝你好运。
答案 1 :(得分:1)
编辑:正如WhozCraig指出的那样,数据是一个指针数组。因此:
第一个和第二个是指向指针的指针,因此您必须获得对Item的指针的引用,然后使用->
来引用结构的字段。总之,它应该看起来像:
Item* first = *(Item**)a;
Item* second = *(Item**)b;
return first->price - second->price;