指向c

时间:2019-11-08 21:57:54

标签: c

我想按特定字段的值对结构进行排序。字段中的数据类型相同。在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上以某种方式仿真以及如何执行

2 个答案:

答案 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;
}