2

I am just working on a liberty functions in which we define our own datatypes for student and book I have to write a code which finds student by id and book by id these are the two functions. In this functions the pointers which I pass are different but the logic is the same so I got a though that why can't we write one function and pass which thing we want. I mean when we pass the student list it will return the index of student when we pass the book list it will return the book index of the book. Can we use void pointers for that??? Thank you everyone!!!

int findBookId(Book* booklist,int* bcount,unsigned int* tbid)
{
    int i;
    for (i=0; i<*bcount; i++)
    {
        if (booklist[i].id==*tbid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}

int findStuId(Student* stulist,int* scount,unsigned int* tsid)
{
    int i;
    for (i=0; i<*scount; i++)
    {
        if (stulist[i].id==*tsid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}   
1
  • You can do it by type casting to void pointer in function by which type info you wan but also necessary to inform function which info you want like pass extra flag regarding info type. Commented Mar 24, 2014 at 4:37

4 Answers 4

1

Assuming you have a student structure:

struct student {
    int id;
    char name[20];
};

You can imitate qsort() function, to design a parameter to receive a callback function and to receive the size and size of each element if you'd like use void *.

int find_ele(void *base, size_t num, size_t width,
    int (*equal)(const void *, const void *),
    void *param)
{
    int i;

    for (i = 0; i < num; ++i) {
        if (equal((char *) base + i * width, param)) {
            return i;
        }
    }

    return -1;
}

Then, define a "tester":

int student_tester(const void *p1, const void *p2)
{
    struct student *sp = (struct student *) p1;
    int id = *(int *) p2;
    return sp->id == id;
}

In main() function:

int main(void)
{
    struct student student_list[] = {
        0, "A",
        1, "B",
        2, "C"
    };

    int id = 2;
    int index = find_ele(student_list, sizeof student_list,
        sizeof(struct student), student_tester, &id);
    if (index != -1) {
        printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
            index, student_list[index].name);
    } else {
        printf("Not found. \n");
    }

    return 0;
}

This is a bit complicated. You can create macros to simplify it if you don't care.

Rename find_ele to _find_ele, and create a macro:

#define find_ele(base, num, compare, param) _find_ele(base, \
    num / sizeof base[0], \
    sizeof base[0], \
    compare, param)

And create another macro to define a "tester":

#define define_tester(name, type, type_to_find, code) \
    int name(const void *_p, const void *param) { \
        type *p = (type *) _p; \
        type_to_find value = *(type_to_find *) param; \
        return (code); \
    }

Now you can define a "tester" like this:

define_tester(student_tester, struct student, int,
    p->id == value);

Complete code:

#include <stdio.h>

int _find_ele(void *base, size_t num, size_t width,
    int (*equal)(const void *, const void *),
    void *param)
{
    int i;

    for (i = 0; i < num; ++i) {
        if (equal((char *) base + i * width, param)) {
            return i;
        }
    }

    return -1;
}

#define find_ele(base, num, compare, param) _find_ele(base, \
    num / sizeof base[0], \
    sizeof base[0], \
    compare, param)

#define define_tester(name, type, type_to_find, code) \
    int name(const void *_p, const void *param) { \
        type *p = (type *) _p; \
        type_to_find value = *(type_to_find *) param; \
        return (code); \
    }

struct student {
    int id;
    char name[20];
};

define_tester(student_tester, struct student, int,
    p->id == value);

int main(void)
{
    struct student student_list[] = {
        0, "A",
        1, "B",
        2, "C"
    };

    int id = 2;
    int index = find_ele(student_list, sizeof student_list, student_tester, &id);
    if (index != -1) {
        printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
            index, student_list[index].name);
    } else {
        printf("Not found. \n");
    }

    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

0

Yes you can use void*, but while dereferencing you should know the exact type of the pointer.
So, when you can your function, add another parameter:

type = 0 for Books
     = 1 for students 

And then your function becomes:

int findId(void* list,int* count,unsigned int* tbid, int type)
{
    Book* booklist=NULL;
    Student* stulist=NULL;
    int i;
    if(type===0)
         booklist = (Book*) list;
    else if(type==1)
         stulist = (Student*) list;
    else
         // Handle this undefined case

    // And now use the same type variable to decide which pointer to use to match the values
    . . . . 
}

1 Comment

thank you vary much i am looking for this answer. thanks a lot
0

Yes you can use void pointer, if you are trying to store address of your array..Your array may contain integer types or some other datatypes stored, it doesn't matter, but right typecasting while de-referencing the void pointer is important.

2 Comments

and for right typecasting you should know the type of object pointed by the void pointer.which i think is not possible in C but i guess you can do it in C+= using typecasting operators and RTTI
but right typecasting while de-referencing the void pointer is important. but which type to cast?
0

I don't think you can use void* in these functions.

If you changed your functions to one and created something like:

int findObjId(void* objlist,int* count, unsigned int* objid)
{
    int i;
    for (i=0; i<*scount; i++)
    {
        if (objlist[i].id==*objid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}   

you won't be able to extract the data from objlist. Neither *objlist, nor objlist[i] can be dereferenced to evaluate to an object. The compiler will definitely stop you from using any such statement.

If you have the option, switch to C++. Using templates, you can accomplish your goal without breaking a sweat.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.