Search code examples
cqsort

qsort not sorting and strange output


so I'm using C, I cant seem to get this to work right. It's an array of pointers to structs which contain some contact info. I can't seem to get the qsort to sort correctly. Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
#define ELEMENTS 50

int sortZips(const void *a, const void *b);

typedef struct contactInfo {
char name[MAX];
char street[MAX];
char cityState[MAX];
char zipCode[MAX];
} contacts;


int main() {
int i = 0;
contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));     

/*  allocate array  */
for (i = 0; i < ELEMENTS; i++) {
    contactArray[i] = malloc(sizeof(contacts));
}
/*  populate array  */
for (i = 0; i < ELEMENTS; i++) {
    fgets(contactArray[i]->name,MAX,stdin);
    fgets(contactArray[i]->street,MAX,stdin);
    fgets(contactArray[i]->cityState,MAX,stdin);
    fgets(contactArray[i]->zipCode,MAX,stdin);

    printf("%s", contactArray[i]->name);
    printf("%s", contactArray[i]->street);
    printf("%s", contactArray[i]->cityState);
    printf("%s", contactArray[i]->zipCode);

}
printf("\n");


/*  qsort((void *)contactArray, ELEMENTS, sizeof(contacts *), sortZips);  */


for (i = 0; i < ELEMENTS; i++) {
    fputs(contactArray[i]->name,stdout);
    fputs(contactArray[i]->street,stdout);
    fputs(contactArray[i]->cityState,stdout);
    fputs(contactArray[i]->zipCode,stdout);
}


}


/*  sortZips() sort function for qsort  */

int sortZips(const void *a, const void *b) {

const contacts *ia = *(contacts **)a;
const contacts *ib = *(contacts **)b;
return strcmp(ia->zipCode, ib->zipCode);



}

The output is printing the addresses (I have 50 in an input file) and then some random characters, like a huge block of them, then the sorted list after that which is messed up and not sorted right.

Please any help would be appreciated. I need to learn what's wrong here and why. Thanx.


Solution

  • First rule: always check input functions - in this case, fgets(). You don't know whether everything is working correctly or not if you do not check.

    Second: use enum in preference to #define in general.

    With the check for early EOF in place, your code sorted my sample data (6 rows) cleanly. It also compiled cleanly - which is very unusual (that's a compliment; I use stringent warnings and even my code seldom compiles cleanly the first time). My amended version of your code is very similar to yours:

    int main(void)
    {
        int i = 0;
        int num;
        contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));
    
        /*  allocate array  */
        for (i = 0; i < ELEMENTS; i++)
            contactArray[i] = malloc(sizeof(contacts));
    
        /*  populate array  */
        for (i = 0; i < ELEMENTS; i++)
        {
            if (fgets(contactArray[i]->name,MAX,stdin) == 0 ||
                fgets(contactArray[i]->street,MAX,stdin) == 0 ||
                fgets(contactArray[i]->cityState,MAX,stdin) == 0 ||
                fgets(contactArray[i]->zipCode,MAX,stdin) == 0)
                break;
            printf("%s", contactArray[i]->name);
            printf("%s", contactArray[i]->street);
            printf("%s", contactArray[i]->cityState);
            printf("%s", contactArray[i]->zipCode);
        }
        printf("\n");
        num = i;
    
        qsort(contactArray, num, sizeof(contacts *), sortZips);
    
        for (i = 0; i < num; i++)
        {
            fputs(contactArray[i]->name,stdout);
            fputs(contactArray[i]->street,stdout);
            fputs(contactArray[i]->cityState,stdout);
            fputs(contactArray[i]->zipCode,stdout);
        }
        return 0;
    }
    

    The data I used was trivial repetitions of sets of 4 lines like this:

    First LastName7
    7 Some Street
    City, CA
    95437
    

    Note that the 'error checking' I do in the input is the bare minimum that 'works'. If you get an over-long line in the input, one field will not contain a newline, and the next will contain the next section of the input line (possibly all the rest, possibly not - it depends on how badly overlong the line is).