2016-04-22 8 views
7

पर लूपिंग के लिए सी में DRY सिद्धांत को कार्यान्वित करने के लिए कैसे करें, दो-आयामी सरणी से निपटने पर, उदा। matrices आपको अक्सर तत्वों की यात्रा करने की आवश्यकता है। यह करने के लिए सीधे आगे रास्ता दो नेस्टेड छोरों से है:मैट्रिस

for(int i=0; i < n; ++i) { 
    for(int j=0; j < m; ++j) { 
    // do something with data[i][j] 
    } 
} 

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

संपादित करें: अधिक रचनात्मक होने के लिए, मान लीजिए कि आपके पास मैट्रिक्स प्रकार typedef double** Matrix; है।

सी के लिए ++ इस इस तरह से हल किया जा सकता है: Loop over matrix elements applying variable function

+0

आप एक मैक्रो बना सकते हैं जो इन लूप उत्पन्न करेगा। – Crozin

+0

हां, आप इन मामलों में फ़ंक्शन या मैक्रो का उपयोग कर सकते हैं। –

+0

एक मैक्रो या तो गन्दा हो सकता है (पाठक को गैर-स्पष्ट) कॉल करने या प्रेत छिपाने के लिए 'i' और' j' vars (पाठक के लिए भी स्पष्ट नहीं), यदि आप छुपे हुए वार्स बनाते हैं, तो वे भी घोंसला नहीं जा सका। – DaveRandom

उत्तर

3

पहले काम: आव्यूह को दर्शाने एक struct रूप data recasting पर विचार करें, या, कि, एक सरल typedef में चूक गए। मैं मानता हूँ कि आप पूर्व करते हैं।

"// do something with data[i][j]" एक समारोह (एक foo कहते हैं) कि i, j लेता है, और तर्क के रूप में मैट्रिक्स struct के लिए सूचक हो सकता है।

फिर आप केवल कि पाशन करता एक समारोह की जरूरत है: उस फंक्शन के लिए एक उपयुक्त foo करने के लिए समारोह सूचक ले जाता है, और मैट्रिक्स struct सूचक।

आपकी नौकरी तब आपकी आवश्यकताओं के अनुसार विभिन्न foo एस लागू करने के लिए है। खासकर यदि वे i और j की तरह हार्ड-कोडेड चर नाम परिचय वे मुश्किल डिबगिंग बनाने,:

इस के लिए नहीं उपयोग मैक्रो करो।

+0

हम्म, मुझे लगता है कि मुझे अनुरूप आगंतुक बनाने के लिए बढ़ावा देने की तरह कुछ चाहिए। अब तक नेस्टेड फ़ंक्शंस के साथ (जो एक जीसीसी एक्सटेंशन हैं, मैं वहां आधा रास्ता हूं: http://pastebin.com/3rUz9gEH) लेकिन मैं नेस्टेड फ़ंक्शंस के मानक-अनुपालन कोड के लिए मैक्रोज़ का उपयोग नहीं करूंगा, न ही लाइब्रेरी निर्भरता जैसे कि http://www.haible.de/bruno/packages-ffcall.html, उदाहरण देखें http://stackoverflow.com/questions/216037/what-tools-are-there-for-functional-programming-in-c। शायद इसके लिए विविध कार्यों का उपयोग करना संभव है? – math

+0

विविधता कार्यों के साथ कार्यान्वयन इस तरह दिख सकता है: http://pastebin.com/N8JtCfve – math

0

संकेत देने के लिए बथशेबा को धन्यवाद, अंत में मैं फ़ंक्शन पॉइंटर्स से जुड़े समाधानों के साथ आया, जिन पर मुझे विश्वास नहीं है। मुख्य समस्या उन विशिष्ट कार्यों का निर्माण है जिन्हें अतिरिक्त पैरामीटर की आवश्यकता हो सकती है।

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

उदाहरण के लिए ऐसा आगंतुक किसी दिए गए मान के साथ सभी मैट्रिक्स तत्वों को रीसेट करता है। एक और आगंतुक पैरामीटर के सेट के साथ तत्वों को संशोधित कर सकता है, या एक पैरामीटर की भी आवश्यकता नहीं है। तो मूल रूप से मैं विजिस्टर फ़ंक्शन प्रकार की लचीली परिभाषा पर प्रश्न का सामना करता हूं।

बीटीडब्ल्यू: सी ++ में इसे std::bind या templates के साथ हल किया जा सकता है।

नेस्टेड कार्य:

नेस्टेड कार्यों एक जीसीसी विस्तार कर रहे हैं, और जैसे क्लैंग के साथ उपलब्ध नहीं है।

typedef double** Matrix;  
typedef void (*MatrixElementVisitor) (double* element); 

void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn) { 
    for(size_t i = 0; i < rows; ++i) { 
    for(size_t j = 0; j < cols; ++j){ 
     fn(&m[i][j]); 
    } 
    } 
} 

void filM(Matrix m, size_t rows, size_t cols, double val) { 
    void fill(double *element) { 
    *element = val; 
    } 
    visitMatrixElements(m, rows, cols, fill); 
} 

variadic कार्य::

typedef double** Matrix; 
typedef void (*MatrixElementVisitor) (double* element, va_list args); 

void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn, ...) { 
    va_list args,copy; 
    va_start(args, fn); 
    for(size_t i = 0; i < rows; ++i) { 
    for(size_t j = 0; j < cols; ++j){ 
     va_copy(copy, args); 
     fn(&m[i][j], copy); 
     va_end(copy); 
    } 
    } 
    va_end(args); 
} 

void fill(double *element, va_list args) { 
    *element = va_arg(args, double); 
} 

void filM(Matrix m, size_t rows, size_t cols, double val) { 
    visitMatrixElements(m, rows, cols, fill, val); 
} 

शून्य सूचक: फिर भी यहाँ कोड उदाहरण है

typedef double** Matrix; 
typedef void (*MatrixElementVisitor) (double* element, void *args); 

void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn, void *args) { 
    if(m) { 
    for(size_t i = 0; i < rows; ++i) { 
     if(m[i]) { 
     for(size_t j = 0; j < cols; ++j){ 
      fn(&m[i][j], args); 
     } 
     } 
    } 
    } 
} 

void fill(double* element, void *args) { 
    if(!args) { 
    return; 
    } 
    *element = *((double*)args); 
} 


void filM(Matrix m, size_t rows, size_t cols, double val) { 
    visitMatrixElements(m, rows, cols, fill, &val); 
} 

हो सकता है कि अन्य तरीके मौजूद हैं, मैं स्थिर समारोह का उपयोग कर के बारे में सोच विज़िटर फ़ंक्शन के प्रारंभ के लिए चर, इसमें विविध कार्य शामिल हैं।

आपकी प्रतिक्रिया के लिए धन्यवाद।

+0

ध्यान दें कि कॉलबैक फ़ंक्शंस को रेखांकित नहीं किया जाएगा, इसलिए प्रत्येक मैट्रिक्स तत्व के लिए वास्तविक फ़ंक्शन कॉल की आवश्यकता होगी। – joop

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