The below program sorts all the suffices of a string using qsort() library function.
int sacomp(const void *a, const void *b)
{
return strcmp(*(const char**)a, *(const char**)b); <------------
}
void sort(string s)
{
int size = s.size();
char const *data = s.c_str();
char const **sa = new char const *[size+1];
for(int i = 0; i < size; i++)
sa[i] = data+i;
qsort(sa, size, sizeof(sa[0]), sacomp); // O(n * Lon n)
}
int main()
{
string s("ABCCCDEFABBABBA");
sort(s);
return 0;
}
I am not able to understand the casting done in the sacomp() method.
strcmp(*(const char**)a, *(const char**)b);
Why a is casted to const char** and then being de-referenced?
qsort passes pointer of elements. You passed sa as char**, so every element is char*, and qsort passes char**, finally you got char** in the sort function.
Your element is char *, therefore you should change void on char * and get pointer to char *, which is char **. Meanwhile strcmp needs char *.
Related
I'm refactoring a C++ application that refers to a bunch a multiple callback functions, each having a different number of arguments and I would like to know if there's a generic way to build a dedicated argument stack frame before calling each of them.
In other words: fetching all required arguments first according to function to be called, then perform a call that would be transparent for called function.
In a way, this is the opposite of a variadic function, as this would be a single function that knows it can receive different number of arguments. Here I have a bunch of immutable, regular functions and I'd like to call them from a generic hub.
I place both C and C++ tags here because I'm interested in propositions for both these languages, I have the feeling that what would work for C would also be applyable to C++ and I'm still open to "C++ only" solutions such as variadic templates or such.
The background of all of it is that quoted program is actually parsing a command line, then calling a function according to the name of the command, passed as first argument after program name, then all required ones as plain strings, but depending of invoked command.
I know I could write something like:
if(nb_of_args == 1)
my_callback_ptr(argv[n]);
else if (nb_of_args == 2)
my_callback_ptr(argv[n],argv[n+1]);
else if (nb_of_args == 3)
my_callback_ptr(argv[n],argv[n+1],argv[n+2]);
else if (nb_of_args == 4)
my_callback_ptr(argv[n],argv[n+1],argv[n+2],argv[n+3]);
else if…
…to restrict the compiled calls to the sole number of arguments regardless of the function itself, but I'd still like to do better.
Thanks in advance to everybody.
A viable approach is to implement dispatch table that will contain pointers to wrapper functions automatically passing appropriate amount of arguments to each callback.
#include <array>
#include <utility>
#include <cstddef>
template<auto x_p_callback, ::std::size_t... x_indexes>
void invoke_callback(char const * const * const pp_args, ::std::index_sequence<x_indexes...>)
{
(*x_p_callback)(pp_args[x_indexes]...);
}
template<typename x_Callback >
struct
t_ArgsCount;
template<typename x_Result, typename... x_Args>
struct
t_ArgsCount<x_Result (x_Args...)>
: ::std::integral_constant<::std::size_t, sizeof...(x_Args)>
{};
template<auto x_p_callback>
void callback_sunk(char const * const * const pp_args)
{
using
t_Callback = typename ::std::remove_reference<decltype(*x_p_callback)>::type;
using
t_Sequence = typename ::std::make_index_sequence<t_ArgsCount<t_Callback>::value>;
invoke_callback<x_p_callback>(pp_args, t_Sequence{});
}
using
t_Callback = void (char const * const * const pp_args);
template<auto... x_p_callbacks>
constexpr auto make_table(void)
{
return ::std::array<t_Callback *, sizeof...(x_p_callbacks)>{&callback_sunk<x_p_callbacks>...};
}
void my_callback_0() {}
void my_callback_1(char const *) {}
void my_callback_2(char const *, char const *) {}
void my_callback_3(char const *, char const *, char const *) {}
int main(int argc, char const * const * const pp_args)
{
constexpr auto table{make_table<my_callback_0, my_callback_1, my_callback_2, my_callback_3>()};
table.at(argc)(pp_args);
}
online compiler
Although I have some doubts about the C code I wrote (all to be verified). To solve the difficulty to convert your callbacks with a prototype like callback(int argc, char *argv[] (as the C/C++ main), my idea has been to make the pointers into the functions table that indexes the callbacks as pointers to variadic functions.
In this way we may call all callback functions passing the maximum number of parameters by means the pointers in the table. Obviously the called functions will only use the parameters they need and not the others.
On the other hand, this code will consume instructions and, depending on the case, even stack memory to pass useless parameters to functions that do not need them.
This code seems to run correctly, but it has to be verified!
#include <stdio.h>
#define CBCALL(cbidx, argv, n) \
ft[cbidx].f(argv[n],argv[n+1],argv[n+2],argv[n+3],argv[n+4])
int cb0();
int cb1(char *);
int cb2(char *, char *);
int cb3(char *, char *, char *);
int cb4(char *, char *, char *, char *);
int cb5(char *, char *, char *, char *, char *);
typedef int FN(char *,...);
struct table {
FN * f;
} ft[]={
{(FN *)cb0},
{(FN *)cb1},
{(FN *)cb2},
{(FN *)cb3},
{(FN *)cb4},
{(FN *)cb5}
};
int main(int argc, char * argv[])
{
if (argc<7) {
CBCALL(argc-1,argv,1);
if (argc>2)
{// Trying with copied parms and NULL.
char *xarg[5];
xarg[0]=argv[1];
xarg[1]=argv[2];
xarg[2]=NULL;
xarg[3]=NULL;
xarg[4]=NULL;
CBCALL(2,xarg,0);
}
} else {
printf("Max 5 parameters are allowed!\n");
}
return 0;
}
int cb0()
{
printf("No parms\n");
return 0;
}
int cb1(char *a)
{
printf("%s\n",a);
return 1;
}
int cb2(char *a, char *b)
{
printf("%s %s\n",a,b);
return 2;
}
int cb3(char *a, char *b, char *c)
{
printf("%s %s %s\n",a,b,c);
return 3;
}
int cb4(char *a, char *b, char *c, char *d)
{
printf("%s %s %s %s\n",a,b,c,d);
return 4;
}
int cb5(char *a, char *b, char *c, char *d, char *e)
{
printf("%s %s %s %s %s\n",a,b,c,d,e);
return 5;
}
I have couple of compare function that go something like this:
int greater_than_int(const void *a, const void *b) {
if (*(int *)a > *(int *)b) return 1;
return 0;
}
and a max function that goes like this:
const void* max(const void *base, size_t members, size_t size,
int (*compar)(const void *, const void *)) {
char *base_ptr = (char *) base;
char max = *base_ptr;
for(int i = 1; i < nmemb; i++) {
if (compar(&(*(base_ptr + i*size)), &max) != 0) {
max = *(base_ptr + i*size);
}
}
return &max;
}
When I try to run this function with greater_than_int I get nonsense results and since I'm still pretty new with C++ I'm not sure why. Any help would be appreciated.
Edit: I've changed some things to my code but now it always returns max as 0. Still trying to figure out why, I appreciate all the people saying that this isn't the best way to do this but, unfortunately, this is the way that I have to do this.
Since you're forced to work with those function signatures, here's one way of dealing with them.
// I suggest changing this to `bool`, but you can leave it as `int` if you must
bool greater_than_int(const void *a, const void *b) {
// no need for `if(...)` - just return the result of the comparison
return *static_cast<const int*>(a) > *static_cast<const int*>(b);
}
Then, the actual max function has some problems where you define max as a char and not a pointer etc. max can be left as a const void* since you don't need to perform any pointer arithmetics with it. I'm using base as the pointer to the maximum element below instead.
#include <iterator> // std::next, std::advance
const void* max(const void *base, size_t nmemb, size_t size,
bool (*compar)(const void*, const void*)) // note: bool here too
{
if(nmemb) {
// no need to cast away const:
auto current = static_cast<const char*>(base);
auto end = std::next(current, nmemb * size);
for(std::advance(current, size); current != end;
std::advance(current, size))
{
if(compar(current, base)) base = current;
}
}
return base;
}
Demo
I have no idea on how to look this up, even the title is confusing, even I am confused about what I'm looking for, and the question has for sure already been asked but it's so specific to be found, so here a bit of context:
int comparison(const int* a, const int* b) {
return *a - *b;
}
int main(int argc, char const *argv[])
{
int arr[3] = {1,6,-2};
qsort(arr,3,sizeof(int),comparison);
return 0;
}
Well, it does work, but the compiler gives me a warning, because qsort wants a function of type:
int(*)(const void*, const void*)
and comparison is a function of type:
int(*)(const int*, const int*)
I want to know why the compiler is not happy because it just has to cast the address. It should even be happy to give a type to a void* pointer. Is this really bad? Like an undefined behavior or something? Or just the compiler whining about nothing much?
After other reasons already given, there's another one. Historically there were platforms for which void * and int * had different bit arrangements, I've heard rumor of one where void * and int * were different sizes. That function pointer cast won't always work.
const int *ia = (const int *)a;
const int *ib = (const int *)b;
might not compile away to ia = a; but rather to something like ia = a >> 1; So there's really got to be a place for those instructions to be.
why he (the compiler) is not happy .
qsort() expects a function point of type int (*)(const void *a, const void *b), not int (*)(const int *a, const int *b). The compiler could guess its OK and beform a cast, yet it is more productive for the compiler to warn about such problems.
Or just the compiler whining about nothing much?
By warming you, you are allowed to determine the degree of the problem.
In addition to #Alex Reynolds good answer, note that *a - *b may overflow, resulting in the wrong comparison.
Instead:
int comparison(const void *a, const void *b) {
const int *ia = (const int *)a;
const int *ib = (const int *)b;
return (*ia > *ab) - (*ia < *ib);
}
Good compilers recognize the (p>q) - (p<q) idiom and emit efficient code.
The qsort function takes as one of its arguments a function of a type you are not passing. So you'll need to change that.
Inside the comparator, you can recast the pointers to the desired type.
Additionally, you need to dereference the values of the const int pointers you are passing into the comparator function:
#include <stdio.h>
#include <stdlib.h>
static int
comparator(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
static void
printArr(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i) {
printf("%d ", arr[i]);
}
}
int
main(int argc, const char **argv)
{
int arr[3] = {1, 6, -2};
qsort(arr, 3, sizeof(int), comparator);
printArr(arr, 3);
return EXIT_SUCCESS;
}
I have tried to solve an exercise from a book but I failed on the static_cast. I used the qsort Method from cstdlib. I have to cast the parameters of my function to a C-String (const char*). But I always get the error message: stattic_cast from type 'const void*' to type 'const char**' casts away qualifiers.
int scmp(const void *s1, const void *s2) {
const char *c1 = (static_cast<const char**>(s1));
const char *c2 = (static_cast<const char**>(s2));
....
}
const char *sfield[] = {"one", "two", "three", "four", "five"};
qsort(sfield, 10, 4, scmp);
The solution is as follows
const char *c1 = *(static_cast<const char* const*>(s1));
What is the reason for the last const and where does it come from? Why I have to cast to a pointer to a constant pointer to char const?
It comes from the origin pointer. static_cast may not discard the const qualifier. So you can only cast void const* to a T const*.
Now, it just so happens that your T is a char const*. You were probably led astray by the leading const in your original code. It does not apply where one may think it applied.
The qsort comparator parameters are pointers to const versions of the elements being compared. In your example the elements being compared are const char *, so a pointer to const of that is const char * const *. Hence the correct version of the code:
int scmp(const void *s1, const void *s2)
{
auto pc1 = static_cast<const char * const *>(s1);
auto pc2 = static_cast<const char * const *>(s2);
char const *c1 = *pc1;
char const *c2 = *pc2;
return strcmp(c1, c2); // or whatever
}
You can do away with pc1, pc2 and apply * operator to the result of the cast if you like .
Perhaps you mistakenly assumed the arguments were the elements being compared, when in fact they are pointers to the elements being compared .
If it is still not clear then maybe it would help to use a symbolic name for the element type:
using ELEMENT_T = const char *;
int scmp(void const *s1, void const *s2)
{
auto pc1 = static_cast<ELEMENT_T const *>(s1);
auto pc2 = static_cast<ELEMENT_T const *>(s2);
ELEMENT_T c1 = *pc1;
ELEMENT_T c2 = *pc2;
return strcmp(c1, c2); // or whatever
}
The same pattern would work for elements that are not pointers (e.g. integer elements).
I want to use the STL's Map container to lookup a pointer by using binary data as a key so I wrote this custom function object:
struct my_cmp
{
bool operator() (unsigned char * const &a, unsigned char * const &b)
{
return (memcmp(a,b,4)<0) ? true : false;
}
};
And using it like this:
map<unsigned char *, void *, my_cmp> mymap;
This compiles and seems to work, but I'm not sure what an "unsigned char * const &" type is and why it didn't work with just "unsigned char *"?
You need to provide a comparator that guarantees non-modifying of the passed values, hence the const (note that it applies to the pointer not the char). As for the reference operator (&), you don't need it -- it's optional. This will also compile:
struct my_cmp
{
bool operator() (unsigned char * const a, unsigned char * const b)
{
return memcmp(a,b,4) < 0;
}
};
It works for me with just unsigned char *.