我正在尝试以特定方式对结构进行排序。正如您在以下结构中所看到的,字段按product
名称排序。
a - $13.00
a.0|100 - $3.00
a.1|100 - $6.00
a.2|100 - $4.00
b - $25.00
b.0|100 - $2.00
b.1|100 - $10.00
b.2|100 - $13.00
我想知道如何按product
名称保留排序,但同时按price
对每个产品进行“子排序”。
这是我到目前为止所拥有的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st_ex {
char product[16];
float price;
};
int struct_cmp_by_product(const void *a, const void *b) {
struct st_ex *ia = (struct st_ex *)a;
struct st_ex *ib = (struct st_ex *)b;
return strcmp(ia->product, ib->product);
}
int main() {
struct st_ex structs[] = {
{"b", 25},
{"b.0|100", 2},
{"b.1|100", 10},
{"b.2|100", 13},
{"a", 13},
{"a.0|100", 3},
{"a.1|100", 6},
{"a.2|100", 4},
};
size_t structs_len = sizeof(structs) / sizeof(struct st_ex);
qsort(structs, structs_len, sizeof(struct st_ex), struct_cmp_by_product);
size_t i;
for(i=0; i<structs_len; i++)
printf("%8s - $%.2f\n", structs[i].product, structs[i].price);
return 0;
}
更新:按价格排序,但按名称分组。例如,b:25
&gt; a:13
b - $25.00
b.2|100 - $13.00
b.1|100 - $10.00
b.0|100 - $2.00
a - $13.00
a.1|100 - $6.00
a.2|100 - $4.00
a.0|100 - $3.00
答案 0 :(得分:0)
作业?有没有人在C中写这种东西了?
考虑一下您的目标是什么:如果产品名称不同,那么价格没有区别,所以您返回名称比较结果。
只有当产品名称与价格相同时才会这样。
所以两个问题需要修复。需要更多应用程序感知的strcmp(3)
替换,知道b
,b.0|100
和b.0|200
应该与产品“名称”进行比较。当然,在平等的情况下,有必要加上价格的比较。下面的代码取代了您的比较功能,并已经过测试。顺便说一句,如果你在普通的C中工作,你不需要在void *
之间转换转换。
int baseproductname(const char *a, const char *b) {
for(;;) {
int c = *a;
int d = *b;
if (c == '.')
c = 0;
if (d == '.')
d = 0;
if(c != d || !c || !d)
return c - d;
++a;
++b;
}
}
int productorder(const struct st_ex *a, const struct st_ex *b) {
int n = baseproductname(a->product, b->product);
printf("%s <=> %s is %d\n", a->product, b->product, n);
if (n)
return n;
if (a->price > b->price)
return -1;
return a->price < b->price;
}
int struct_cmp_by_product(const void *a, const void *b) {
return productorder(a, b);
}
答案 1 :(得分:0)
最简单的方法是修改struct_cmp_by_product
。不要进行strcmp
,而是比较产品名称(取决于您的产品名称可能需要在strcmp
成员的子字符串上使用product
多久)。
我宁愿在st_ex
类型中对这种区别进行编码,方法是保留两个成员,这些成员在合并后会给出实际的产品名称。
struct st_ex {
char product[ 4 ]; // product group
char subgroup[ 12 ]; // sub group
float price;
}
int struct_cmp_by_product(const void *a, const void *b) {
struct st_ex const *ia = a; // do not cast away const-ness!
struct st_ex const *ib = b;
int x = strcmp(ia->product, ib->product);
if (!x) {
return ia->price > ib->price;
}
return x;
}
答案 2 :(得分:0)
关键是能够识别产品名称。这当然取决于产品名称的格式。如果你在这里写的是精确的,那么它意味着.
之前的单词(如果有的话)。让我们一块一块地构建比较函数:
int struct_cmp_by_product(const void *a, const void *b) {
struct st_ex *ia = (struct st_ex *)a;
struct st_ex *ib = (struct st_ex *)b;
首先,我们必须找到.
发生的位置:
size_t len_a, len_b;
char *a_dot, *b_dot;
a_dot = strchr(ia->product, '.');
b_dor = strchr(ib->product, '.');
if (a_dot)
len_a = a_dot - ia->product;
else
len_a = strlen(ia->product);
if (b_dot)
len_b = b_dot - ib->product;
else
len_b = strlen(ib->product);
然后我们必须检查两个产品名称是否相等:
int res; /* define above */
if (len_a == len_b && strncmp(ia->product, ib->product, len_a) == 0)
{
/* then check for price */
}
else
return strcmp(ia->product, ib->product);
和比较价格的部分简单地给出:
if (ia->price < ib->price)
return -1;
if (ia->price > ib->price)
return 1;
return 0;
最后关闭功能:
}
注意:我可能缺少错误检查或输入错别字,请确保在使用之前了解代码。不要复制粘贴。
答案 3 :(得分:0)
int struct_cmp_by_product(const void *a, const void *b) {
struct st_ex *ia = (struct st_ex *)a;
struct st_ex *ib = (struct st_ex *)b;
int rc;
size_t len_a, len_b, len;
len_a = strcspn(ia->product, ".");
len_b = strcspn(ib->product, ".");
len = (len_a > len_b) ? len_a : len_b; /* assuming ascii */
rc = strncmp(ia->product, ib->product, len);
if (rc) return rc;
if (ia->price > ab-price) rc = 1;
else if (ia->price < ab-price) rc = -1;
return rc;
}
更新:strcmp() - &gt;&gt; strncmp +计算尺寸