1

继我之前的问题之后,我正在寻找一种方法来按类别组织以下结构,就像现在一样,但在组之间进行排序。

例如, GroupMeats大于 group Drinks,所以Meatsgroup 应该在 上面Drinks,依此类推。

到目前为止,我了解使用的部分qsort(),但不确定分组部分。这是我正在寻找的输出(我绝对愿意接受更好的方法)

                 Meats   -   43.00
         Meats,Chicken   -   27.00
            Meats,Beef   -   9.00
            Meats,Pork   -   4.00
          Meats,Turkey   -   3.00

                Drinks   -   33.00
         Drinks,Coffee   -   20.00
          Drinks,Pepsi   -   10.00
            Drinks,Tea   -   3.00

                Fruits   -   25.00
         Fruits,Grapes   -   13.00
          Fruits,Melon   -   10.00
          Fruits,Apple   -   2.00

工作代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct st_ex {
    char product[96];
    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;

    int p;
    char *iaa = ia->product, *ibb = ib->product;
    while (1) {
        int c = *iaa;
        int d = *ibb;
        if(c == ',') c = 0;
        if(d == ',') d = 0;
        if(c != d || !c || !d) {
            p = c - d; break;
        }
        ++iaa;
        ++ibb;
    }
    if (p) return p;
    return ia->price < ib->price;
}

int main() {
    struct st_ex structs[] = {
        {"Fruits", 25},
        {"Meats,Beef", 9},
        {"Fruits,Apple", 2},
        {"Meats,Chicken", 27},
        {"Fruits,Grapes", 13},
        {"Meats", 43},
        {"Fruits,Melon", 10},
        {"Meats,Pork", 4},
        {"Meats,Turkey", 3},
        {"Drinks,Tea", 3},
        {"Drinks,Coffee", 20},
        {"Drinks,Pepsi", 10},
        {"Drinks", 33},

    };
    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("%30s   -   %.2f\n", structs[i].product, structs[i].price);
    return 0;
}
4

2 回答 2

1

您可能需要更复杂的数据类型,以便您可以按价格和类别进行分组。此外,最简单的方法将需要两种排序(因此,您有两个排序功能)。就像是:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

struct category {
    char name[ 12 ];
    float price;
};

struct group {
    char name[ 12 ];
    float price;
    struct category cats[ 5 ]; // use a linked-list; this is for demo  
};

int cmp_by_group(const void *a, const void *b) {
    struct group const *ia = a;
    struct group const *ib = b;

    return (ia->price < ib->price);
}

int cmp_by_category(const void *a, const void *b) {
    struct category const *ia = a;
    struct category const *ib = b;

    return (ia->price < ib->price);
}

int main() {    
    struct group structs[] = {
        {"Fruits", 25, {{"Apple", 2}, {"Grapes", 13}, {"Melon", 10}}},
        {"Meats", 43, {{"Beef", 9}, {"Chicken", 27}, {"Pork", 4}, {"Turkey", 3}}},
        {"Drinks", 33, {{"Tea", 3}, {"Coffee", 20}, {"Pepsi", 10}}}
    };
    for (size_t i = 0; i < 3; ++i) {
        qsort(structs[ i ].cats, 3, sizeof(struct category), cmp_by_category);
    }

    size_t structs_len = sizeof(structs) / sizeof(struct group);
    qsort(structs, structs_len, sizeof(struct group), cmp_by_group);
    size_t i;
    for(i=0; i<structs_len; i++) {
        printf("%s   -   %.2f\n", structs[i].name, structs[i].price);
        for (size_t j = 0; j < 3; ++j)
            printf("%s,%s   -   %.2f\n", structs[i].name, structs[i].cats[ j ].name, structs[i].cats[ j ].price);
    }
    return 0;
}

(不过,您将需要修复理由部分。)

于 2012-06-12T02:23:03.327 回答
1

通常,您会在单个值之后而不是在它们之前打印组的聚合值,因为它更容易编程。因此,“肉类”的摘要行将出现在“肉类,Xxxx”的 4 个详细信息行之后。

由于您想按类别降序打印数据,我相信您将不得不对数据进行两次传递。在第 1 步中,您将累积不同类别(肉类、饮料、水果)的总和 (SUM)。在第 2 步中,您将根据两个标准对数据进行排序 - 类别的聚合,然后按类别内的价格。我希望对数据进行一些预处理,以便更容易排序,将类别分开。您还需要决定如何保留类别的 SUM。我认为您排序的结构应该有额外的类别字段和类别内的价格总和。然后,您可以在第二遍时相当轻松地对数据进行排序。

所以,我认为大纲处理可能是:

struct reporting
{
    char     category[32];
    float    cat_sum;
    char     product[96];
    float    price;
};
  • 扫描struct st_ex数据记录struct reporting,为每条记录创建一条记录,并为每个类别 struct st_ex创建一条附加记录:struct reporting
    • 识别类别并确保有struct reporting该类别的记录(其中categoryproduct字段包含相同的字符串)。
    • st_ex价格添加到相关类别(汇总)。
    • struct st_ex记录复制到自己的struct reporting记录中。
  • 将类别记录(类型struct reporting)添加到要排序的列表中。
    • 每个类别记录中的pricecat_sum值将相同。
    • 每个类别记录中的categoryproduct值将相同。
  • cat_sum每个struct reporting记录的设置为price类别记录中的值(因此每个肉类记录具有相同的 值cat_sum)。
  • 按以下方式对struct reporting记录进行排序:
    • 的降序cat_sum
    • 的降序category(以防两个类别碰巧共享相同的cat_sum)。
    • 的降序price
    • 降序排列product(以防两种产品共享相同的类别和价格)。
  • 按排序顺序打印记录。

这成为此时的控制中断报告。谷歌搜索“控制中断报告”会发现一些有用的材料,但(仅此一次)维基百科页面不是从中获取信息的地方之一(它是一个孤立的页面,只是一个存根)。


我希望这足够清楚,但这不是我最好的解释,我担心。我认为这些想法是合理的,但我能理解我想说的话——我不确定这是否对其他人有帮助。

于 2012-06-12T06:57:12.007 回答