2012-07-01 24 views
6

कहो मुझे लगता है कि युगल के सरणियों की एक सरणी के रूप में प्रतिनिधित्व कर रहे हैं डेटा बिंदुओं का एक सेट है, तोक्रमबद्ध सी में विभिन्न अनुक्रमित द्वारा सरणियों की एक सरणी

double **data; 

अब अगर मैं द्वारा डेटा को सॉर्ट करना चाहता था डेटा बिंदुओं में से प्रत्येक में कुछ क्षेत्र, का कहना है कि 2 nd क्षेत्र, मैं एक तुलनित्र ऐसा ही कुछ करना होगा लिखना होगा:

int compare_data_second_field(void *a, void *b) { 
    double da = ((double *) a)[1]; 
    double db = ((double *) b)[1]; 
    if (da < db) return -1; 
    else if (da > db) return 1; 
    return 0; 
} 

और फिर 2 nd फाई द्वारा उन्हें सुलझाने के लिए qsort का उपयोग फ़ील्ड।

मेरा सवाल यह है कि अगर मैं हाथ से पहले नहीं जानता कि मैं किस क्षेत्र से सॉर्ट करना चाहता हूं तो मैं इसे कैसे सामान्यीकृत करूं? जैसे मैं 1 सेंट फ़ील्ड कभी-कभी और 5 वें फ़ील्ड द्वारा सॉर्ट करना चाहता हूं, आदि। मैं इसे थ्रेड सुरक्षित भी पसंद करूंगा, इसलिए मैं एक वैश्विक चर का उपयोग नहीं करना चाहता हूं इनमें से कई के बाद से क्रमबद्ध करने के लिए क्षेत्र एक बार में जा रहा है।

सी ++ में मैं सिर्फ एक कस्टम सॉर्टिंग क्लास का उपयोग करता हूं और कक्षा में एक उदाहरण चर होता है ताकि ट्रैक को किस क्रमबद्ध किया जा सके। मुझे नहीं पता कि सी

+6

आप वास्तव में _third_ आइटम को पकड़ रहे हैं। क्या आप इससे जागरुक हैं? –

+2

असल में 'डबल ** डेटा है;' डबल डेटा ** नहीं; ' –

+3

इनमें से दोनों के लिए संपादित किया गया।जबकि वे सच हैं, वे चर्चा के लिए पूरी तरह से अप्रासंगिक हैं और वास्तव में कुछ भी नहीं जोड़ते हैं, लेकिन जो भी हो। – pjreddie

उत्तर

7

qsort_r का उपयोग करने के लिए सबसे अच्छा तरीका यह होगा कि यह आपके प्लेटफॉर्म पर उपलब्ध है। qsort_r आपके तुलनित्र को पारित एक अतिरिक्त तर्क स्वीकार करता है, ताकि आप उस क्षेत्र को पारित करने के लिए इसका उपयोग कर सकें जिसके द्वारा आप अपना डेटा सॉर्ट करना चाहते हैं।

यदि यह आपके प्लेटफ़ॉर्म पर उपलब्ध नहीं है, तो वास्तव में ऐसा करने का एक आसान तरीका नहीं है। आप वैश्विक चर का उपयोग करके इसके आसपास काम कर सकते हैं, एक स्ट्रक्चर में अपना डेटा लपेट सकते हैं जिसमें सॉर्टिंग फ़ील्ड पर जानकारी होगी, या अपने qsort_r-जैसे फ़ंक्शन को रोल करना होगा।

0

आप एन = 0,1,2 के लिए compare_data_field_N कार्यों का पूरा समूह घोषित कर सकते हैं ... और उसके बाद संबंधित कार्यों के साथ प्रारंभ किए गए फ़ंक्शन पॉइंटर्स की compare_data सरणी घोषित कर सकते हैं। फिर, किसी विशिष्ट फ़ील्ड पर qsort पर, आप qsort पर जाने के लिए सरणी से फ़ंक्शन पॉइंटर खींचते हैं। आप कार्यों और सरणी सरल की पीढ़ी बनाने के लिए मैक्रो का उपयोग कर सकते हैं:

#define REP10(M) M(0) M(1) M(2) M(3) M(4) M(5) M(6) M(7) M(8) M(9) 
#define DECLARE_COMPARE(N)           \ 
    int compare_data_field_##N(void *a, void *b) {     \ 
     double da = ((double *) a)[N];        \ 
     double db = ((double *) b)[N];        \ 
     if (da < db) return -1;         \ 
     else if (da > db) return 1;        \ 
     return 0;             \ 
    } 
#define REF_COMPARE(N) compare_data_field_##N, 

REP10(DECLARE_COMPARE) 
int (*compare_data_field[])(void *, void *) = { REP10(REF_COMPARE) }; 

आप केवल REP10 मैक्रो संशोधित की जरूरत है अगर आप 10 से अधिक संभावित क्षेत्रों चाहते हैं।

+0

शायद मैं गलत हूं, लेकिन मुझे लगता है कि ओपी _run-time_ पर क्रमबद्ध करने के लिए फ़ील्ड की अनुक्रमणिका चुनना चाहता है। –

4

वास्तव में, नेस्टेड फ़ंक्शंस (जो एक जीसीसी एक्सटेंशन हैं) के साथ इसके लिए एक सुंदर साफ समाधान है।
आप क्या कर सकते हैं एक सामान्य तुलनित्र करते हैं:

int my_comparator(const void* a, const void* b, int n) 
{ 
    double da = ((double*)a)[n]; 
    double db = ((double*)b)[n]; 
    return (da > db) ? 1 : ((da < db) ? -1 : 0); /* Awesome */ 
} 

और एक कस्टम छँटाई समारोह है कि लपेटता मूल qsort():

void my_qsort(void* base, size_t num, size_t size, 
    int (*comparator)(const void *, const void *, int), int field) 
{ 
    /* Internal comperator */ 
    int my_qsort_comperator(const void* a, const void* b) 
    { 
     return comparator(a, b, field); 
    } 

    /* Invoke the base qsort function */ 
    qsort(base, num, size, my_qsort_comperator); 
} 

इस समारोह सिर्फ मूल qsort() तरह बर्ताव करता है, सिवाय इसके कि यह एक लेता है अतिरिक्त तर्क field, जो क्रमबद्ध करने के लिए फ़ील्ड की अनुक्रमणिका इंगित करता है।

संबंधित मुद्दे