Home > Software engineering >  Array Sorting Through Structures and Functions
Array Sorting Through Structures and Functions

Time:10-03

This is the function I am currently working on, which is very similar to a qsort function. This function returns true if the array is sorted, and false if it is not. The thing I am struggling with is figuring out how to go through the array and call the comparison function given as a parameter.
My main goal is to compare each adjacent value of the array, and if it is > 0, return false. (Note: This is because my comparision functions are like the qsort function, returning 1 if the first value is greater, -1 if less, 0 if same).

1.) How would I call the compar function if the parameters are void? Also, how would I call on the array "stu" each time and compare each part (ID, firstname, lastname)? Would I need 3 if statements?

bool areStudentsSorted(Student * stu, int numelem, int (*compar)(const void *, const void *)) {
  for (int i = 0; i <= numelem; i  ){

    if (compar(i,i 1) > 0){             <- incorrect 
      //stuck

  return true;
}

Here are two ways of calling the function

if (!areStudentsSorted(stu, numelem, compareFirstName)) {
          return EXIT_FAILURE;
      }
if (!areStudentsSorted(stu, numelem, compareLastName)) {
          return EXIT_FAILURE;

This is an example of a comparison function

int compareLastName(const void * p1, const void * p2)
{
    const Student *stu1, *stu2;
    stu1 = p1;
    stu2 = p2;
    return strcmp(stu1->lastname, stu2->lastname);
}

And finally, this is the struct, Student

typedef struct
{
  int ID;
  char firstname[NAME_LENGTH] ;
  char lastname[NAME_LENGTH] ;
} Student;

CodePudding user response:

How would I call the compare function if the parameters are void?

The parameters are not void, they are void *. When you pass a pointer for a void * parameter, you can pass any type of pointer. It will be implicitly converted to a void * argument.

However, your function call is incorrect:

compar(i,i 1)

The variable i is not a pointer, it is an integer representing an index into the array. Instead, you should pass a pointer to the Student structures. So you should write

compar( &stu[i], &stu[i 1] )

instead. The & operator is the "address-of" operator.

Also, you should change

for (int i = 0; i <= numelem; i ){

to

for (int i = 0; i < numelem - 1; i ){

otherwise you will access the array out of bounds.


Also, how would I call on the array "stu" each time and compare each part (ID, firstname, lastname)? Would I need 3 if statements?

If you want the compare function to take all 3 fields into account when determining the sorting order, then you must decide by which criteria the students should be sorted. For example, you may want the students to be primarily sorted by last name, and if several students have the same last name, they should be sorted by first name, and if several students have the same last name and first name, you may want them to be sorted according to their ID. In that case, you could write a corresponding compare function which takes all 3 criteria into account:

int compareByAllThreeCriteria( const void * p1, const void * p2 )
{
    int ret;

    //compare last name
    ret = compareLastName( p1, p2 );
    if ( ret != 0 )
        return ret;

    //last name is identical, so it should be sorted by first name
    ret = compareFirstName( p1, p2 );
    if ( ret != 0 )
        return ret;

    //both names are identical, so it should be sorted by ID
    return compareID( p1, p2 );
}

You could also combine the functions compareLastName, compareFirstName and compareID into one large compare function:

int compareByAllThreeCriteria( const void * p1, const void * p2 )
{
    const Student *stu1, *stu2;
    stu1 = p1;
    stu2 = p2;

    int ret;

    //first compare the last name
    ret = strcmp(stu1->lastname, stu2->lastname);
    if ( ret != 0 )
        return ret;

    //last name is identical, so it should be sorted by first name
    ret = strcmp( stu1->firstname, stu2->firstname );
    if ( ret != 0 )
        return ret;

    //both names are identical, so it should be sorted by ID
    if ( stu1->ID < stu2->ID )
        return -1;
    if ( stu1->ID > stu2->ID )
        return  1;

    //if they are not smaller or greater, they must be equal
    return 0;
}

CodePudding user response:

  1. void * means that your parameter could point to anything, but it is just like any other pointer. You could pass the pointers of the elements you are trying to compare. e.g. compar(stu i, stu i 1)

I would recommend writing your compar function to handle comparing all three fields of your struct.

  • Related