2012-06-10 39 views
2

我想以一種particuar的方式排序一個結構。正如你可以在下面的結構中看到的,字段按product名稱排序。自定義qsort比較函數與結構中的多個字段C

 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>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

謝謝你們,使得現在很多更有意義。 – user1024718

回答

0

作業?有人用C寫這種東西嗎?

想想你的目標是什麼:如果產品名稱是不同的,那麼它是沒有區別的價格是什麼,所以你返回的名稱比較結果。

只有在產品名稱與價格相同的情況下才是如此。

因此需要固定問題。需要更多應用感知的替代品strcmp(3),知道b,b.0|100b.0|200應該作爲產品「名稱」進行同等比較。當然,在平等的情況下,有必要添加一個價格比較。下面的代碼取代了您的比較功能並已經過測試。順便說一句,你不需要投的轉換和從void *如果你是工作在純C.

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); 
} 
0

最簡單的方法是修改您的struct_cmp_by_product。而不是做一個strcmp,比較產品名稱(取決於您的產品名稱的長度,您可能希望在product成員的子字符串上使用strcmp)。

但我寧願通過保持相結合,當兩個成員加入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; 
} 
+0

「x」在任何時候都不會成立嗎? – user1024718

+0

我假設'product'字段包含'a','b'等,而'subgroup'字段包含'.0 | 100'部分。所以,我不明白爲什麼'x'總會是真的。但是當它是真的,我們按價格(而不是名稱)來分類。這不是你想要的嗎? – dirkgently

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; 

終收功能:

} 

注:我可能會丟失錯誤檢查或有錯別字,請確保您在使用它之前理解的代碼。不要只複製粘貼。

+0

我認爲有關使用'strchr'的觀點。謝謝 – user1024718

+0

@ user1024718,如果答案對您有幫助,您可以upvote /接受它。 – Shahbaz

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; 
} 

UPDATE:STRCMP() - >> STRNCMP +計算尺寸

+0

不會'strcmp'一直返回true?我不明白什麼時候會比較價格。 – user1024718

+0

strcmp()返回零,或者小於零,或者大於零。 'if(rc)'條件測試不等於零的條件,所以比較價格只會在產品名稱相同時纔會發生。 – wildplasser

+0

但這不起作用。產品名稱在strcmp的意義上實際上是不同的......您只需要對產品「名稱」的一部分進行排序。 – DigitalRoss