C qsort 与非全局查找比较 table
C qsort compare with non-global lookup table
我正在尝试重构一个目前是独立 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
查找 table 全局?我传统上是一个 C++ 人,所以我的第一个想法是仿函数,但我必须留在 C 中,所以我想我是无仿函数的。我也无法将 int *myarray
替换为包含每个项目评级的结构数组,因为其他代码需要当前形式的数组。我还有其他选择吗?
不,数组评分不必是全局的:您可以在此处使用static
:
int comp_by_rating(const void *a, const void *b) {
static double *rating = { .. init here .. };
如果成员是 non-constant:
,则使用另一种初始化方法
int comp_by_rating(const void *a, const void *b) {
static double *rating = NULL;
if (!rating) {
// Initialize rating here
}
}
这就是你在 C 中的方式。如果你担心 thread-safety,请考虑制作变量 thread-local,以便多个线程拥有它的不同副本:
static _Thread_local double *rating;
尽管旧编译器不支持此功能,但您需要某种 portability kludge。如果你也不喜欢这个,你就不能真正绕过编写自己的允许额外参数的排序例程。
gcc 提供 nested functions 作为解决这个问题的扩展,但它们还有其他问题,即它们需要一个可执行堆栈,这会降低程序对错误的弹性。
I also can't replace int *myarray
with an array of structs holding the rating for each item, since other code requires the array in its current form.
您可以临时替换排序,调用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
视为整数数组。
我正在尝试重构一个目前是独立 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
查找 table 全局?我传统上是一个 C++ 人,所以我的第一个想法是仿函数,但我必须留在 C 中,所以我想我是无仿函数的。我也无法将 int *myarray
替换为包含每个项目评级的结构数组,因为其他代码需要当前形式的数组。我还有其他选择吗?
不,数组评分不必是全局的:您可以在此处使用static
:
int comp_by_rating(const void *a, const void *b) {
static double *rating = { .. init here .. };
如果成员是 non-constant:
,则使用另一种初始化方法int comp_by_rating(const void *a, const void *b) {
static double *rating = NULL;
if (!rating) {
// Initialize rating here
}
}
这就是你在 C 中的方式。如果你担心 thread-safety,请考虑制作变量 thread-local,以便多个线程拥有它的不同副本:
static _Thread_local double *rating;
尽管旧编译器不支持此功能,但您需要某种 portability kludge。如果你也不喜欢这个,你就不能真正绕过编写自己的允许额外参数的排序例程。
gcc 提供 nested functions 作为解决这个问题的扩展,但它们还有其他问题,即它们需要一个可执行堆栈,这会降低程序对错误的弹性。
I also can't replace
int *myarray
with an array of structs holding the rating for each item, since other code requires the array in its current form.
您可以临时替换排序,调用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
视为整数数组。