Reuse comparison function - c

I have builded a binary tree using an AVL and then data is packed in an array
typedef struct {
void **data;
int count;
} t_table;
The comparison function looks like:
int cmp(const void *pa, const void *pb)
{
int a = *(int *)pa;
int b = *(int *)pb;
if (a > b)
return +1;
else
if (b > a)
return -1;
else
return 0;
}
I am inserting in avl-tree and sorting the array of pointers using K&R qsort without problems.
Now I want to use the sandard function qsort of <stdlib.h> but I am forced to use a new function for t_table (due to pointer conversion required by qsort), it looks like:
int cmp(const void *pa, const void *pb)
{
int a = *(int*)(*(void**)pa);
int b = *(int*)(*(void**)pb);
if (a > b)
return +1;
else
if (b > a)
return -1;
else
return 0;
}
I understand why the function must be changed (quoting C-FAQ):
To understand why the curious pointer conversions in a qsort
comparison function are necessary (and why a cast of the function
pointer when calling qsort can't help), it's useful to think about how
qsort works. qsort doesn't know anything about the type or
representation of the data being sorted: it just shuffles around
little chunks of memory. (All it knows about the chunks is their size,
which you specify in qsort's third argument.) To determine whether two
chunks need swapping, qsort calls your comparison function. (To swap
them, it uses the equivalent of memcpy.)
But I wonder if there is any alternative (using stdlib qsort) to avoid having to maintain two comparison functions (one for avl and another for void **)

I'm not sure if you can really avoid to maintain these 2 functions, but you can do something like this:
int cmp_int(const void *pa, const void *pb)
{
int a = *(int *)pa;
int b = *(int *)pb;
return cmp(a, b);
}
int cmp_voidp(const void *pa, const void *pb)
{
int a = *(int*)(*(void**)pa);
int b = *(int*)(*(void**)pb);
return cmp(a, b);
}
static int cmp(const int a, const int b)
{
if (a > b)
return +1;
else
if (b > a)
return -1;
else
return 0;
}
You have 3 functions, but you don't repeat yourself and it's more easy to maintain.
EDIT: Like Sergey L. said, if you're using C99, cmp could be a static inline function.

You can't use exactly the same function, but you can define the second in terms of the first:
int cmp2(const void *pa, const void *pb)
{
return cmp(*(void **)pa, *(void **)pb);
}

Related

C: Check if array includes consecutive elements that are equal

Yesterday I had a test on C where I coudn't figure out the last question:
We were given two arrays of two types of arrays: arrays including consecutive elements that are equal(eg: {"stack","heap","heap"}) and arrays of where no consecutive elements where equal (eg: {1,2,3,4,5,6,7,8,9}).
We were then asked to find one function that returned 1 or 0 if the given array contained doubles or not. So this function had to work with both integer arrays and char * arrays.
This is what I came up with today (but it keeps giving the wrong answer and crashing afterwards or a segmentation fault when comparing the strings)
Edit: correct code (thanks to #BLUEPIXY !)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int contains_dup(void *array, size_t size, size_t sizeoftype, int (*cmp)(const void*, const void*)){
//array != NULL, size != 0
char *obj = array;
size_t i;
for(i = 0; i < size-1; ++i){
if(cmp(obj + sizeoftype * i, obj + sizeoftype * (i+1)))
return 1;
}
return 0;
}
int eqi(const void *a, const void *b){
int x = *(const int *)a;
int y = *(const int *)b;
return x == y;
}
int eqs(const void *a, const void *b){
return strcmp(a, b) == 0;
}
#define TEST(name, cmp)\
do{\
int test;\
puts(#name ":");\
test = contains_dup(name, sizeof(name)/sizeof(*name), sizeof(*name), cmp);\
test ? puts("doubles? Yes\n") : puts("doubles? No\n");\
}while(0)\
/**/
int main(void){
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[] = {0,1,2,3,4,5,6,7,8};
char *strings_yes[]={"heap","stack","stack","overflow"};
char *strings_no[] ={"heap","stack","heap","stack","overflow"};
puts("test:");
TEST(ints_yes, eqi);
TEST(ints_no, eqi);
TEST(strings_yes, eqs);
TEST(strings_no, eqs);
return 0;
}
Wrong old code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int array_contains_doubles(void ** array, int size, int sizeoftype){
int i;
char **out =(char**) malloc(size * sizeof(char*));
for(i=0;i<size;i++){ //trying to convert the array of ints to an
out[i] = array+i*sizeoftype; //array of char * eg: {1,2} ->{"1","2"}
// *out[i] +='a';
printf("%c\n",*out[i]);
}
out[i]= NULL;
while(*(out+1)!=NULL){
if(strcmp(*out,*(out++))==0){ //<- where i get the segmentation error
return 1;
}
}
return 0;
}
int main(void){
int i;
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[]={0,1,2,3,4,5,6,7,8};
char * strings_yes[]={"heap","stack","stack","overflow"};
char * strings_no[]={"heap","stack","heap","stack","overflow"};
int test = array_contains_doubles((void **) ints_no,
sizeof(ints_no)/sizeof(ints_no[0]), sizeof(int));
(test) ? (printf("doubles? Yes")) : (printf("doubles? No"));
}
Sorry for any spelling mistakes, english is not my native language.
What your teacher is likely fishing for, is for you to implement a "functor" similar to the function pointer passed to bsearch (study this function). Something along the lines of this:
typedef int comp_func_t (const void*, const void*);
bool equal (const void* obj1, const void* obj2, comp_func_t* comp)
{
return comp(obj1, obj2)==0;
}
You call equal from your application with a pointer to the objects to compare, no matter what kind of objects they are. The function pointer specifies how objects of this type should be compared. You then implement the comparison functions for each type:
int comp_int (const void* obj1, const void* obj2)
{
int a = *(const int*)obj1;
int b = *(const int*)obj2;
if(a < b)
{
return -1;
}
else if(a > b)
{
return 1;
}
else // a == b
{
return 0;
}
}
int comp_str (const void* obj1, const void* obj2)
{
...
}
Typical use could be:
int x;
int y;
...
if(equal(&x, &y, comp_int))
{
...
}
Now this only compares two objects, so you'll have to expand this for an array by 1) sorting the array and 2) calling it for every two adjacent items in the sorted array, to find out if any are equal.
The above is the old, "de facto standard" way to implement type-specific behavior in C. In newer versions of the language, more elegant ways are available through the _Generic keyword, but this would probably not be addressed on a beginner-level class.

Use case of function pointers in c

One of the common use cases I've come across when I read about function pointers is that they can be used to make a function more flexible, as part of the functionality of the function can be taken in as a parameter. An example for this is qsort where I can make a compare function to decide what is meant by greater and lesser (ascending, descending, is a multiple of,etc) and pass the compare funtion pointer to qsort function.
Here, the function repeat has addptr as parameter and therefore performs multiplication.
int add(int a, int b)
{
return a+b;
}
int (*addptr)(int,int);
int repeat(int a,int b,int (*funcptr)(int,int))
{
int i,ans=0;
for(i=0;i<a;i++)
{
ans=(*funcptr)(ans,b);
}
return ans;
}
int main()
{
addptr=&add;
printf("%d\n",repeat(7,5,addptr));
return 0;
}
But the same exact thing can be done without function pointers at all!
int add(int a, int b)
{
return a+b;
}
int repeat(int a,int b,int func(int,int))
{
int i,ans=0;
for(i=0;i<a;i++)
{
ans=func(ans,b);
}
return ans;
}
int main()
{
printf("%d\n",repeat(7,5,add));
return 0;
}
So why is this even one of the uses of function pointers?
What is the advantage of the first code over the second?
There is a rule C11 6.7.6.3/8 saying that if you write a function inside a parameter list, it will get adjusted to a pointer to function of that type:
A declaration of a parameter as ‘‘function returning type’’ shall be
adjusted to ‘‘pointer to function returning type’’,
This works similar to when you write an array as function parameter, it gets adjusted to a pointer to the first element.
That being said, it is not really meaningful to write a function as a parameter, it is just very confusing to the reader. Use function pointers instead.
EDIT
For maximum readability, I would personally recommend using this style:
typedef int operation_t (int, int);
int repeat (int a, int b, operation_t* operation)
{ ...
Though the most commonly used style is perhaps this one:
typedef int (*operation_t) (int, int);
int repeat (int a, int b, operation_t operation)
{ ...
I prefer the former since hiding pointers behind typedefs is a bad idea, and since that style makes function pointers consistent with regular pointers.
As noticed in comment by #user2390668, func in repeat in already a function pointer. And when you call it, add decays to a function pointer.
If your question is what is a possible use case for a variable holding a function pointer, we must try to imagine a use case where a function will not only be passed as a parameter, but will have to be stored. An example for that would be simulating polymorphism of structs in C. Here is an oversimplified example:
#include <stdio.h>
struct Base {
/* common member variables
...
*/
const char *name;
void (*display)(void *, FILE *fd);
};
struct S1 {
struct Base base;
/* other member variables */
};
void _S1_display(void *this, FILE *fd) {
struct S1 *s1 = this;
fprintf(fd, "In S1, name: %s\n", s1->base.name);
}
struct S2 {
struct Base base;
/* other member variables */
};
void _S2_display(void *this, FILE *fd) {
struct S2 *s2 = this;
fprintf(fd, "In S1, name: %s\n", s2->base.name);
}
void process(void *this, FILE *fd) {
struct Base *base = this; /* valid because base is first element of both S1 and S2 */
base->display(this, fd);
}
int main() {
struct S1 s1 = { "s1", &_S1_display };
struct S2 s2 = { "s2", &_S2_display };
process(&s1, stdout);
process(&s2, stdout);
return 0;
}
Ok, fur such a simply example, polymorphism would not be necessary, but as I said it is oversimplified...
You may use pointers to functions when you need a little more abstraction.
For example, you may want to manage a table of operators that a generic function should use:
int add(int a, int b) {
return a+b;
}
int sub(int a, int b) {
return a-b;
}
int mult(int a, int b) {
return a*b;
}
int div(int a, int b) {
return a/b;
}
void doit(int a,int b,int (*ptr[2])(int,int)) {
printf("%d\n",ptr[0](a,b));
printf("%d\n",ptr[1](a,b));
}
int main() {
int (*ptr[2])(int,int);
printf("additives (1) or multiplicatives (2) ?");
int choice;
scanf("%d",&choice);
switch(choice) {
case 1:
ptr[0] = &add;
ptr[1] = ⊂
break;
default:
ptr[0] = &mult;
ptr[1] = &div;
break;
}
doit(7,5,ptr);
return 0;
}
Of course you can also design a doit function with two pointers but sometimes a table is more convenient (think about a variable length table of function pointers for example, I know even in this case we may use a variable arguments list...).
At least, passing a function pointer in parameter is defining a function pointer variable...
Another example is also implementing in C object oriented programming, where you may implement methods as function pointers members.

How can I cast a const void* to a struct element?

I have my comparison function to use in qsort() like this:
int compar(const void *p, const void *q){
interval a,b;
*p = (interval)a
*q = (interval)b;
if(a.extrem[1] < b.extrem[0])
return -1;
if(b.extrem[1] < a.extrem[0] )
return 1;
return 0;
}
My structure is as follows:
typedef struct interval{
double extrem[2];
} interval;
I've tried many variations of "casting" in function compar, which all failed. My question, as it is apparent, how can I cast a const void* to my struct element? I know it seems to be a very basic question but I could not find a clear answer anywhere, also I'm new to this. Any help is gladly appreciated.
You were close...
typedef struct interval {
double extrem[2];
} interval;
int compar(const void *p, const void *q) {
const interval *a = p, *b = q;
if(a->extrem[1] < b->extrem[0])
return -1;
if(b->extrem[1] < a->extrem[0])
return 1;
return 0;
}
BTW, without a single cast, this will be perfectly clean under gcc -Wall.
Update... Tavian makes a good point, this is not a transitive ordering, so your set technically has no partial order. But depending on your data and your objective, qsort may return a useful result even so.
The qsort() function is going to call your callback with pointers to the elements.
Assuming the array is an actual array of interval, not one of interval pointers, you'd do:
static int interval_compare(const void *a, const void *b)
{
const interval *ia = a, *ib = b;
if(ia->extrem[1] < ib->extrem[0]) return -1;
return ib->extrem[1] > ia->extrem[0];
}
I don't understand the extrem indexes, but that's what you used. No casts are necessary when converting void * to a more specific type. See this answer.

Sorting structure with C qsort()

Having trouble getting my head around implementing the qsort() built into C to sort an array of structs by a stored int value (hitCount).
My struct:
typedef struct words {
const char *word;
int hitCount;
} words;
I'm trying to use the example given by Microsoft (http://support.microsoft.com/kb/73853).
So I've got at the top:
typedef int (*compfn)(const void*, const void*);
and the comparision method:
int compare (words *a, words *b) {
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
then within another method I call qsort with my array name and other details replacing the Microsoft example:
qsort((void *) &output, outputLength, sizeof(words), (compfn)compare);
This gives a segmentation fault.
I don't fully understand how to use qsort so I assume where I've adapted it from Microsoft's example I've done it incorrectly.
I hope I've included the mistake and can get some enlightenment as to what I should be doing in order for this to work correctly.
Many Thanks!
You have to pass the array not the address of the array to qsort.
qsort( output, ... );
Also your compare function must return an int and accept two const void* arguments.
Casting your function int compare (words *a, words *b) to a different( yet correct ) type which is then called by qsort() will cause undefined behaviour.
The compare function must be:
int compare (const void *a, const void *b)...
Then you cast a and b to correct types:
((words*)a)->hitCount < ((words*)b)->hitCount
I suspect that outputLength is computed incorrectly. A complete working example:
#include <stdio.h>
#include <stdlib.h>
typedef struct words {
const char *word;
int hitCount;
} words;
int compare(const void * left, const void * right) {
const words * a = (const words *) left;
const words * b = (const words *) right;
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
int main() {
struct words output[] = {
{ "hello", 314 },
{ "world", 42 },
{ "answer", 42 }
};
int outputLength = sizeof(output) / sizeof(output[0]);
int i;
output[0].word = "hello";
output[0].hitCount = 314;
output[1].word = "world";
output[1].hitCount = 42;
qsort(output, outputLength, sizeof(words), compare);
for (i = 0; i < outputLength; ++i) {
printf("%d %s\n", output[i].hitCount, output[i].word);
}
return 0;
}
The prototype of the standard library function qsort is
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Note the signature of the compare function. You cannot typecast a pointer to a function of different signature and make it work correctly. Therefore, typecasting your compare function will not work. It must have the same signature as declared in the prototype of qsort. Change your compare function to -
int compare(const void *a, const void *b) {
int c = ((words *) a)->hitCount;
int d = ((words *) b)->hitCount;
if(c > d) return -1;
if(c < d) return 1;
return 0;
}
The first argument base of qsort is the base address of the buffer which contains the elements to be sorted. Also, any pointer type is assignment compatible to a void * variable and as such you don't need to cast the base address. Therefore, you should call the qsort function as -
qsort(output, outputLength, sizeof output[0], compare);
Got it working with:
int compare (const void *a, const void *b) {
if (((words *)a)->hitCount > ((words *)b)->hitCount) {
return -1;
} else if (((words *)a)->hitCount < ((words *)b)->hitCount) {
return 1;
} else {
return 0;
}
}
and call to sort:
qsort(output, outputLength, sizeof(words), compare);
Thanks to everyone's help but majority credit to "self".

Is it possible to swap C functions?

Looking to see if anyone knows if its possible to swap C functions...?
void swap2(int(*a)(int), int(*b)(int)) {
int(*temp)(int) = a;
*a = *b;
*b = temp;
// Gives 'Non-object type 'int (int)' is not assignable
}
swap2(&funcA, &funcB);
EDIT
More data here as to intention -- Some answers have been provided below which do work such as creating the function ptr using typedef, pointing them to the functions and switching those, which lets you invoke the new swapped ptrs successfully.
BUT calling the functions by their original names after swapping shows no change. Essentially I'm looking for a c equivalent of the objc "swizzle".
I'm beginning to think this isn't possible, due to c's complete lack of reflection, and would require actually modifying the binary itself (obviously not feasible). D:
Comments welcome.
If you use the function pointers like below, it is yes
typedef int (*func_pt)(int);
func_pt a, b;
void swap(func_pt * a, func_pt * b)
{
func_pt tmp = *b;
*b = *a;
*a = tmp;
}
swap(&a, &b);
Or you use it as this, I think it is no:
int test1(int a)
{
return a;
}
int test2(int b)
{
return b;
}
swap(&test1, &test2);
Complete compiling working program
#include <stdio.h>
#include <stdlib.h>
typedef int (* func_pt)(int);
func_pt a, b;
int test1(int a)
{
printf("test1\n");
return 1;
}
int test2(int a)
{
printf("test2\n");
return 2;
}
void swap(func_pt * a, func_pt * b)
{
func_pt tmp = *b;
*b = *a;
*a = tmp;
}
int main(void)
{
a = &test1;
b = &test2;
printf("before\n");
a(1);
b(1);
swap(&a, &b);
printf("after\n");
a(1);
b(2);
return 0;
}
Output:
before
test1
test2
after
test2
test1
Some people do not try it by themselves, just say it absurd.So I give you a example.
I'm pretty sure you need pointers to function pointers to swap pointers, no? This type of swapping function swaps values; you really want to deal in addresses. The example function call wouldn't really work because C doesn't treat functions as first-class variables so you can't actually swap functions directly; you need to use pointers to function addresses, since addresses CAN be swapped:
void swap2(int(**a)(int), int(**b)(int)) {
int(*temp)(int) = *a;
*a = *b;
*b = *temp;
}
int(*func1)(int) = &foo;
int(*func2)(int) = &bar;
swap2(&func1, &func2);
Your code will give error like "invalid lvalue" at the time of assignment. As I can see in your code you are trying to swap pointers without changing its values so have a look on below solution.
void swap2(int(**a)(int), int(**b)(int)) {
int(*temp)(int) = *a;
*a = *b;
*b = temp;
}
int main(){
int(*temp1)(int) = &funcA;
int(*temp2)(int) = &funcB;
swap2(&temp1,&temp2);
}
Yes,you can. Think that a function-pointer is just a memory-address,the single requeriment is: where you will keep such address needs to be mutable. Say,int (*foo)() not really to where foo points to. May be to printf() or fopen().
Although the subject asks about swapping functions, you actually want to emulate what swizzle does. This just means you want to be able to call the same function name but have it do something different.
A pointer only solution will not give you that behavior. If that is not important to you, then you should adopt one of the function pointer only solutions provided. If it is important to you, then, you will need to introduce a layer of abstraction. The abstraction could use function pointers under the hood (although there are other solutions).
The API to users of this interface would be:
/* API to initialize */
void abstract_func_init ();
/* API to manipulate abstract functions */
typedef int abstract_func_type ();
abstract_func_type * abstract_func_get (abstract_func_type *key);
int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior);
/* the abstract functions */
extern int foo ();
extern int bar ();
The implementation of such an interface could look like:
static void insert (abstract_func_type *key, abstract_func_type **behavior)
{ /* associate key to behavior */ }
static abstract_func_type ** lookup (abstract_func_type *key)
{ /* return behavior from key */ }
abstract_func_type * abstract_func_get (abstract_func_type *k) {
abstract_func_type **f = lookup(k);
if (f) return *f;
return 0;
}
int abstract_func_set (abstract_func_type *k, abstract_func_type *p) {
abstract_func_type **f = lookup(k);
if (f) {
*f = p;
return 0;
}
return -ENOENT;
}
#define DEFINE_ABSTRACT_FUNC(func) \
static int static_##func (); \
static abstract_func_type *func##_ptr = static_##func; \
int func () { return func##_ptr(); } \
static int static_##func ()
DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); }
DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); }
void abstract_func_init () {
insert(foo, &foo_ptr);
insert(bar, &bar_ptr);
}
Then, the swap() you initially presented in your post could be implemented like this:
void swap (abstract_func_type *a, abstract_func_type *b) {
abstract_func_type *ap = abstract_func_get(a);
abstract_func_type *bp = abstract_func_get(b);
abstract_func_set(a, bp);
abstract_func_set(b, ap);
}
Here is a program that calls swap():
puts("before swap");
foo();
bar();
swap(foo, bar);
puts("after swap");
foo();
bar();
And its output would be:
before swap
foo
bar
after swap
bar
foo
To automate the adding of abstract functions into the lookup table, you could introduce into the build system an extra step that called a script that would grep out the DEFINE_ABSTRACT_FUNC lines, and generate a new source file that had a function with the calls to insert() for each such line.
A complete version of the mock-up can be found here.

Resources