Using qsort in C on an array of strings

1k views Asked by At

I can't figure out how to use qsort. I want to sort an array of strings. Like so:

John              Adam
Adam      ->      John
Stacy             Stacy

However, nothing I do seems to work. I've tried copying exactly what others have used (about 5 different qsort functions from various sources) and nothing has worked. I have one for int's that works (backwards but at least it works).

Here's the necessary code I have:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
char name[80];
int age;
} RECORD;
RECORD record[25];

int main (int argc, char *argv[80]){     // Using command line to get my strings

    int i = 2, j;
    for(j = 0; j < (argc / 2); j++)      //Converting and storing my ages
    {
        record[j].age = atoi(argv[i]);
        i = i + 2;
    }

    int p, q = 1;
    for(p = 0; p < (argc / 2); p++)
    {
        strcpy(record[p].name, argv[q]);
        q = q + 2;
    }
}

int compareByName(const void* a, const void* b) //The qsort that doesn't work at all
{
    const char *ia = (const char *)a;
    const char *ib = (const char *)b;

    return strncmp(ia, ib, 25);
}

int compareByAge (const void * a, const void * b)  //My other qsort that works backwards
{

    RECORD *RECORDA = (RECORD *)a;
    RECORD *RECORDB = (RECORD *)b;

    return ( RECORDB->age - RECORDA->age );
}

void printRecords(RECORD r[], int num){
//printing stuff here

double size = sizeof r[0];
double count = sizeof(r)/size;          //My qsort with size stuff, doesn't work
qsort(r, count, size, compareByName);   // if I do it the same as the other  

qsort (r, 25, sizeof(RECORD), compareByAge);   //My other qsort that works backwards

//more printing stuff here
}
3

There are 3 answers

0
Chris Dodd On

You don't have an array of strings, you have an array of RECORDs, and it sounds like you want to sort that array based on the strings in the name array of the records. So you want something like:

int compareByName(const void *a_, const void *b_) {
    RECORD *a = a_, *b = b_;

    return strcmp(a->name, b->name);
}

and then you sort with

qsort (r, 25, sizeof(RECORD), compareByName);
0
Jeffrey Hantin On

Okay, I see several issues here.

It's worth noting that sizeof is evaluated at compile time, so you can't use sizeof(r) to determine the size of a dynamically-sized array you were passed. I'm going to guess that's why num is passed in to printRecords.

As @Chris points out, you're sorting RECORD structures rather than character pointers, so the comparison function and the qsort call both need to take that into account.

You have the subtraction reversed in the age comparison - it needs to return a negative number if the left side is less than the right side, so use RECORDA->age - RECORDB->age.

1
QuestionC On

First off (this is why your strings aren't sorting), double count = sizeof(r)/size; is wrong. sizeof(r) isn't doing what you expect it to. You'll need to pass the size of the array to printRecords() as described in this question:

How to get the length of array in C? is "sizeof" is one of the solution?

Second off, int compareByAge (const void * a, const void * b) //My other qsort that works backwards is backwards because you're doing it backwards. Comparator functions always return A - B, not B - A.