如何使用 qsort 对结构进行排序
How to sort struct using qsort
我正在尝试使用 qsort 对包含指针的结构进行排序。是比较功能的问题吗?我该如何修复才能根据 cc 进行排序。
代码如下:
#include <stdlib.h>
#include <string.h>
typedef enum {
PETROL,
DIESEL,
ELECTRIC,
LPG,
BIOFUEL,
OTHER
} fuel_t;
typedef struct car_tag {
unsigned cc;
fuel_t fueltype;
} car_t;
typedef struct fleet_tag {
car_t ** cars;
size_t n_cars;
} fleet_t;
int car_comp(const void * vp1, const void * vp2) {
const car_t* const c1 = vp1;
const car_t* const c2 = vp2;
if (c1->cc > c2->cc)
return -1;
else if (c1->cc < c2->cc)
return 1;
else {
return 0;
}
}
int main() {
car_t array[] = {
{ 600, PETROL},
{1200, PETROL},
{1000, PETROL},
{1600, DIESEL},
{1000, ELECTRIC}
};
int size = sizeof(array) / sizeof(array[0]);
fleet_t fl;
fl.n_cars = size;
fl.cars = malloc(size * sizeof(car_t));
for (int i = 0; i < size; i++) {
car_t* pc = malloc(sizeof(car_t));
memcpy(pc, &array[i], sizeof(car_t));
fl.cars[i] = pc;
}
// how to sort cars by cc
qsort(&fl, fl.n_cars, sizeof(car_t), car_comp);
// sort function doesn't correctly sort fleet of cars by cc
}
我认为这段代码中的每辆待分类汽车都不需要动态分配和 memcpy 调用。
您正在构建一个指针床(一系列指针),那么为什么不分配它(您正在做的),然后将 array
中每个元素的地址存储在那里。然后,定制您的比较器以解决您发送的内容:指针的地址(指向指针的指针)并相应地设置取消引用
除此之外,您应该将 fl.cars
传递给 qsort,而不是 &fl
,其中的 sizeof 参数也是错误的。
最后,我不知道您是否有意在比较器中使用大于逻辑堆栈,但这正是您最终得到的结果。
例子
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
PETROL,
DIESEL,
ELECTRIC,
LPG,
BIOFUEL,
OTHER
} fuel_t;
typedef struct car_tag {
unsigned cc;
fuel_t fueltype;
} car_t;
typedef struct fleet_tag {
car_t ** cars;
size_t n_cars;
} fleet_t;
int car_comp(const void * vp1, const void * vp2)
{
const car_t * const *pc1 = vp1;
const car_t * const *pc2 = vp2;
if ((*pc1)->cc > (*pc2)->cc)
return -1;
if ((*pc1)->cc < (*pc2)->cc)
return 1;
return 0;
}
int main() {
car_t array[] = {
{ 600, PETROL},
{1200, PETROL},
{1000, PETROL},
{1600, DIESEL},
{1000, ELECTRIC}
};
int size = sizeof(array) / sizeof(array[0]);
fleet_t fl;
fl.n_cars = size;
fl.cars = malloc(size * sizeof *fl.cars);
for (int i = 0; i < size; i++)
fl.cars[i] = array+i;
// how to sort cars by cc
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
for (int i=0; i<size; ++i)
printf("%d (%u, %d)\n", i+1, fl.cars[i]->cc, fl.cars[i]->fueltype);
free(fl.cars);
return EXIT_SUCCESS;
}
输出
1 (1600, 1)
2 (1200, 0)
3 (1000, 0)
4 (1000, 2)
5 (600, 0)
qsort
的工作原理是给它提供一个 "things" 的序列,一个长度表示有多少 "things",一个大小表示每个 "thing" [=41] =]在序列中,最后是一个比较器函数,它将在算法执行期间提供每个"thing"的地址。
在你的例子中,你的 "things" 是指向 car_t
结构的指针。事实上,
- 你的序列是一个动态指针数组;您的 "thing" 是指向
car_t
. 的指针
- 你的长度是
size
.
- 你每个"thing"的大小是一个指针的大小。
- 你的比较器将访问你的两个东西的地址(因此,两个指针,所以指针指向指针),并采取行动因此。
因此调用变为:
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
最后注意,原来的array
保持不变。这种类型只改变了你的指针床。这可能是可取的,我希望你能理解它是如何工作的。
我正在尝试使用 qsort 对包含指针的结构进行排序。是比较功能的问题吗?我该如何修复才能根据 cc 进行排序。
代码如下:
#include <stdlib.h>
#include <string.h>
typedef enum {
PETROL,
DIESEL,
ELECTRIC,
LPG,
BIOFUEL,
OTHER
} fuel_t;
typedef struct car_tag {
unsigned cc;
fuel_t fueltype;
} car_t;
typedef struct fleet_tag {
car_t ** cars;
size_t n_cars;
} fleet_t;
int car_comp(const void * vp1, const void * vp2) {
const car_t* const c1 = vp1;
const car_t* const c2 = vp2;
if (c1->cc > c2->cc)
return -1;
else if (c1->cc < c2->cc)
return 1;
else {
return 0;
}
}
int main() {
car_t array[] = {
{ 600, PETROL},
{1200, PETROL},
{1000, PETROL},
{1600, DIESEL},
{1000, ELECTRIC}
};
int size = sizeof(array) / sizeof(array[0]);
fleet_t fl;
fl.n_cars = size;
fl.cars = malloc(size * sizeof(car_t));
for (int i = 0; i < size; i++) {
car_t* pc = malloc(sizeof(car_t));
memcpy(pc, &array[i], sizeof(car_t));
fl.cars[i] = pc;
}
// how to sort cars by cc
qsort(&fl, fl.n_cars, sizeof(car_t), car_comp);
// sort function doesn't correctly sort fleet of cars by cc
}
我认为这段代码中的每辆待分类汽车都不需要动态分配和 memcpy 调用。
您正在构建一个指针床(一系列指针),那么为什么不分配它(您正在做的),然后将 array
中每个元素的地址存储在那里。然后,定制您的比较器以解决您发送的内容:指针的地址(指向指针的指针)并相应地设置取消引用
除此之外,您应该将 fl.cars
传递给 qsort,而不是 &fl
,其中的 sizeof 参数也是错误的。
最后,我不知道您是否有意在比较器中使用大于逻辑堆栈,但这正是您最终得到的结果。
例子
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
PETROL,
DIESEL,
ELECTRIC,
LPG,
BIOFUEL,
OTHER
} fuel_t;
typedef struct car_tag {
unsigned cc;
fuel_t fueltype;
} car_t;
typedef struct fleet_tag {
car_t ** cars;
size_t n_cars;
} fleet_t;
int car_comp(const void * vp1, const void * vp2)
{
const car_t * const *pc1 = vp1;
const car_t * const *pc2 = vp2;
if ((*pc1)->cc > (*pc2)->cc)
return -1;
if ((*pc1)->cc < (*pc2)->cc)
return 1;
return 0;
}
int main() {
car_t array[] = {
{ 600, PETROL},
{1200, PETROL},
{1000, PETROL},
{1600, DIESEL},
{1000, ELECTRIC}
};
int size = sizeof(array) / sizeof(array[0]);
fleet_t fl;
fl.n_cars = size;
fl.cars = malloc(size * sizeof *fl.cars);
for (int i = 0; i < size; i++)
fl.cars[i] = array+i;
// how to sort cars by cc
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
for (int i=0; i<size; ++i)
printf("%d (%u, %d)\n", i+1, fl.cars[i]->cc, fl.cars[i]->fueltype);
free(fl.cars);
return EXIT_SUCCESS;
}
输出
1 (1600, 1)
2 (1200, 0)
3 (1000, 0)
4 (1000, 2)
5 (600, 0)
qsort
的工作原理是给它提供一个 "things" 的序列,一个长度表示有多少 "things",一个大小表示每个 "thing" [=41] =]在序列中,最后是一个比较器函数,它将在算法执行期间提供每个"thing"的地址。
在你的例子中,你的 "things" 是指向 car_t
结构的指针。事实上,
- 你的序列是一个动态指针数组;您的 "thing" 是指向
car_t
. 的指针
- 你的长度是
size
. - 你每个"thing"的大小是一个指针的大小。
- 你的比较器将访问你的两个东西的地址(因此,两个指针,所以指针指向指针),并采取行动因此。
因此调用变为:
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
最后注意,原来的array
保持不变。这种类型只改变了你的指针床。这可能是可取的,我希望你能理解它是如何工作的。