Reputation: 2100
I'm having a problem with the following VS 2010 code. Am trying to sort an array of structures. The code compiles without errors, is very fast, but has a problem in that the sort result is incorrect.
I am sorting by the "zip" character string (for test purposes, NOT numerically, but by character compare). I have a version of this running using the standard lib qsort, but want to do some further fiddling so am writing my own.
struct address {
char name[40];
char street[40];
char city[20];
char state[30];
char zip[21];
};
void qs_struct(struct address items[], int left, int right)
{
int i, j;
char *x;
struct address temp;
i = left;
j = right;
x = items[(left+right)/2].zip;
do {
while((strcmp(items[i].zip,x) < 0) && (i < right)){ i++;}
while((strcmp(items[j].zip,x) > 0) && (j > left)) { j--;}
if(i <= j) {
temp = items[i];
items[i] = items[j];
items[j] = temp;
i++; j--;
}
} while(i <= j);
if(left < j) qs_struct(items, left, j);
if(i < right) qs_struct(items, i, right);
}
void qx(struct address items[], int count)
{
qs_struct(items,0,count-1);
}
void fillStructWithRandomDataForTest(struct address *addr, int i, int j)
{
char temp[444];
sprintf(temp, "%d%d", j +i, j*i);
strcpy(addr->name, temp);
sprintf(temp, "%d%d", j +i, j*i);
strcpy(addr->street, temp);
sprintf(temp, "%d%d", j +i, j*i);
strcpy(addr->city, temp);
sprintf(temp, "%d%d", j +i, j*i);
strcpy(addr->state, temp);
sprintf(temp, "%d%d", j +i, j*i);
strcpy(addr->zip, temp);
}
void xqs(void)
{
struct address addrs[20];
for (int i = 0, j = 33; i < 16; ++i, --j)
fillStructWithRandomDataForTest(&addrs[i], i, j);
qx(addrs, 16);
// results: incorrectly sorted
for (int k = 0; k < 16; ++k)
printf("%s \n",addrs[k].zip);
}
Upvotes: 0
Views: 1036
Reputation: 2100
Instead of this:
while((i < n) && (strcmp(list[i].name, key) < 0)) i++;
while((j > m) && (strcmp(list[j].name , key) > 0)) j--;
should be this:
while((i <= n) && (strcmp(list[i].name, key) <= 0)) i++;
while((j >= m) && (strcmp(list[j].name , key) > 0)) j--;
Upvotes: 0
Reputation: 183978
This
x = items[(left+right)/2].zip;
ties the pivot to a position. When the middle address is moved, the pivot against which the zips are compared is changed. That messes up the sort. You need to copy the zip against which to compare,
x = strdup(items[(left+right)/2].zip); // or strlen and malloc
while (...)
free(x);
Upvotes: 1
Reputation: 62129
It would be nice if you had told us in precisely what way your results are incorrect, but it is okay, let me guess: it prints nothing, right? All blank lines, eh?
The very last loop in your code uses k
as loop counter, but then it uses i
as an index to select a struct to printf()
. This will always select addrs[16]
, which has not been initialized.
You need coffee. Or sleep. But not both.
Upvotes: 2