简体   繁体   中英

access struct member with a variable or pointer in C

I have a struct and want to sort an array of the struct using merge sort. I need to pass the sorting parameter to the merge function and access the struct members. Can this be done in C?

example:

struct movie_imdb_data {
    char color[15];
    char director_name[100];
    int num_critic_for_reviews;
    int duration; /// in min not date and time 
    int director_facebook_likes;
    int actor_3_facebook_likes;
    char actor_2_name[100]; 
    int actor_1_facebook_likes;
    int gross;
};

in the main function, I have:

    if (argc > 2) {
        column_sort = argv[2];
    }

now I want to call merge_sort(<array of struct>, <column_sort *>)

can I access the member in the array as array[0]->column_sort to compare?

now I want to call merge sort and pass the

I want to pass the array and the sorting parameter (that I need the array sorted by) can I use a variable in place of a members name ie..

arr[1].column_sort   

instead of

arr[1].color

Sounds like you want to take a command line argument specifying the name of the field to sort on and then sort on that field.

For that, try code like:

#include <stdlib.h>
#include <string.h>

/* compare function for field 3: "num_critic_for_reviews" */    
int compField3(const void *a, const void *b)
{
    struct movie_imdb_data* aStruct = (struct movie_imdb_data*)a;
    struct movie_imdb_data* bStruct = (struct movie_imdb_data*)b;
    return (aStruct->num_critic_for_reviews < bStruct->num_critic_for_reviews)?
        -1: (aStruct->num_critic_for_reviews > bStruct->num_critic_for_reviews)?
            +1: 0;
}

/* also define other compare functions for each field */

int main()
{
    const char* columnName = argv[2];
    struct movie_imdb_data* parray;
    parray = your-array;
    int (*comp)(const void *, const void *, void *) = 0;

    /* map the column name to compare function for that column */
    if (strcmp(columnName, "num_critic_for_reviews") == 0)
    {
        comp = compField3;
    }
    /* map other names to compare function for column */
    else if (...) {...}
    else { exit(1); /* if not recognized column name */ }

    qsort(parray, numElementsOfArray, sizeof(struct movie_imdb_data), comp);
    ...
}

Hope this helps!

There are different approaches to your problem:

  • you can write separate functions to compare structures on specific fields. In main , you would select the appropriate comparison function by testing the name of the field (or possibly generic names that are not field names). You would then pass this comparison function to mergesort (or qsort ...).

  • if all members have the same type, you could determine the offset of the field from the beginning of the structure with macros offsetof(type, member) . There is no generic way to compute these offsets, you need to write a series of tests or use a table. The comparison function would use casts to access the members:

     size_t member_offset = offsetof(struct movie_imdb_data, duration); int comp_int_member(const void *a1, const void *a2) { const int *p1 = (const int *)((const unsigned char*)a1 + member_offset); const int *p2 = (const int *)((const unsigned char*)a2 + member_offset); return (*p1 > *p2) - (*p1 < *p2); } 

    The downside of this latter approach is it can only handle fields with a given type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM