C - Mixed Qsort with Struct (String and Double)
我有一个几乎完整的代码,需要Qsort一些东西,首先我有一个整数数组,一个浮点数组,然后我有一个带有char和double组合数组的struct。需要以某种方式对它们进行排序,但是我被卡住了。
这是我的代码,对整数和浮点数排序没有问题,但是我无法完成结构排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN 20 typedef struct product { double price; char name[LEN]; } product; int ComparFuncInt(const void *x, const void *y); int ConparFuncFloat(const void *x, const void *y); int ComparFuncStructName(const void *x, const void *y); int ComparFuncStructPrice(const void *x, const void *y); /* void PrintIntegerArray(int *numbers, int len); void PrintFloatArray(float *numbers, int len); void PrintStructArray(product *items, int len); */ int main(void) { unsigned option; /* initialized variables to be used with functions */ int numArr1[] = {15, 25, 3, 19, 22, 17, -54, 0, 9}; float numArr2[] = {76.40f, 11.2f, 235.4f, 76.50f, 341.6f}; product prices[] = {{0.75f,"Milk"}, {0.99f,"Yogurt"}, {3.19f,"Cucumber"}, {1.09f,"Orange"}, {0.80f,"Bread"}, {0.99f,"Juice"}}; int numCount = sizeof(numArr1) / sizeof(int); float floatCount = sizeof(numArr2) / sizeof(float); double doubleCount = sizeof(struct product) / sizeof(double); char charCount = sizeof(struct product) / sizeof(char); while (1) { printf("\ \ Select your action!\ \ "); printf("1. Sort integers (numArr1)\ "); printf("2. Sort decimals (numArr2)\ "); printf("3. Sort structures by price\ "); printf("4. Sort structures by name\ "); printf("0. Exit\ "); scanf("%u", &option); switch (option) { case 1: qsort(numArr1, (size_t)numCount, sizeof(int), ComparFuncInt); for (int i = 0; i < numCount; printf("%3d", numArr1[i]), i++); break; case 2: qsort(numArr2, (size_t)floatCount, sizeof(float), ConparFuncFloat); for (int j = 0; j < floatCount; printf("%.2f", numArr2[j]), j++); break; case 3: qsort(prices, (size_t)doubleCount, sizeof(double), ComparFuncStructPrice); for (int k = 0; k < doubleCount; printf("%.2f", prices[k].price), k++); break; case 4: qsort(prices, (size_t)charCount, sizeof(char), ComparFuncStructName); for (int l = 0; l < charCount; printf("%s", prices[l].name), l++); break; case 0: exit(1); break; default: printf("Only selections from 1 to 4 and 0 are accepted\ "); } } return EXIT_SUCCESS; } int ComparFuncInt(const void *x, const void *y){ if(* (int*)x > *(int*)y) return 1; else if(* (int*)x < *(int*)y) return -1; else return 0; } int ConparFuncFloat(const void *x, const void *y){ if(* (float *)x > *(float *)y) return 1; else if(* (float *)x < *(float *)y) return -1; else return 0; } int ComparFuncStructName(const void *x, const void *y){ const char *pa = *(const char**)x; const char *pb = *(const char**)y; return strcmp(pa,pb); } int ComparFuncStructPrice(const void *x, const void *y){ if(* (float *)x > *(float *)y) return 1; else if(* (float *)x < *(float *)y) return -1; else return 0; } |
我想这样做,因为当用户选择3时,它将按价格对产品下的PRICES数组进行排序,如果用户选择4,则应按名称进行排序,在两种情况下都应同时输出价格和名称,只是区别在于按其排序方式。
在比较函数中,指针(在您的情况下为
要访问结构的成员,您当然需要使用适当的指向结构的指针访问,例如箭头运算符
如果将指针保存在适当的变量中也很容易,这样您就不必一直进行所有转换。实际上,如果要使用传递的数据作为指针而不是值,则根本不需要强制转换,因为
因此对于您的结构比较功能,您可以执行例如
1 2 3 4 5 6 | int ComparFuncStructName(const void *x, const void *y){ const product *a = x; const product *b = y; return strcmp(a->name, b->name); } |
或者,当然,由于您要对结构数组进行排序,因此数组的元素大小就是结构的大小,因此您也需要修复该问题:
1 |
哦,您计算结构中元素的数量也是错误的。公式为
所以你需要做
1 | size_t charCount = sizeof prices / sizeof prices[0]; |
在不相关且更具风格上的注意事项:请勿将
将所有语句放在循环体中:
1 2 |
您也不需要为循环使用不同的迭代变量。它们对于它们自己范围内的循环而言是本地的,因此您可以为所有循环重用
更改此内容:
1 |
至:
1 |
因为结构数组只有一个大小,所以无论您要按名称还是按价格排序。而且,无论您要按名称还是按价格排序,数组每个元素的大小都等于该结构的大小。
类似于按名称排序的方式。
此外,您的比较功能是错误的。首先,您需要隐瞒指向结构的所有void指针。然后,您需要使用结构的相关字段进行比较。
为进行价格比较,请使用越来越少的运算符。如果简单地减去,将会得到错误的结果。
将所有内容放在一起(并丢弃非结构数组),您将得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN 20 typedef struct product { double price; char name[LEN]; } product; int ComparFuncStructName(const void *x, const void *y); int ComparFuncStructPrice(const void *x, const void *y); /* void PrintStructArray(product *items, int len); */ int main(void) { unsigned option; product prices[] = {{0.75f,"Milk"}, {0.99f,"Yogurt"}, {3.19f,"Cucumber"}, {1.09f,"Orange"}, {0.80f,"Bread"}, {0.99f,"Juice"}}; size_t pricesCount = sizeof prices / sizeof prices[0]; while (1) { printf("\ \ Select your action!\ \ "); printf("3. Sort structures by price\ "); printf("4. Sort structures by name\ "); printf("0. Exit\ "); scanf("%u", &option); switch (option) { case 3: qsort(prices, pricesCount, sizeof(prices[0]), ComparFuncStructPrice); for (size_t k = 0; k < pricesCount; printf("%f", prices[k].price), k++); break; case 4: qsort(prices, pricesCount, sizeof(prices[0]), ComparFuncStructName); for (size_t l = 0; l < pricesCount; printf("%s", prices[l].name), l++); break; case 0: exit(1); break; default: printf("Only selections from 1 to 4 and 0 are accepted\ "); } } return EXIT_SUCCESS; } int ComparFuncStructName(const void *x, const void *y){ const product* pa = (const product*) x; const product* pb = (const product*) y; return strcmp(pa->name, pb->name); } int ComparFuncStructPrice(const void *x, const void *y){ const product* pa = (const product*) x; const product* pb = (const product*) y; return (pa->price > pb->price) - (pa->price < pb->price); } |
输出(如果我选择按名称排序):
1 2 3 4 5 6 7 8 9 10 11 12 | Select your action! 3. Sort structures by price 4. Sort structures by name 0. Exit Bread Cucumber Juice Milk Orange Yogurt Select your action! 3. Sort structures by price 4. Sort structures by name 0. Exit |