Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

qsort on more than one item in a struct

Tags:

c

qsort

I'm tasked with the user inputting n lines containing a month, day and year in the form of 'January 12 99'.

I have to sort the list of dates chronologically using qsort first by year, then by day, then by month.

My problem is I am not sure of how to qsort on multiple indexes. I have done it for the year whic works fine but after that I don't know how to qsort on the day as surely it will just sort it by day but the years will be muddled up again?

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

typedef int (*compfn)(const void*, const void*);

struct date
{
    char month[9]; //Maximum of 9 characters in a month
    int day; //The day of the month (e.g. 18)
    int year; //The year of the date    
};

int sortDates(struct date *elem1, struct date *elem2)
{

    if (elem1 -> year < elem2 -> year)
    {
        return -1;
    }
    else 

    if (elem1->year > elem2->year)
        {
        return 1;
    }
    else
        return 0;

}


main()
{
    int n;
    int i;

    scanf("%d", &n);

    struct date *list;

    list = (struct date *)malloc((n * sizeof(struct date)));

    for(i = 0; i < n; i++)
    {
        scanf("%s %d %d", list[i].month, &list[i].day, &list[i].year);
    }

    qsort(list, sizeof(list), sizeof(struct date), (compfn)sortDates);

    for(i = 0; i < n; i++)
    {
        printf("%s %d %d\n", list[i].month, list[i].day, list[i].year);
    }
}

EDIT: So I have the sort working, I am just struggling with converting from an integer back to the string representation of the month when printing the sorted list. Here is the code, I am getting "array subscript is not an integer" error.

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

typedef int (*compfn)(const void*, const void*);

struct date
{
    int month;
    int day; //The day of the month (e.g. 18)
    int year; //The year of the date    
};

char* months[]= {
   "January", "February",
   "March", "April",
   "May", "June",
   "July", "August",
   "September", "October",
   "November", "December"};


int getMonth(char tempMonth[])
{
    int i = 0;
    for(i = 0; i<12; i++)
    {
            if(tempMonth == months[i]) return i;
    }
    return 0;
}

char getStringMonth(struct date month)
{
    return months[month];
}

int sortDates(struct date *elem1, struct date *elem2)
{
    if (elem1 -> year < elem2 -> year)
    {
        return -1;
    }
    else 

    if (elem1->year > elem2->year)
        {
        return 1;
    }


    if ( elem1->month < elem2->month )
    {
            return -1;
    }
    else 

    if ( elem1->month > elem2->month )
        {
        return 1; 
    }


    if ( elem1->day < elem2->day )
    {list
            return -1;
    }
        else 

    if ( elem1->day > elem2->day )
        {
        return 1;
    } 
        else

    return 0;
}

main()
{
    int n;
    int i;
    char tempMonth[255]; //Used to store the month until checked

    scanf("%d", &n);list

    struct date *list;

    list = (struct date *)malloc((n * sizeof(struct date)));

    for(i = 0; i < n; i++)
    {
        scanf("%s %d %d", tempMonth, &list[i].day, &list[i].year);
        list[i].month = getMonth(tempMonth);
    }

    qsort(list, sizeof(list), sizeof(struct date), (compfn)sortDates);

    for(i = 0; i < n; i++)
    {
        printf("%s %d %d", getStringMonth(list[i].month), list[i].day, list[i].year);
    }

}
like image 679
Mike Avatar asked Mar 08 '12 12:03

Mike


People also ask

What is the time complexity of qsort in C?

The time complexity of the quicksort in C for various cases is: Best case scenario: This case occurs when the selected pivot is always middle or closest to the middle element of the array. The time complexity for such a scenario is O(n*log n).

Is qsort and Quicksort same?

No, they aren't. qsort() is a C standard library function. "Quicksort", on the other hand, is a specific sorting algorithm. It is often used as the backing algorithm of an actual implementation of qsort() .

Is qsort in C Stable?

Since quicksort is an unstable sort — there are multiple possible results when the array contains equivalent elements — this means qsort() is not guaranteed to be stable, even if internally the C library is using a stable sort like merge sort. The C standard library has no stable sort function.


1 Answers

Remember to free the memory you malloc'd.

In the following code I have assumed that the month is stored as a number, but I see in your struct that this is not the case. I would convert the inputted month from string to a number, to ease the sorting process.

int sortDates(struct date* elem1, struct date* elem2)
{

    if ( elem1->year < elem2->year)
        return -1;
    else if ( elem1->year > elem2->year )
        return 1;


    /* here you are sure the years are equal, so go on comparing the months */

    if ( elem1->month < elem2->month )
        return -1;
    else if ( elem1->month > elem2->month )
        return 1; 

    /* here you are sure the months are equal, so go on comparing the days */

    if ( elem1->day < elem2->day )
        return -1;
    else if ( elem1->day > elem2->day )
        return 1; 
    else
        return 0; /* definitely! */

}

Also pay attention to this declaration: char month[9];, it is true that September is 9 chars, but you need a terminator char '\0' in C to close a string. To avoid this sort of problems, I would declare an array with all the months, to allow the checking and to convert the month from a string to a number:

char* allMonths[]=
   "January", "February",
   "March", "April",
   "May", "June",
   "July", "August",
   "September", "October",
   "November", "December";

char tmpMonth[255];
scanf("%s %d %d", tmpMonth, &list[i].day, &list[i].year);
/* convert tmpMonth to a number by finding it in the allMonths and throw error if not found */
like image 109
vulkanino Avatar answered Oct 24 '22 15:10

vulkanino