简体   繁体   English

将函数转换为通用 void 指针作为函数参数

[英]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.我必须将接收 int 数组、将值与常量进行比较并返回值与 const 不同的数组的函数转换为可以接收任何类型数组的通用函数。 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.为此,我使用了 void 指针,但是在获取正确输出时遇到了一些问题,并且数组的重新分配也存在一些问题。

#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 .qsortqsort_r获取灵感。 free memory. free内存。 Handle errors.处理错误。

Translated 1:1 your function with an additional size parameter that means size of one array element.翻译 1:1 您的函数,并带有一个额外的size参数,这意味着一个数组元素的大小。

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 .代码打印0 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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