2012-01-04 6 views
2

私は、次の構造体Cで構造体の配列をソートする方法は?

typedef struct _my_data_ 
{ 
    unsigned int id; 
    double latitude; 
    double longitude; 
    unsigned int content_len; 
    char* name_dyn; 
    char* descr_dyn; 
} mydata; 

の配列を持っているし、それがIDで昇順にソートしたいと思います。 qsort関数を使用して配列をソートすることは可能ですが、構造体のソート時に正しく使用する方法がわかりません。

ご協力いただければ幸いです。

+5

与えられた2つの構造体のどちらが大きいか小さい「id」フィールドを持っているかを知る関数を書いたことがありますか? – sarnold

答えて

16

あなたはqsort()、すなわちによって期待される機能のプロトタイプと一致する構造のコンパレータ機能必要がありますすることができますので、あなたがこれまで以上に複雑なソート基準を取得した場合、これはまだ良い基盤である

int md_comparator(const void *v1, const void *v2) 
{ 
    const mydata *p1 = (mydata *)v1; 
    const mydata *p2 = (mydata *)v2; 
    if (p1->id < p2->id) 
     return -1; 
    else if (p1->id > p2->id) 
     return +1; 
    else 
     return 0; 
} 

int md_comparator(const void *v1, const void *v2) 
{ 
    const mydata *p1 = (mydata *)v1; 
    const mydata *p2 = (mydata *)v2; 
    if (p1->latitude < p2->latitude) 
     return -1; 
    else if (p1->latitude > p2->latitude) 
     return +1; 
    else if (p1->longitude < p2->longitude) 
     return -1; 
    else if (p1->longitude > p2->longitude) 
     return +1; 
    else 
     return 0; 
} 

明らかに、これは必要な基準で繰り返されます。あなたは、値を比較する機能(?strcmp())を呼び出し、一度それを呼び出すが、二回のローカル変数と使用への復帰を割り当てる必要がある場合:

int md_comparator(const void *v1, const void *v2) 
{ 
    const mydata *p1 = (mydata *)v1; 
    const mydata *p2 = (mydata *)v2; 
    int rc; 
    if (p1->latitude < p2->latitude) 
     return -1; 
    else if (p1->latitude > p2->latitude) 
     return +1; 
    else if (p1->longitude < p2->longitude) 
     return -1; 
    else if (p1->longitude > p2->longitude) 
     return +1; 
    else if ((rc = strcmp(p1->name_dyn, p2->name_dyn)) < 0) 
     return -1; 
    else if (rc > 0) 
     return +1; 
    else 
     return 0; 
} 

データメンバが符号なし整数である場合にも、このテンプレートは動作しますが、符号付き整数を比較するときのオーバーフローの問題を回避します。整数が署名とのしている場合idは(2つの符号なし整数の差が負になることはありません)符号なし、およびオーバーフローの対象となる場合

int md_comparator(const void *v1, const void *v2) /* BAD */ 
{             /* BAD */ 
    const mydata *p1 = (mydata *)v1;    /* BAD */ 
    const mydata *p2 = (mydata *)v2;    /* BAD */ 
    return(p1->id - p2->id);      /* BAD */ 
}             /* BAD */ 

悪いです:あなたが時々表示される場合があります短いカットは、すなわち上のバリエーションがあることに注意してください大規模かつ反対の符号。

+0

コメントをいただき、ありがとうございます。 –

+0

あなたの答えに多くの感謝、私は今すぐこのコードを試してみるつもりです。 – beta

+1

'id'がunsigned'の場合の瞑想:返り値が 'int'なので、' unsigned'の値は 'int'に変換され、負になります。しかし、 'id'が' unsigned long'や 'unsigned long long'、' sizeof(long)> sizeof(int) 'なら、あなたは非常に奇妙な振る舞いに脆弱です。明示的なリターン±1のメカニズムが常に働くという観察は、依然として正確である。 2つの符号なし量の比較が厳密に正確でない場合には、スイープ「減算は機能しません。 –

関連する問題