2013-10-25 5 views
5

की स्थिति को सशर्त रूप से नियंत्रित करने का सबसे अच्छा तरीका क्या है मेरे पास मेरे कोड में एक ब्लॉक है जिसमें लूप को किसी शर्त के आधार पर आगे या पीछे चलना चाहिए।लूप

if (forwards) { 
    for (unsigned x = 0; x < something.size(); x++) { 
     // Lots of code 
    } 

} else { 
    for (unsigned x = something.size()-1 ; x >= 0 ; x--) { 
     // Lots of code 
    } 
} 

क्या इसे स्थापित करने का कोई अच्छा तरीका है, इसलिए मैं दो बार लूप के भीतर सभी कोड दोहराता नहीं हूं?

प्रश्न में 'कुछ' एक std :: vector <> है, तो हो सकता है कि यह एक पुनरावर्तक के साथ संभव हो?

+1

रिवर्स इटरेटर। – yngccc

+0

लूप –

+0

का उपयोग करें ध्यान रखें कि लूप के लिए दूसरे में 'x> = 0' हमेशा सत्य का मूल्यांकन करेगा क्योंकि x हस्ताक्षरित है। – doug

उत्तर

6

अलग आप पाश अंदर का उपयोग मूल्य से पाश मूल्य (मैं सी ++ 11 का उपयोग नहीं कर रहा हूँ):

for (unsigned x2 = 0; x2 < something.size(); x2++) { 
    const int x = forward ? x2 : (something.size()-1) - x2; 
    // Lots of code using x 
} 
+0

मैं इसे उत्तर के रूप में चुनता हूं) मैंने इसका इस्तेमाल किया और बी) यह मैंने जो सवाल उठाया, वह सबसे सीधे हल किया गया। मुझे अन्य उत्तरों भी पसंद हैं। एक बिल्ली त्वचा के कई तरीके! – joeButler

+0

आपने लूप के अंदर से सशर्त स्थानांतरित कर दिया है - कार्यात्मक लेकिन निश्चित रूप से इष्टतम नहीं है यदि यह प्रदर्शन महत्वपूर्ण कोड है। दूसरी तरफ, चूंकि आप "बहुत सारे कोड" कहते हैं, यह संभावना नहीं है कि सशर्त एक महत्वपूर्ण बोझ जोड़ देगा ... और शाखा भविष्यवाणी आपके पक्ष में काम करेगी। –

+0

हाँ, मैं इसके साथ सहमत हूं। लेकिन मुझे लगता है कि मूल्यांकन या फंक्शन कॉल के लिए हमेशा सशर्त होगा। मेरे 'असली' कोड में, एक आंतरिक लूप है जो भारी उठाने वाला कर रहा है, इसलिए मुझे किसी भी मार्ग से जाने में खुशी होगी, जहां अधिकांश समय व्यतीत होता है। – joeButler

6

शायद सबसे आसान तरीका है तर्क x के साथ एक समारोह के लिए Lots of code कन्वर्ट करने के लिए है

void do_lots_of_stuff(unsigned x) { 
    // Lots of code 
} 

//////// 

if (forwards) { 
    for (unsigned x = 0; x < something.size(); x++) { 
    do_lots_of_stuff(x); 
    } 
} else { 
    for (unsigned x = something.size()-1 ; x >= 0 ; x--) { 
    do_lots_of_stuff(x); 
    } 
} 
+0

कृपया इसे ठीक करें: 'के लिए (unsigned x = something.size() - 1; x> = 0; x--) {'क्योंकि यह एक अनंत लूप चलाएगा। एस/बी 'के लिए (int x = something.size() - 1; x> = 0; x--) {' – doug

2
template<typename Cont, typename Func> 
Func directional_for_each(Cont c, bool forwards, Func f) { 
    return forwards ? for_each(begin(c), end(c), f) : for_each(rbegin(c), rend(c), f); 
} 

इस तरह उपयोग किया:: और उस समारोह के लिए एक कॉल के साथ दोनों पाश निकायों की जगह

vector<int> v; 
// put stuff in v... 
bool forwards = false; 
directional_for_each(v, forwards, [](decltype(v[0]) x) { 
    // Lots of code using x 
}); 

जैसा कि आप सी ++ 11 का उपयोग नहीं कर रहे हैं, जिसमें 'एक्स का उपयोग कर बहुत सारे कोड' वाले लैम्ब्डा को कहीं और परिभाषित फ़ंक्शन के साथ प्रतिस्थापित करना होगा।

3

या आप कुछ इस तरह कर सकते हैं:

for (unsigned x = (forward ? 0: something.size()); x != (forward ? something.size() :0); forward? x++: x--) { 
    // Lots of code 
} 

संकलक सबसे अधिक संभावना यह अनुकूलन और forward का मूल्यांकन केवल एक बार के बाद से यह मूल्य for पाश मुझे लगता है में परिवर्तन नहीं करता है जाएगा।

0

मैं इस सवाल पर आने के लिए ऐसा हुआ और सोचा कि मैं सशर्त रूप से प्रत्येक लूप की जांच किए बिना समाधान प्रदान कर सकता हूं चाहे आगे या पीछे नहीं जाना है या नहीं।

// Could do 0xFFFFFFFFU if unsigned is 32bits. 
const unsigned MAX_UINT = 0U - 1U; 

// Will need this later. 
const bool backwards = !forwards; 

// temp is either going to be one or zero. 
const unsigned temp = unsigned(forwards); 

// By adding it to all ones, if temp is ones the mask is all zeros 
// else if temp is zero we get all ones. 
const unsigned mask = temp + MAX_UINT; 

// Bit shift temp over such that it will push all of the ones after 
// the first bit to all zeros if temp is one. This means we will 
// either have a one or a negative one if temp is zero. 
const int delta = int((temp << 1) + MAX_UINT); 

const int size = something.size(); 

// The mask will be zero if forwards is true therein i will start out 
// at zero else the mask will be all ones therein return (size - 1). 
for(int i = int((size - 1) & mask); 
// This may be a more complicated check, but there is only one conditional branch. 
    (forwards && (i < size)) || (backwards (0 <= i)); 
    i += delta) 
{ 
    // Lots of code 
}