Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using qsort for character array in C

I'm trying to use qsort to sort a character array. I can't see why this is not working. I have a pointer to the compare function as the man pages specifies. Can someone please tell me what's wrong? Thanks. My code:

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

int cmpfunc( const void *a, const void *b) {
  return *(int*)a - *(int*)b;
}

void AlphabetSoup( char str[] ) {
  qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
  printf("%s\n", str);
}


int main() {
  char str1[] = "bcead";

  AlphabetSoup(str1);

  return 0;
}

outputs: dabce when I expect abcde.

like image 452
user1527227 Avatar asked Apr 18 '14 04:04

user1527227


People also ask

What is the use of qsort in C?

It is called by qsort() , multiple times, to compare two elements. Since the comparator function is user-defined, it can be used to define the logic for comparing elements of any datatype (i.e. structs).

Is qsort standard C?

qsort is a C standard library function that implements a polymorphic sorting algorithm for arrays of arbitrary objects according to a user-provided comparison function.

Is qsort Quicksort in C?

No, they aren't. qsort() is a C standard library function. "Quicksort", on the other hand, is a specific sorting algorithm.

How do you qsort a string?

To use qsort with array of strings, we need to customize the compare function. This can be done using strcmp function to compare strings in C. Note strings are array of characters in C.


1 Answers

Simple error.

Use char* instead of int* in cmpfunc.

int cmpfunc( const void *a, const void *b) {
  return *(char*)a - *(char*)b;
}

When you use int*, instead of char*, the address pointed to by a is interpreted as an address to an int, not a char.

Your input has the following characters:

+---+---+---+---+---+
| b | c | e | a | d |
+---+---+---+---+---+

In hex, those are:

+----+----+----+----+----+
| 62 | 63 | 65 | 61 | 64 |
+----+----+----+----+----+
^    ^
|    |
a    b

If you treat the addresses pointed to a and b as int*, assuming an int takes 4 bytes in your system, *(int*)a can be either

0X62*2^24 + 0X63*2^16 + 0X65*2^8 + 0X61

or

0X62 + 0X63*2^8 + 0X65*2^16 + 0X61*2^24

depending on whether you have big endian system or a little endian system.

You can similarly compute what *(int*)b would be. As you can see, you are already running into unexpected number comparisons. By the time you start comparing the values that are at other byte locations of your input, you are also using memory that you are not supposed to use, and you are reaching the realms of undefined behavior.

like image 145
R Sahu Avatar answered Oct 05 '22 23:10

R Sahu