如何实现支持int、float、C字符串的C语言通用冒泡排序?
修复通用冒泡排序实现的问题
原代码中的核心问题
- 参数类型错误:
bubbleSort的第一个参数是void* arr[](void指针数组),但通用排序应该接收单个void*指向数组起始地址,这样才能处理任意类型的连续数组。 - 比较逻辑错误: 直接比较元素地址
&arr[j] > &arr[j+1]毫无意义,我们需要根据元素类型的值进行比较,因此必须传入一个自定义比较函数。 - 元素访问错误: 对于
void*类型的数组,不能直接用下标访问,需要通过char*转换后按元素大小计算偏移量来获取元素地址。 - 打印方式错误:
printf(&arr[i])不符合printf的调用规范,且无法通用打印不同类型的元素,应该在排序完成后根据类型单独处理打印。 - 主函数数组声明错误:
int* arr[] = {0,1,...}是指针数组,这里的整数值会被当作指针地址(比如0是NULL指针),应该声明为普通的int数组。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stdbool.h> void swapG(void* a, void* b, int elemSize) { void* temp = malloc(elemSize); assert(temp != NULL); memcpy(temp, a, elemSize); memcpy(a, b, elemSize); memcpy(b, temp, elemSize); free(temp); } // 比较函数指针类型:返回值 <0 表示a<b,=0表示相等,>0表示a>b typedef int (*CompareFunc)(const void* a, const void* b); void bubbleSort(void* arr, int n, int elemSize, CompareFunc compare) { int i, j; bool swapped; // 将void*转换为char*以便按字节计算偏移 char* arrBytes = (char*)arr; for (i = 0; i < n - 1; i++) { swapped = false; for (j = 0; j < n - i - 1; j++) { // 获取第j个和j+1个元素的地址 void* elemJ = arrBytes + j * elemSize; void* elemJ1 = arrBytes + (j+1)*elemSize; if (compare(elemJ, elemJ1) > 0) { swapG(elemJ, elemJ1, elemSize); swapped = true; } } if (!swapped) break; } } // 针对不同类型的比较函数 int compareInt(const void* a, const void* b) { return *(const int*)a - *(const int*)b; } int compareFloat(const void* a, const void* b) { float diff = *(const float*)a - *(const float*)b; return diff > 0 ? 1 : (diff < 0 ? -1 : 0); } int compareString(const void* a, const void* b) { return strcmp(*(const char**)a, *(const char**)b); } // 打印函数示例 void printIntArray(const int* arr, int n) { for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); } void printFloatArray(const float* arr, int n) { for (int i = 0; i < n; i++) { printf("%.2f ", arr[i]); } printf("\n"); } void printStringArray(const char** arr, int n) { for (int i = 0; i < n; i++) { printf("%s ", arr[i]); } printf("\n"); } int main() { // 测试int数组 int intArr[] = {0,1,4,6,9,10,13,7}; int nInt = sizeof(intArr)/sizeof(intArr[0]); bubbleSort(intArr, nInt, sizeof(int), compareInt); printf("排序后的int数组:"); printIntArray(intArr, nInt); // 测试float数组 float floatArr[] = {3.14, 1.59, 2.65, 0.78, 4.20}; int nFloat = sizeof(floatArr)/sizeof(floatArr[0]); bubbleSort(floatArr, nFloat, sizeof(float), compareFloat); printf("排序后的float数组:"); printFloatArray(floatArr, nFloat); // 测试字符串数组 const char* strArr[] = {"banana", "apple", "cherry", "date", "elderberry"}; int nStr = sizeof(strArr)/sizeof(strArr[0]); bubbleSort(strArr, nStr, sizeof(char*), compareString); printf("排序后的字符串数组:"); printStringArray(strArr, nStr); return 0; }
关键修复说明
- 引入比较函数: 通过
CompareFunc类型定义,让bubbleSort接收一个自定义比较函数,这样可以处理int、float、字符串等不同类型的比较逻辑。 - 正确的元素地址计算: 将
void* arr转换为char*,然后通过j * elemSize计算每个元素的偏移地址,确保能正确访问任意类型的数组元素。 - 修正数组传递: 在main中使用普通数组(而非指针数组),并将数组名直接传递给
bubbleSort(数组名会自动 decay 为指向首元素的指针)。 - 单独处理打印: 针对不同类型编写专用的打印函数,避免通用函数的复杂性,同时保证打印正确。
- 简化swapG: 去掉了不必要的
(char*)强制转换,malloc(elemSize)已经足够。
内容的提问来源于stack exchange,提问作者thedrooster
相关产品推荐
相关产品推荐

