简体   繁体   中英

Transform function to generic void pointer as function parameter

I have to transform a function that receives a int array, compares the values with a constant number and returns an array with the values that are different from that const, into a generic function that can receive any type of array. For that i'm using the void pointer, but i'm having some issues getting the correct output and also some problem with the realloc of the array.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ALG 0 

int f2(int * e) {
  return *e == ALG;
}

int * f1(int a[], size_t *size, int (*fin)(int * e)) {
  size_t i = *size;
  while(i--) {
    if(fin(&a[i])) {
      memmove(&a[i], &a[i+1], (--*size -i)*sizeof(int));
    }
  }
  return realloc(a, *size * sizeof (int));
} 

//generic type function
int * f1a(void *a, size_t *size, int (*fin)(int * e)) {
  size_t i = *size;
  while(i--) {
    int * x = (int*) a + i;
    if(fin(x)) {
      memmove(a + i, a + i + 1, (--*size -i)*sizeof(*a));
    }
  }
 return realloc(a, *size * sizeof (*a));
} 


int main(void) {

  int *a = malloc(8*sizeof(int));
  a[0] = 2; a[1] = -3; a[2] = 1; a[3] = 0; a[4] = 4; a[5] = 7; a[6] = 0; a[7] = 6;

  size_t i, size=8;
  printf("%zu\n", size);
  
  //int *res = f1(a, &size, f2); output : 2 -3 1 4 7 6
  
  int *res = f1a(a, &size, f2);

  for(i=0; i<size; i++) {
    printf("%d ", res[i]);
  }    
  
  return 0;
}

Can anyone help me please?

Thanks in advance!

Write readable code. Do one thing at a time. Name variables meaningful. Pass context to user callback functions. Take inspiration from qsort and qsort_r . free memory. Handle errors.

Translated 1:1 your function with an additional size parameter that means size of one array element.

void *filter_generic(
     void *base, size_t nmemb, size_t size,
     size_t *out_nmemb,
     int (*fin)(void* e, size_t size, void *cookie), void *cookie) {
   for (size_t i = nmemb; i--; ) {
      void *elempnt = (char*)base + (size * i);
      if (fin(elempnt, size, cookie)) {
            // the following is invalid and
            // results in out-of-bounds access
            memmove(
               (char*)base + (size * i),
               (char*)base + (size * (i + 1)),
               size * (nmemb - i)
            );
            nmemb -= 1;
       }
    }
    *out_nmemb = nmemb;
    return realloc(base, size * );
}

In this case, using two pointers or two indexes is just trivially simpler.

#include <stdlib.h>
#include <string.h>

int intpnt_compare_to_zero(void *elem, size_t size, void *cookie) {
    return *(int *)elem == 0;
}

/**
 * Filters array elements depending on function.
 * @param base like for qsort
 * @param nmemb like for qsort
 * @param size like for qsort
 * @param out_nmemb return new size of the array
 * @param compare comparison function
 * @param cookie cookie for compare
 * @return new allocate memory for array
 */
void *filter_generic(void *base, size_t nmemb, size_t size, size_t *out_nmemb,
             int (*compare)(void *e, size_t size, void *cookie), void *cookie) {
    void *out = base;
    void *in = base;
    void *const end = (char *)base + (size * nmemb);
    for (; in < end; in = (char *)in + size) {
        if (compare(in, size, cookie)) {
            memmove(out, in, size);
            out = (char *)out + size;
        }
    }
    const size_t new_nmemb = ((char *)out - (char *)base) / size;
    *out_nmemb = new_nmemb;
    return realloc(base, size * new_nmemb);
}

int main(void) {
    size_t size = 8;
    int *a = malloc(sizeof(*a) * size);
    a[0] = 2;
    a[1] = -3;
    a[2] = 1;
    a[3] = 0;
    a[4] = 4;
    a[5] = 7;
    a[6] = 0;
    a[7] = 6;

    int *res = filter_generic(a, size, sizeof(*a), &size, intpnt_compare_to_zero, NULL);
    for (size_t i = 0; i < size; ++i) {
        printf("%d%s", res[i], i + 1 == size ? "\n" : " ");
    }

    free(res);
}

The code prints 0 0 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM