Say I have this struct:
struct MyStruct {
int iID;
int iMyNumber;
};
Then I define an array of MyStructs:
struct MyStruct msTest[3];
I'm doing a sorting operation on a struct similar to this one by looking at the ID. Now, as soon as I find out which records should be swapped to sort the array I have to do the actual swapping. I tried this:
if (iSmallest != iCntr) {
stPTmp = &stXDB[iCntr];
&stXDB[iCntr] = &stXDB[iSmallest];
&stXDB[iSmallest] = &stPTmp;
}
stPTmp is defined as void *stPTmp;
and iCntr
and iSmallest
contain the indices of the records to be swapped. My code doesn't work, but how do I fix it?
You need to swap elements, not pointers,
struct MyStruct stTmp;
if (iSmallest != iCntr) {
stTmp = stXDB[iCntr];
stXDB[iCntr] = stXDB[iSmallest];
stXDB[iSmallest] = stTmp;
}
Not terribly efficient, but your structs are small, so its only a bit more expensive than swapping pointers.
You could just let someone else think about this, i.e. use qsort()
:
#include <stdlib.h>
int compare_struct(const void *a, const void *b)
{
const struct MyStruct *sa = a, *sb = b;
return (sa->iID < sb->iID) ? -1 : sa->iId > sb->iId;
}
qsort(msTest, sizeof msTest / sizeof *msTest, sizeof *msTest, compare_struct);
Note that this totally removed the need to write the swapping function. Under the hood, this might be a bit more costly (could use malloc()
, almost certainly uses memcpy()
), but it's way easier to write and much easier to maintain.
John has already answered your question, but to sort your struct
s, you can use the standard library qsort()
function:
#include <stdlib.h>
#include <stdio.h>
struct MyStruct {
int iID;
int iMyNumber;
};
/* comparison function, should return < 0, > 0 or == 0
if a < b, a > b or a == b respectively. Used by qsort */
static int comp_mystruct(const void *a, const void *b);
/* utility function to print an array of our struct */
static void print_mystruct(const void *start, size_t n);
int main(void)
{
/* some data */
struct MyStruct data[] = {
{ 1, 10 },
{ 5, 50 },
{ 2, 20 },
{ -3, 100 }
};
size_t ndata = sizeof data / sizeof data[0];
/* before sorting */
print_mystruct(data, ndata);
putchar('\n');
/* sort the array now */
qsort(data, ndata, sizeof data[0], comp_mystruct);
/* after sorting */
print_mystruct(data, ndata);
return 0;
}
static void print_mystruct(const void *start, size_t n)
{
size_t i;
const struct MyStruct *s = start;
for (i=0; i < n; ++i) {
printf("% 3d % 3d\n", s[i].iID, s[i].iMyNumber);
}
}
static int comp_mystruct(const void *a, const void *b)
{
const struct MyStruct *sa = a;
const struct MyStruct *sb = b;
if (sa->iID > sb->iID) {
return 1;
} else if (sa->iID < sb->iID) {
return -1;
} else {
return 0;
}
}
The output of the program is:
1 10
5 50
2 20
-3 100
-3 100
1 10
2 20
5 50
The advantage is that qsort()
is standard, and you can use it to sort anything.