I am slamming my head against the wall with this problem.
To summarize: I need to dynamically add strings to an array, sort them, and then check against another string value.
This needs to work on a SCADA-system that support C as a scripting language, but with limited functionality. I have qsort() available.
However, with the test code I have, I am not able to use qsort on an array, with values that are added dynamically.
To be clear, I can add strings to the array, which works fine. However when I call qsort() on that array, I can no longer print out the indices.
Heres is the code so far (be kind, I'm not very proficient in C):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cstring_cmp (const void *a, const void *b)
{
// This function is taken from an online example
const char **ia = (const char **) a;
const char **ib = (const char **) b;
return strcmp (*ia, *ib);
}
int main ()
{
//char *ArchiveKomponents[] = {"R1890L", "F1121D", "F1284Z", "A1238K"};
// If I do the above commented out, it works as intended
char ArchiveKomponents[100][20];
strcpy(ArchiveKomponents[0], "R1890L");
strcpy(ArchiveKomponents[1], "F1284Z");
size_t strLen = sizeof (ArchiveKomponents) / sizeof (char *);
printf ("Len: %zu\n", strLen);
printf ("Before [0]: %s\n", ArchiveKomponents[0]);
printf ("Before [1]: %s\n", ArchiveKomponents[1]);
qsort (ArchiveKomponents, (size_t)strLen, sizeof (char *), cstring_cmp);
printf ("After [0]: %s\n", ArchiveKomponents[0]);
printf ("After [1]: %s\n", ArchiveKomponents[1]);
// When run, the "After" prints are not even printed, the program simply halts
return 0;
}
I feel that I have googled the entire internet, in search of an answer on how to do this, with no luck.
Regards
CodePudding user response:
You are comparing incorrect types. The comparison functions treats 4 or 8 characters from the element as a pointer to a string. Dereferencing this pointer triggers Undefined Behavior, likely a crash.
Note, that the type of a single element is char[20]
not char*
. Therefore your comparison function could be simply implemented as:
int cstring_cmp (const void *a, const void *b)
{
return strcmp (a, b);
}
Pointers a
and b
points to arrays of 20 character. The address of array is the same as an address of its first element. So a
and b
can be used as pointers to chains of char
(aka "c-strings").
Moreover, void*
is automatically converted to any pointer type without casting.
The qsort
invocation should be:
qsort (ArchiveKomponents, // array to be sorted
2, // number of elements in the array
sizeof ArchiveKomponents[0], // size of a single element
cstring_cmp // comparison function
);