C qsort与非全局查找表进行比较

时间:2016-01-20 10:35:16

标签: c lookup-tables qsort

我正在尝试重构一个当前独立的C程序的实用程序,这样我就可以创建一个可重用的库。它包括一个数组的排序步骤,根据全局数组中的相应值。

// Global lookup table
double *rating;

// Comparator using lookup
int comp_by_rating(const void *a, const void *b) {
  int * x = (int *) a;
  int * y = (int *) b;
  if (rating[*x] > rating[*y])
    return 1;
  else if (rating[*x] < rating[*y])
    return -1;
  else
    return 0;
}

int main() {
  int* myarray;
  // ...
  // initialize values of local myarray and global rating
  // ...

  qsort(myarray, length_myarray, sizeof(int), comp_by_rating);
  // ...
  return 0;
}

我有办法避免将rating查找表全局化吗?我传统上是一个C ++人,所以我的第一个想法是一个算子,但我必须留在C中,所以我想我是无算子的。我也无法用保存每个项目的评级的结构数组替换int *myarray,因为其他代码需要以当前形式的数组。我还有其他选择吗?

3 个答案:

答案 0 :(得分:3)

  

我也无法用保存每个项目评级的结构数组替换int *myarray,因为其他代码需要当前形式的数组。

您可以临时替换排序,调用qsort,然后将结果收回原始数组:

struct rated_int {
    int n;
    double r;
};

struct rated_int *tmp = malloc(length_myarray * sizeof(struct rated_int));
for (int i = 0 ; i != length_myarray ; i++) {
    tmp[i].n = myarray[i];
    tmp[i].r = ratings[myarray[i]];
}
qsort(tmp, length_myarray, sizeof(struct rated_int), comp_struct);
for (int i = 0 ; i != length_myarray ; i++) {
    myarray[i] = tmp[i].n;
}
free(tmp);

这样,其余代码会将myarray视为整数数组。

答案 1 :(得分:1)

你是如何在C中滚动的。如果你担心线程安全,可以考虑使用线程局部变量,所以多个线程有不同的副本:

static _Thread_local double *rating;

旧版编译器不支持此功能,而是需要某种portability kludge。如果您也不喜欢这样,那么您就无法编写自己的排序例程来提供额外的参数。

gcc提供nested functions作为解决此问题的扩展,但它们还有其他问题,即它们需要一个可执行堆栈,这会降低程序对错误的抵御能力。

答案 2 :(得分:0)

不,数组评级不必是全局的:您可以在此使用static

int comp_by_rating(const void *a, const void *b) {
    static double *rating = { .. init here .. };

如果成员是非常数,则初始化它的替代方法:

int comp_by_rating(const void *a, const void *b) {
    static double *rating = NULL;
    if (!rating) {
        // Initialize rating here
    }
}