我想按特定字段的值对结构进行排序。字段中的数据类型相同。在c ++中,我使用了指向成员的指针,以避免针对不同的字段重写相同的排序。
#include<string.h>
typedef struct {
int id;
int year;
int price;
} example_struct;
void sort_arr(example_struct a[5], const char* usr_field) {
int example_struct::*field = nullptr;
if (strcmp(usr_field, "id") == 0)
field = &example_struct::id;
else if (strcmp(usr_field, "year") == 0)
field = &example_struct::year;
else if (strcmp(usr_field, "price") == 0)
field = &example_struct::price;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5 - i; j++) {
if (a[j].*field > a[j + 1].*field) {
buff = a[j];
a[j] = a[j+1];
a[j+1] = buff;
}
}
}
}
int main {
example_struct a[5];
fill_arr(a); //somehow filling the array
sort_arr(a,"year");
}
我想知道此代码是否可以在C上以某种方式仿真以及如何执行
答案 0 :(得分:1)
您应该能够使用offsetof
宏来获取要比较的成员的偏移量,然后使用指针算法来获取该成员的值。请注意,您将不会获得该成员的任何类型信息,而只会获得结构体中的偏移量,因此,您需要确保自己知道成员字段的大小。
因此,您可以进行比较:
void sort_arr(example_struct a[5], const char* usr_field) {
size_t offset;
if (strcmp(usr_field, "id") == 0)
offset = offsetof(example_struct, id);
else if (strcmp(usr_field, "year") == 0)
offset = offsetof(example_struct, year);
else if (strcmp(usr_field, "price") == 0)
offset = offsetof(example_struct, price);
...
if (*((int*)((char*)&a[j])+offset) > *((int*)((char*)&a[j+1])+offset)) {
...
定义一些宏可能有助于使成员访问更加愉快。
#define memberat(ref, offset, membertype) *((membertype*)((char*)ref)+(size_t)offset)
if (memberat(&a[j], offset, int) > memberat(&a[j+1], offset, int))
如果要处理不同类型的成员,则必须使用函数指针来处理比较,因为比较的方式将有所不同。
答案 1 :(得分:0)
marco offsetof
是答案,但是这种排序方式太难了,而且不是特别安全的类型(如果更改类型,则可能不会收到错误甚至警告)。是要排序的典型C代码;一个具有一个函数,该函数从每个int
值中选择一个struct
中想要的int
,然后比较qsort
。
#include <stdlib.h> /* EXIT_* qsort rand */
#include <stdio.h> /* printf */
#include <string.h> /* strcmp */
#include <assert.h> /* assert */
struct ExampleStruct { int id, year, price; };
static void fill(struct ExampleStruct *const a) {
assert(a);
/* <http://c-faq.com/lib/randrange.html> */
a->id = rand() / (RAND_MAX / 99998 + 1) + 1;
a->year = rand() / (RAND_MAX / 119 + 1) + 1900;
a->price = rand() / (RAND_MAX / 999999 + 1) + 1;
}
static void print(struct ExampleStruct *const a) {
assert(a);
printf("%05d\t%d\t$%d\n", a->id, a->year, a->price);
}
static void for_each(struct ExampleStruct *const a, const size_t a_size,
void (*const action)(struct ExampleStruct *const)) {
size_t i;
assert(a && action);
for(i = 0; i < a_size; i++) action(&a[i]);
}
static int cmp_int(const int a, const int b) { return (a > b) - (b > a); }
static int cmp_id(const void *const va, const void *const vb) {
const struct ExampleStruct *const a = va, *const b = vb;
return cmp_int(a->id, b->id);
}
static int cmp_year(const void *const va, const void *const vb) {
const struct ExampleStruct *const a = va, *const b = vb;
return cmp_int(a->year, b->year);
}
static int cmp_price(const void *const va, const void *const vb) {
const struct ExampleStruct *const a = va, *const b = vb;
return cmp_int(a->price, b->price);
}
int main(void) {
struct ExampleStruct a[5];
size_t a_size = sizeof a / sizeof *a;
for_each(a, a_size, &fill);
printf("Sorted by id.\n");
qsort(a, a_size, sizeof *a, &cmp_id);
for_each(a, a_size, &print);
printf("Sorted by year.\n");
qsort(a, a_size, sizeof *a, &cmp_year);
for_each(a, a_size, &print);
printf("Sorted by price.\n");
qsort(a, a_size, sizeof *a, &cmp_price);
for_each(a, a_size, &print);
return EXIT_SUCCESS;
}