如何用#define数组替换C语言函数调用?循环调用排序函数失效排查
问题出在哪?
C语言里字符串就是普通的字符集合,编译器不会把字符串里的内容当成可执行代码来跑。你定义的sorts数组只是存了几个写着函数调用的字符串,循环里的sorts[i]只是把这个字符串读出来而已,根本不会触发函数执行——这就相当于把函数调用的写法写在记事本里,指望打开记事本它就自动运行,显然不可能。
另外C本身也没有内置的“把字符串转成代码执行”的能力,这种操作属于动态编译,复杂且完全没必要用在这场景里。
正确的实现方式:用函数指针数组
要在循环里批量调用不同排序函数,用函数指针数组才是正解,函数指针能存函数的地址,直接通过指针就能调用对应的函数。
第一步:统一函数接口
你的几个排序函数参数格式不一样:
bubbleSort、insertionSort、selectionSort是(数组, 长度)quickSort、mergeSort是(数组, 起始索引, 结束索引)
得把它们的接口统一,最简单的办法是给后两个写个包装函数:
// 包装quickSort,适配(数组, 长度)的接口 void quickSortWrapper(int arr[], int size) { quickSort(arr, 0, size - 1); } // 包装mergeSort,适配统一接口 void mergeSortWrapper(int arr[], int size) { mergeSort(arr, 0, size); }
第二步:定义函数指针数组
先声明函数指针的类型,再把各个排序函数(包括包装后的)的地址存进数组:
// 定义函数指针类型:接收int数组和int长度,无返回值 typedef void (*SortFunc)(int[], int); // 把各个排序函数的地址存到数组里 SortFunc sorts[] = {bubbleSort, quickSortWrapper, insertionSort, selectionSort, mergeSortWrapper}; // 计算排序函数的数量,不用手动写NUMBER_OF_SORTS #define NUMBER_OF_SORTS (sizeof(sorts) / sizeof(sorts[0]))
第三步:循环调用函数
现在就能在循环里直接调用了,记得每次调用前要复制原数组——不然第一个算法把数组排好序后,后面的算法拿到的都是有序数组,对比就没意义了:
for(int i = 0; i < NUMBER_OF_SORTS; ++i) { // 复制原数组到临时数组,避免修改原数据 int tempArr[size]; memcpy(tempArr, arr, sizeof(tempArr)); // 通过函数指针调用排序函数 sorts[i](tempArr, size); // 这里可以加计时、验证排序结果的代码,用来对比各个算法 }
不想写包装函数?也有办法(不推荐)
如果不想写包装函数,可以用支持可变参数的函数指针,但调用时得手动给每个函数传对应参数,容易出错,维护起来麻烦:
// 定义支持可变参数的函数指针类型 typedef void (*SortFuncVar)(int[], int, ...); SortFuncVar sorts[] = { (SortFuncVar)bubbleSort, (SortFuncVar)quickSort, (SortFuncVar)insertionSort, (SortFuncVar)selectionSort, (SortFuncVar)mergeSort }; // 循环调用时手动处理每个函数的参数 for(int i = 0; i < NUMBER_OF_SORTS; ++i) { int tempArr[size]; memcpy(tempArr, arr, sizeof(tempArr)); switch(i) { case 0: sorts[i](tempArr, size); break; case 1: sorts[i](tempArr, 0, size-1); break; case 2: sorts[i](tempArr, size); break; case 3: sorts[i](tempArr, size); break; case 4: sorts[i](tempArr, 0, size); break; } }
内容的提问来源于stack exchange,提问作者vabalas
相关产品推荐
相关产品推荐

