I am sorting/searching a struct array.
struct Substance
{
char name[NAME_SIZE]
int mass;
double halftime;
}
The sorting/searching is done after prompting the user to choose what member of the struct to sort by, i.e by name, mass or halftime.
Is there a way to make a general function that can work with all of the three data types or do I have to write different functions for each?
The reason why I don't want to write several functions is that 90% of the code in each function would be the same.
I am especially struggling with the fact that I have to get the member I want to operate on for each iteration, i.e substances[i].mass
to access the mass and this syntax obviously has to be different for each member of the struct.
I tried to do some pre processing to avoid this issue:
switch(choice)
{
case '1':
memcpy(current, substances[i].name, NAME_SIZE);
break;
case '2':
sprintf(current, "%d", substances[i].mass);
break;
case '3':
sprintf(current, "%lf", substances[i].halftime);
}
But if I want to sort by mass
I would then have to convert every other substance's mass
in the struct array aswell.
I have also thought about representing every member as the same data type in the first place and then just convert in when needed, like printing, writing to file etc but I don't know what data type I would use.
A general use case would be:
/*
Do you want to sort by (1) name, (2) mass or (3) halftime: 2
Sorted list by mass:
Name Mass Halftime
Zirconium 91 ...
Radon 220 ...
Radon 222 ...
Uranium 238 ...
*/
CodePudding user response:
Yes qsort(). example:
Given struct:
struct Substance
{
char name[NAME_SIZE]
int mass;
double halftime;
};
And assuming array defined substances[N];//has been populated
, then examples of calls can be:
qsort(substances, N, sizeof (struct Substance), compareName);
qsort(substances, N, sizeof (struct Substance), compareMass);
qsort(substances, N, sizeof (struct Substance), compareHtime);
...with the forms for your compare functions being passed in qsort()
being:
int compareName(const void *a, const void *b)
{
const struct Substance *ia = a;
const struct Substance *ib = b;
return strcmp(ia->name, ib->name);//returns -1, 0 1 per strcmp rules
}
int compareMass(const void *a, const void *b)
{
const struct Substance *ia = a;
const struct Substance *ib = b;
return ia->mass == ib->mass ? 0 :
ia->mass > ib->mass ? 1 : -1;
}
int compareHtime(const void *a, const void *b)
{
const struct Substance *ia = a;
const struct Substance *ib = b;
return fabs(ia->halftime - ib->halftime) < 0.00001 ? 0 :
(ia->halftime - ib->halftime) > 1 ? 1 : -1;
}
"Is there a way to make a general function that can work with all of the three data types or do I have to write different functions for each?"
You could create a void function that uses your switch()
, and uses an enum
. to decide which of the three compare functions to call. Eg:
enum {
NAME,
MASS,
HALF,
TYPE_MAX
};
void sort(struct Substance *s, size_t size, int type)
{
switch(type)
case NAME;
qsort(s, size, sizeof (struct Substance), compareName);
break;
case
...