Sort char pointer array in C - c

I am trying to sort array of char pointers, for that purpose I use qsort function, but I can't understand what I am doing wrong and how I can sort that array.
int StringCompare( const void* a, const void* b)
{
char const *char_a = (char const *)a;
char const *char_b = (char const *)b;
return strcmp(char_a, char_b);
}
int main() {
char *a[] = { "Garima",
"Amit",
"Gaurav",
"Vaibhav"
};
int n;
qsort( a, 4, sizeof(char*), StringCompare);
for (n=0; n<4; n++)
printf ("%c ",*a[n]);
}
The Output is: G A G V

The issue is that the values passed to the sort function (a.k.a StringCompare) are pointers into the a array. In other words, they are of type const char **.
You need to instead declare char_a and char_b as const char **, and dereference them in the call to strcmp:
int StringCompare( const void* a, const void* b)
{
char const **char_a = a;
char const **char_b = b;
return strcmp(*char_a, *char_b);
}
Also note the casts are unnecessary.

proper comparator:
int StringCompare( const void* a, const void* b)
{
char const *char_a = *(char const **)a;
char const *char_b = *(char const **)b;
return strcmp(char_a, char_b);
}
NOTE:
according to sort description comparator function is:
compar
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements.
It shall follow the following prototype:
int compar (const void* p1, const void* p2);
so, it receives not a char*, but char**
proper output cycle:
for (n=0; n<4; n++)
printf ("%s ", a[n]);

Define your StringCompare function this way:
int StringCompare(const char **a, const char **b)
{
return strcmp(*a, *b);
}
No need to clutter the code with explicit casting because you can implicitly cast a void pointer to any other pointer type.

If you want to sort char-arrays for the first letters, you could implement a function, that looks at the (unsigned) values of the first char in the array. As they are all equal to the numbers in the ASCII-standards. But you have to be careful if you mix upper case chars with lower case chars.
I know... its not a some special implemented function, but I once programmed it that way and it worked.

Related

getting at pointers in an array of struct passed as a void*

I have a function with a signature like qsort:
const char* get_str(int i, const void *base, size_t nmemb, size_t size);
I am passed arrays of pointers to const char*, or arrays of structs whose first field is a pointer to const char*.
What casts do I need to do to extract that pointer in the array element i?
I have tried casting the base as an array of char itself, so I can advance to the right element:
return *(const char**)(((const char*)base)[i * size]);
But the compiler is complaining: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
It looks like you want to implement a type or identification sytem for structs like so:
#include <stdlib.h>
#include <stdio.h>
struct a {
const char *id;
int x;
};
struct b {
const char *id;
double d;
};
union any {
struct a a;
struct b b;
};
int main()
{
struct a a[] = {{"one", 1}, {"two", 2}, {"three", 3}};
struct b b[] = {{"pi", 3.1415}, {"e", 2.71}};
union any any[3];
any[0].a = a[0];
any[1].b = b[0];
any[2].a = a[1];
puts(get_str(1, a, 3, sizeof(*a)));
puts(get_str(1, b, 2, sizeof(*b)));
puts(get_str(1, any, 3, sizeof(*any)));
return 0;
}
In this case, the following works:
const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
const char *p = base;
const char **pp = (const char**) (p + i * size);
return *pp;
}
This can be written in one line as:
const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
return *(const char**) ((const char *) base + i * size);
}
But I think that the detour via void pointers is not necessary. You can do the address calculations with the typed array:
puts(*(const char **) (&a[1]));
puts(*(const char **) (&b[1]));
puts(*(const char **) (&any[1]));
If you wrap that in a function:
const char *get_str(const void *str)
{
return *(const char **) str;
}
you get:
puts(get_str(&a[1]));
puts(get_str(&b[1]));
puts(get_str(any + 1));
which is more readable than the qsortish syntax in my opinion.
This works, because you acces only one element at a known position. The functions bsort and qsort, however, can't use this technique, because they have to access the array at several indices and hence must be able to do the index calculation themselves.
Find me (well, "yet another" but suppose this parentheses never existed!) a bug in that compiler and I give you a free cookie!
The compiler is right. This
*(const char**)(((const char*)base)[i * size]);
Will type-compile to something like (syntax: expresion -> type)...
base -> const void*
(const char*)base -> (const char*)const void*
(((const char*)base)[i * size]) -> *(const char*)const void* -> const char // Here's the problem!
(const char**)(((const char*)base)[i * size]) -> (const char**)const char // Now, this is *not* good...
*(const char**)(((const char*)base)[i * size]) -> *(const char**)const char -> const char* // Well, we have now just perfectly dereferenced '~'...
Not very sane, isn't it?*
BTW: You don't give us enough information for me to provide a full solution to your problem. What are those structs you talk about?
Edit: May this help you (written according to comments)?
*(const char**)&(((const unsigned char*)base)[size * i])

Pointer Initialization to Iterate through Array

I have a function, where I have 2 void pointers (part of the specification), but I know they are char *. I want to iterate through the char arrays, so I tried to create some pointers to iterate through them. When I do the following, my program doesn't work:
int foo(void const * first, void const * second)
{
char const * firstIt = (const char*) first;
char const * secondIt = (const char*) second;
...
}
However, if I do:
int foo(void const * first, void const * second)
{
char const * firstIt = *(const char**) first;
char const * secondIt = *(const char**) second;
...
}
What is the difference between the two and why does the second one work? I don't know if I included enough detail, so if more information is needed I'd be happy to provide it.
If the second one works, this is because the void pointer that you indicate for the function can really be anything, and I am guessing that you are passing to the function the pointer of a pointer. For example, the following code works:
#include <stdio.h>
#include <stdlib.h>
int foo(void const * first, void const * second);
int goo(void const * first, void const * second);
int main () {
char * a, * b;
a = malloc (sizeof (char));
b = malloc (sizeof (char));
*a = 'z';
*b = 'x';
goo (&a, &b); /* critical line */
free (a);
free (b);
return 0;
}
int foo(void const * first, void const * second) {
char const * firstIt = (const char*) first;
char const * secondIt = (const char*) second;
printf ("%c %c", *firstIt, *secondIt);
return 1;
}
int goo(void const * first, void const * second) {
char const * firstIt = *(const char**) first;
char const * secondIt = *(const char**) second;
printf ("%c %c", *firstIt, *secondIt);
return 2;
}
However, for the above program to work with the function foo you need to replace the critical line with a call of the form:
foo (a, b);
Does the difference make sense? Did it solve your problem?
The first approach assumes the caller has passed a char * (const qualified in some way).
The second assumes the caller has passed a char ** (const qualified in some way).
If the second one works, that means your caller is passing a char **.
The reason the first wouldn't work is undefined behaviour. Having a pointer of one type, converting to another type, and dereferencing it as anything other than the original type gives undefined behaviour. A round trip via a void pointer doesn't change that.
That is why compilers complain about implicit conversions of one pointer type to another (except to and from void pointers).

Casting a const void * to a const char * in C

So I have a C function that goes like this:
int cmp (const void *a, const void* b)
return rot13cmp( (const char*)a, (const char*)b );
}
and rot13cmp is another function that takes two parameters of type const char *.
I pass this function into the compare parameter for the C qsort function but it doesn't seem to work.
However, if I instead cast the const void * variables by doing
return rot13cmp ( *(const char **)a, *(const char **)b );
the function then starts to work. I looked this up at SO but every source said that the first method of casting should work so I wanted to know why only the second one worked for me?
Edit: Here's the relevant code I have,
int cmp (const void *a, const void *b) {
return rot13cmp( (const char *)a, (const char *)b );
}
int rot13cmp (const char *a, const char *b) {
while (*a == *b && *a != '\n') {
a++;
b++;
}
if (*a == *b) { return 0; }
else if (*a == '\n') { return 1; }
else if (*b == '\n') { return 1; }
else { return rot13(*a) - rot13(*b);
}
and rot13 returns an int for the ASCII code of a letter rotated by 13 letters in the alphabet.
I called qsort by doing
qsort(words, word_count, sizeof(char*), cmp);
where words is an array of char** and word_count is an int. cmp is also just
qsort() calls the comparison function with pointers to the array elements that should be compared.
If your array contains const char*, that means the comparison function is called with pointers to those pointers, and you have to cast and dereference accordingly.
With (const char*)a you are interpreting the parameter as if it would be a pointer to const char. But it isn't. In reality it's a pointer to the const char* in the input array.
That's why (const char**)a is the correct cast, it interprets the parameter as a pointer to a const char*. To do string comparison you want that pointed-to const char*, which you access by dereferencing the casted value with *.
You can think of it as first correcting the type (by casting), and then accessing the pointed-to value (by dereferencing).
The difference between the two attempts is that the second case does an additional dereference. This is important since qsort() doesn't pass the const char* directly, but rather passes a pointer to it. So we have to look at the pointed-to value to find what we are looking for. By casting directly to const char* we just claim that the variable would contain such a pointer, which won't end well because that's not the case.

convert pointer to pointer to void pointer

When I'm learning to use qsort to sort an array of string, there is a question puzzled me.
For example, to sort the following s
char *s[] = {
"Amit",
"Garima",
"Gaurav",
"Vaibhav"
};
To use the qsort, you must provide a comparison function like the
following function cstring_cmp I guess in the qsort function, the type of parameter to be passed to the function cstring_cmp is char**. How to convert a char** to a void*? Why can we convert a char** to a void*?
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* return the negative of the normal comparison */
}
Your question seems a bit vague but I'll give it a go anyway. To answer how, you can convert any pointer type to any other pointer type in C by simply casting. To answer why, well that's how C is defined.
The qsort() function requires a function with the given prototype (with const void *) parameters. This is because qsort() is unaware of the actual data type you are sorting, and must use a consistent function prototype for the comparison callback. Your comparison callback is responsible for converting the const void * parameters to pointers to the actual types in your array, in your case const char **.
The example you provide is being setup to ask qsort() to sort an array of char pointers (char *). This comparator you're providing is given each 'pair' of items the algorithm needs, by address. two char pointers. the address qsort() uses is based on the root address you give it, adding size-bytes per "item". Since each "item" is a char*, the size of each item is, in fact, the size of a pointer.
I've modified the comparator to demonstrate what is being compared, and what the addresses are that are being passed in. you will see they are all increments off the base address of the array containing all the char *s.
char *mystrings[] =
{
"This",
"is",
"a",
"test",
"of",
"pointers",
"to",
"strings"
};
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
printf("%p:%s - %p:%s\n", a, *ia, b, *ib);
return -strcasecmp(*ia, *ib);
}
int main(int argc, char *argv[])
{
printf("Base address of our pointer array: %p\n\n", mystrings);
qsort(mystrings, sizeof(mystrings)/sizeof(mystrings[0]), sizeof(char*), cstring_cmp);
for (size_t i=0; i<sizeof(mystrings)/sizeof(mystrings[0]);i++)
printf("%s\n", mystrings[i]);
return 0;
}
produces the following output:
Base address of our pointer array: 0x100006240
0x100006240:This - 0x100006260:of
0x100006260:of - 0x100006278:strings
0x100006240:This - 0x100006278:strings
0x100006248:is - 0x100006240:strings
0x100006278:This - 0x100006240:strings
0x100006250:a - 0x100006240:strings
0x100006270:to - 0x100006240:strings
0x100006258:test - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006268:pointers - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006240:test - 0x100006248:This
0x100006248:test - 0x100006250:to
0x100006240:This - 0x100006248:to
0x100006260:of - 0x100006268:pointers
0x100006268:of - 0x100006270:a
0x100006270:a - 0x100006278:is
0x100006268:of - 0x100006270:is
to
This
test
strings
pointers
of
is
a
A even less visualized one:
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
But you can see , a and b are char **, and they are dereferenced and become char * and passed to strcasecmp.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
int main(){
char *s[] = { "Amit",
"Garima",
"Vaibhav",
"Gaurav"};
qsort(s, 4, sizeof(char *), cstring_cmp);
printf("%s\n%s\n%s\n%s\n", s[0], s[1], s[2], s[3]);
return 0;
}
Output:
Vaibhav
Gaurav
Garima
Amit
It is legal to cast any pointer to char * or void * because void * means a pointer to a memory (RAM or virtual) byte.

What are the various styles of defining a function returning a function pointer

I have one function:
int compare(char * c1, char * c2){
...
...
}
What are the various styles in which I can write a function int ret_compare(void * item) that returns a pointer to compare?
There are two main styles, one using a typedef and one not (with two variants of the typedef). Your comparator should take constant pointers, as below:
int compare(const char *c1, const char *c2) { ... }
// Raw definition of a function returning a pointer to a function that returns an int
// and takes two constant char pointers as arguments
int (*ret_compare1(void *item))(const char *, const char *)
{
// Unused argument - item
return compare;
}
// More usual typedef; a Comparator2 is a pointer to a function that returns an int
// and takes two constant char pointers as arguments
typedef int (*Comparator2)(const char *, const char *);
// And ret_compare2 is a function returning a Comparator2
Comparator2 ret_compare2(void *item)
{
// Unused argument - item
return compare;
}
// Less usual typedef; a Comparator3 is a function that returns an int
// and takes two constant char pointers as arguments
typedef int Comparator3(const char *, const char *);
// And ret_compare3 is a function returning a pointer to a Comparator3
Comparator3 *ret_compare3(void *item)
{
// Unused argument - item
return compare;
}
Note that these comparators cannot be used with bsearch() and qsort() (unless you use fairly gruesome casts) because those comparators are expected to take const void * arguments.
Note, too, that for comparing strings, as opposed to single characters, the function used by qsort() or bsearch() should be similar to:
int string_comparator(const void *v1, const void *v2)
{
const char *s1 = *(char **)v1;
const char *s2 = *(char **)v2;
return(strcmp(s1, s2));
}

Resources