Rafa
Rafa

Reputation: 33

Pass the field name of struct to access inside a function

I have a linked list and I made a function to fetch a node. But I want to use it both to search by first or last name.

typedef struct people {
   char name[60],
        lastname[60];
   struct people *next;
} people;

people *search(const char *key, people *list, FIELD) {
    while (list && strcmp(key, list->FIELD) != 0) {
        list = list->next;
    }
    return list;
}

Example:

people *aux;
aux = search("John", list_of_people, "name");

Or:

aux = search("Smith", list_of_people, "lastname");

There is a clear and efficient way to solve this problem without repeating code?

Upvotes: 3

Views: 994

Answers (3)

BLUEPIXY
BLUEPIXY

Reputation: 40145

use offsetof(<stddef.h>) macro.

E.g:

people *search(const char *key, people *list, size_t FIELD) {// FIELD is field offset,
    while (list && strcmp(key, (char*)list + FIELD) != 0) {
        list = list->next;
    }
    return list;
}

call

aux = search("John", list_of_people, offsetof(people, name));
aux = search("Smith", list_of_people, offsetof(people, lastname));

Upvotes: 2

R Sahu
R Sahu

Reputation: 206577

I would recommend using an enum to do the different searches.

enum {SEARCH_BY_FIRSTNAME, SEARCH_BY_LASTNAME};

char* getSeachName(people* list, int searchBy)
{
   return ( searchBy == SEARCH_BY_FIRSTNAME ? list->name : list->lastname );
}

people *search(const char *key, people *list, int searchBy) {
    while (list && strcmp(key, getSearchName(list, searchBy)) != 0) {
        list = list->next;
    }
    return list;
}

// Search by first name.
people *aux;
aux = search("John", list_of_people, SEARCH_BY_FIRSTNAME);

// Search by last name.
aux = search("Smith", list_of_people, SEARCH_BY_LASTNAME);

Upvotes: 2

Crowman
Crowman

Reputation: 25908

With just two fields, this seems like the obvious way:

people *search(const char *key, people *list, bool first) {
    while (list && strcmp(key, first ? list->name : list->lastname) != 0) {
        list = list->next;
    }
    return list;
}

For a more general case, something like this would work:

struct mystruct {
    char field1[60];
    char field2[60];
    char field3[60];
    char field4[60];
    char field5[60];
    struct mystruct * next;
}

char * get_field(struct mystruct * list, size_t field) {
    char * fields[] = { list->field1, list->field2, list->field3,
                        list->field4, list->field5 };
    return fields[field];
}

people *search(const char *key, people *list, bool first) {
    while (list && strcmp(key, get_field(list, 3)) != 0) {
        list = list->next;
    }
    return list;
}

Upvotes: 2

Related Questions