1

I already have a list of strings read in from a text file into a 2D array named word ready to be sorted.

The list looks like:

I
like
cherry
pie
and
chocolate
pie

I want the list to look like this after sorted:

and
cherry
chocolate
I
like
pie
pie

The function prototype is below. int counter is the amount of strings, and MAX_CHAR_LEN = 1024 in case you were wondering.

void alphabetize(char word[][MAX_CHAR_LEN], int counter)
{

    return;
}

Notice that sorting by the first character alone is not sufficient, as the list contains two strings that start with "ch"

Can someone provide a function that can do this? Thanks in advance.

Karim Elsheikh
  • 349
  • 3
  • 6
  • 18

4 Answers4

2

You want to use the qsort() function.

qsort(base, num_of_elements, element_size, my_compare);

The comparison function my_compare takes two arguments, each a const void *, and returns a number indicating the relative order of the arguments. A negative number means the first argument is before the second argument. A positive number means the first argument is after the second argument. A zero is returned if the arguments have compared to be equal.

As your string comparison is case insensitive, you will need to create your own comparison function, or find one provided to you by your system that is not part of the C library proper. POSIX provides strcasecmp() for this purpose (Google tells me that _stricmp() is available on Windows).

int my_compare (const void *a, const void *b) {
    return strcasecmp(a, b);
}

Defining the comparison function is usually the trickiest part of using qsort(). You have to understand the context of the pointers that are being passed into that function. When an array of TYPE is passed into qsort(), it will pass a pointer to const TYPE to each argument of the comparison function.

In your case, you would be passing in an array of array of MAX_CHAR_LEN chars. So, each argument to the comparison function is a pointer to const array of MAX_CHAR_LEN chars. This means that technically, the my_compare function should be written like this:

int my_compare (const void *a, const void *b) {
    typedef char TYPE[MAX_CHAR_LEN];
    const TYPE *aa = (const TYPE *)a;
    const TYPE *bb = (const TYPE *)b;
    return strcasecmp(*aa, *bb);
}

The cast on the arguments would normally not be necessary, except that C doesn't really support the notion of a constant array. It converts such a thing into an array of constants, so the cast is required to reflect that.

However, the address of an array is equal to the address of its first element. That is, for the code above, the following assertions would be true:

    assert(aa == (const void *)*aa);
    assert(bb == (const void *)*bb);

So, because the dereference of a pointer to an array equals the decayed address value of the same array, the first implementation of my_compare() is sufficient for your 2-D array.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • Why it is giving warning: `warning: initialization discards 'const' qualifier from pointer target type [enabled by default]`, when cast is removed from the assignment `const TYPE *aa = a;` ? – haccks Jun 24 '14 at 07:25
  • @haccks: This is explained in the the text under the `my_compare()` code block in the answer. – jxh Jun 24 '14 at 08:10
  • Then, simply can't it be done by using `const char (*aa)[MAX_CHAR_LEN] = (const char (*)[MAX_CHAR_LEN])a; const char (*bb)[MAX_CHAR_LEN] = (const char (*)[MAX_CHAR_LEN])a;` ? – haccks Jun 24 '14 at 09:00
  • @haccks: I don't see how that is more simple, but you can do it however you want. – jxh Jun 24 '14 at 15:21
  • But there is a problem in using this. I got the same warning without cast as in above case. I do not understand why? Another thing is that, what is the difference between *constant array* and *array of constants*. – haccks Jun 24 '14 at 15:24
  • @haccks: There is no syntax to express a constant array, but if you have an array of arrays, a pointer to a constant array is what `qsort()` will pass to the comparison callback function (just like if you have an array of `int`s, the callback gets a pointer to a `const int`). – jxh Jun 24 '14 at 15:45
  • `int const a[r][c]`--> `a` is an array of arrays of `c` constant int`s. After decay, `a` is of type *pointer to an array of `c` constant `int`s*, then `qsort` should pass pointer to array of constants, isn't it? (I don't know what is *constant array*. I found nothing about it). – haccks Jun 24 '14 at 15:57
  • 1
    @haccks: There is no syntax to express a constant array, which is why you can't find anything about it. `qsort()` doesn't know what the actual type of the array it is sorting is, it passes a `const void *`, where `void` stands for the object being sorted. The decay you are talking about occurred at or before `qsort()` was passed the array to sort. – jxh Jun 24 '14 at 17:53
  • OK. That mean in case of 2D array, the object to be sorted passed to compare is a 1D array which is of `const` type. Therefore assignment `const char (*aa)[MAX_CHAR_LEN] = a;` discards the `const`-ness of `a`, am I right? – haccks Jun 24 '14 at 19:37
  • @haccks: That would be my understanding as well. – jxh Jun 24 '14 at 23:18
1

You can use the qsort function to sort. You also need to create a compare function that compares two arrays of chars, and then pass that function pointer as an argument.

Example that sorts ints:

/* qsort example */
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* qsort */

int values[] = { 40, 10, 100, 90, 20, 25 };

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

int main ()
{
  int n;
  qsort (values, 6, sizeof(int), compare); 
  for (n=0; n<6; n++)
     printf ("%d ",values[n]);
  return 0;
}

The above code can easily be adapted to sort arrays of chars instead of ints.

jh314
  • 27,144
  • 16
  • 62
  • 82
0

If you want to write your own sort function, something like this is pretty straight forward.

for (int i = 0; i < array.size(); i++)
{
    for (int j = i+1; j < array.size(); j++)
    {
        if (array[i] > array[j])
            swap(array[i],array[j]);
    }
}
sora0419
  • 2,308
  • 9
  • 39
  • 58
0

qsort is Good Option. See it's detail here

You can also try Bubble Sort. It's implementation in C is easy - See this Good answer for help

Community
  • 1
  • 1
Shumail
  • 3,103
  • 4
  • 28
  • 35