'<' बनाम '! =' के रूप में हालत में 'पाश' के लिए?


31

कहते हैं कि आपके पास निम्नलिखित forलूप है:

for (int i = 0; i < 10; ++i) {
    // ...
}

जिसे सामान्यतः लिखा जा सकता है:

for (int i = 0; i != 10; ++i) {
    // ...
}

अंतिम परिणाम समान हैं, तो क्या एक के बाद एक का उपयोग करने के लिए कोई वास्तविक तर्क हैं? व्यक्तिगत रूप से मैं iकिसी कारण के लिए मामले में पूर्व का उपयोग करता है haywire जाता है और मूल्य 10 को छोड़ देता है।

* जादू की संख्या का उपयोग करें, लेकिन यह सिर्फ एक उदाहरण है।


18
दोनों में से किसी एक का बेहतर समाधान है कि int i = 10; while(i --> 0) { /* stuff */ }
आपर

@glowcoder एरो ऑपरेटर मेरा पसंदीदा है
कार्सन मायर्स

3
@glowcoder, अच्छा है, लेकिन यह पीछे से आता है। आप हमेशा ऐसा नहीं चाह सकते हैं।

2
@SuperElectric, यह पार्स करता हैwhile ((i--) > 0)
क्रिस्टोफर जॉनसन

17
सेंसर इनपुट के लिए लूप टेस्टिंग के कारण होने वाली औद्योगिक दुर्घटना के बारे में एक (शायद एपोक्रीफाल) कहानी है! = MAX_TEMP। दुर्भाग्य से एक दिन सेंसर इनपुट MAX_TEMP से कम होने से अधिकतम MAX_TEMP से अधिक हो गया, बिना MAX_TEMP से गुजरते हुए। प्रक्रिया का पता लगाए बिना ओवरहीट हो गया, और आग लग गई। कभी-कभी इसमें अंतर होता है! = और <।
चार्ल्स ई। ग्रांट

जवाबों:


59

एक या दूसरे को चुनने का कारण इरादा है और इसके परिणामस्वरूप, यह पठनीयता बढ़ाता है

आशय: लूप तब तक चलना चाहिए जब तक i10 से छोटा न हो, जब तक iकि 10 के बराबर न हो, तब तक नहीं। हालांकि इस विशेष मामले में उत्तरार्द्ध समान हो सकता है, लेकिन इसका मतलब यह नहीं है कि आपको इसका मतलब नहीं होना चाहिए। ऐसा लिखा जाए।

पठनीयता: आपके लिखने का एक मतलब यह है कि यह समझना भी आसान है। उदाहरण के लिए, यदि आप उपयोग करते हैं i != 10, तो कोड पढ़ने वाला कोई व्यक्ति आश्चर्यचकित हो सकता है कि क्या लूप के अंदर कोई रास्ता i10 से बड़ा हो सकता है और यह कि लूप जारी रहना चाहिए (btw: यह खराब शैली है, जहां इट्रेटर के साथ गड़बड़ करने की जगह कहीं और है for-statement, लेकिन इसका मतलब यह लोग यह क्या करता है नहीं है नहीं है और इसके परिणामस्वरूप देखरेख यह उम्मीद)।


3
नहीं, लूप को तब तक नहीं चलाना चाहिए जब तक कि i"10 से छोटा" न हो, इसे तब तक चलाना चाहिए जब तक (इस मामले में) ऊपरी बाउंड तक नहीं पहुंचा जाता है। C ++ अंतराल / पुनरावृत्ति श्रेणी के तर्क का उपयोग करते समय, इसके माध्यम !=से इसे व्यक्त करना कहीं अधिक तार्किक है <
कोनराड रुडोल्फ

14
@Konrad मैं इससे बिल्कुल भी असहमत नहीं हूं। मुख्य बिंदु हठधर्मी होना नहीं है, बल्कि निर्माण का चयन करना है जो शर्त की मंशा को सबसे अच्छा व्यक्त करता है। और इसलिए, यदि आप 0 पर शुरू होने और ऊपर जाने वाली किसी चीज़ के माध्यम से लूप चुनते हैं, तो <वास्तव में यह ठीक व्यक्त करता है।
डेकार्ड

6
@ कोनराड, आप बिंदु को याद कर रहे हैं। इस लूप में वृद्धि ऑपरेटर यह स्पष्ट करता है कि लूप की स्थिति एक ऊपरी बाध्य है, पहचान की तुलना नहीं है। यदि आप कमी कर रहे थे, तो यह कम बाध्य होगा। यदि आप एक गैर-आदेशित संग्रह पर पुनरावृत्ति कर रहे हैं, तो पहचान सही स्थिति हो सकती है।
एलेक्स फीमिन

3
@ वेतन वृद्धि मेरी बात नहीं थी। एक अंतराल भी जरूरी नहीं है है एक आदेश। यह सिर्फ ... कुछ ठीक है, जब तक यह अंत तक नहीं पहुँचता है। उदाहरण के लिए, हैश सेट में तत्व। C ++ में, यह iterators और एक forलूप का उपयोग करके किया जाता है । <यहाँ का उपयोग करना मूर्खतापूर्ण होगा। इसके अलावा, डेकार्ड इस बात को स्वीकार करता है। मैं उनके जवाब में उनकी टिप्पणी से बहुत सहमत हूं।
कोनराड रूडोल्फ

1
ध्यान दें, यदि आप पीछा करने वाले बिंदुओं के साथ एक रोटरी बफर का उपयोग करते हैं, तो आपको उपयोग करना होगा!=
एसएफ।

48

<पैटर्न आम तौर पर प्रयोग करने योग्य भले ही वेतन वृद्धि 1 वास्तव में होने के लिए नहीं होता है।

यह एक ही आम तरीका है कि यह वास्तव में कैसे किया जाता है की परवाह किए बिना लूप करने की अनुमति देता है।


6
iयदि आवश्यक हो तो यह लूप के अंदर पूरी तरह से सुरक्षित रूप से संशोधित करने की भी अनुमति देता है।
मैथ्यू शार्ले

1
या यदि 'i' को पूरी तरह से अनसैचुरेट कर दिया गया है ... दूसरी टीम को अजीब सर्वर प्रॉब्लम थी। यह 100% CPU उपयोग की रिपोर्ट करता रहा और इसे सर्वर या निगरानी प्रणाली के साथ समस्या होना चाहिए, है ना? नहीं, मुझे 'विशेषज्ञ वरिष्ठ प्रोग्रामर' द्वारा लिखी गई एक लूप कंडीशन मिली, जिस समस्या के बारे में हम बात कर रहे हैं।
jqa

12
सिवाय इसके कि लूप्स के लिए सभी C ++ का उपयोग नहीं किया जा सकता है <, जैसे कि एक अनुक्रम में पुनरावृत्तियां, और इसलिए !=C ++ में लूप्स करने का एक सामान्य तरीका होगा।
डेविड थॉर्नले

@SnOrfus: मैं उस टिप्पणी पर बहुत गौर नहीं कर रहा हूं। आप सामान्य रूप से बहुत अधिक पुनरावृत्तियों को बढ़ाने के लिए अपवाद प्राप्त नहीं करेंगे (हालाँकि आप जहां हैं वहां अधिक विशिष्ट परिस्थितियां हैं)।
डेविड थोरले

खैर, मैं <पैटर्न का पालन करता हूं क्योंकि पैटर्न के साथ दो के बजाय एक कीस्ट्रोक की आवश्यकता होती है >, और चार के साथ !=। यह वास्तव में ओसीडी जैसी दक्षता की बात है।
स्पोकाइक

21

C ++ में अधिक प्रभावी C ++ (आइटम 6) में स्कॉट मायर्स द्वारा सिफारिश हमेशा दूसरी का उपयोग करने के लिए होती है जब तक कि आपके पास कोई कारण न हो, क्योंकि इसका मतलब है कि आपके पास इट्रेटर और पूर्णांक अनुक्रमित के लिए एक ही वाक्यविन्यास है ताकि आप बीच में intऔर सीटर को स्वैप कर सकें सिंटैक्स में कोई बदलाव किए बिना।

अन्य भाषाओं में यह लागू नहीं होता है इसलिए मुझे लगता <है कि शायद थोरबजर्न रेवन एंडरसन की बात के कारण यह बेहतर है।

वैसे, दूसरे दिन मैं एक और डेवलपर के साथ इस बारे में चर्चा कर रहा था और उन्होंने कहा कि पसंद <करने !=का कारण iयह है कि गलती से एक से अधिक वृद्धि हो सकती है, और इससे ब्रेक की स्थिति पूरी नहीं हो सकती है; IMO बकवास का भार है।


17
"बकवास का भार" ... उस दिन तक जब तक आप लूप के शरीर में अतिरिक्त i ++ नहीं रखते।

2
+1, विशेष रूप से "बकवास के भार" के लिए, क्योंकि यह है। यदि लूप बॉडी गलती से काउंटर को बढ़ाती है, तो आपको बहुत बड़ी समस्याएं हैं।
कोनराड रुडोल्फ

12
@ बी टायलर, हम केवल मानव हैं, और बड़ी गलतियां पहले भी हुई हैं। तब <से अधिक रक्षात्मक प्रोग्रामिंग करने के लिए विचार करें !=...

2
@ Thorbjørn रावन एंडरसन - मैं यह नहीं कह रहा हूं कि मैं आपसे सहमत नहीं हूं, मैं करता हूं; <अधिक रक्षात्मक है और अगर !=मैं ऐसा नहीं लिखता तो मेरे सहकर्मी इससे नफरत करते हैं। हालाँकि, !=C ++ में एक मामला है और जो मैंने प्रस्तुत किया है।

9
एक परिदृश्य जहां एक आकस्मिक अतिरिक्त के साथ समाप्त हो सकता i++है, जब एक लूप में एक लूप में बदल रहा है। यह निश्चित नहीं है कि पुनरावृत्तियों की आधी संख्या किसी भी (हालांकि) अनंत लूप से बेहतर है; बाद शायद बग को और अधिक स्पष्ट कर देगा।
ak2

12

(I <10) का उपयोग करना मेरी राय में एक सुरक्षित अभ्यास है। यह संभावित छोड़ने वाले मामलों की अधिकतम संख्या को पकड़ता है - सब कुछ जो 10 से अधिक या उसके बराबर है। अन्य मामले के साथ इसका विरोध करें (i! = 10); यह केवल एक संभव छोड़ने के मामले को पकड़ता है - जब मैं ठीक 10 पर हूं।

इसका एक अनुचर यह है कि यह पठनीयता में सुधार करता है। इसके अतिरिक्त, वेतन वृद्धि कुछ अन्य 1 होनी चाहिए, यह समस्या को कम करने में मदद कर सकता है जब हमें छोड़ने के मामले को लिखना चाहिए।

विचार करें:

1) for (i = 1; i < 14; i+=2)

2) for (i = 1; i != 14; i+=2)

यद्यपि दोनों मामलों में त्रुटिपूर्ण / गलत होने की संभावना है, दूसरा गलत होने की संभावना है क्योंकि यह नहीं छोड़ा जाएगा। पहला मामला छोड़ दिया जाएगा, और एक उच्च संभावना है कि यह सही स्थान पर छोड़ देगा, भले ही 14 संभवतः गलत संख्या है (15 शायद बेहतर होगा)।


पहला मामला सही हो सकता है! यदि आप 14 से कम सभी प्राकृतिक संख्याओं पर चलना चाहते हैं, तो इसे व्यक्त करने का कोई बेहतर तरीका नहीं है - "उचित" ऊपरी बाउंड (13) की गणना करना सादे बेवकूफ होगा।
मातरिनस

9

यहाँ एक और जवाब है कि कोई भी अभी तक साथ नहीं आया है। forजब आपको किसी अनुक्रम पर पुनरावृति करने की आवश्यकता होती है तो लूप का उपयोग किया जाना चाहिए । का उपयोग करना !=लूप के लिए समाप्ति की स्थिति को बताते हुए सबसे संक्षिप्त विधि है। हालांकि, कम प्रतिबंधात्मक ऑपरेटर का उपयोग करना एक बहुत ही रक्षात्मक प्रोग्रामिंग मुहावरा है। पूर्णांकों के लिए यह कोई फर्क नहीं पड़ता है - यह एक अधिक विशिष्ट उदाहरण के बिना सिर्फ एक व्यक्तिगत पसंद है। पुनरावृत्तियों के साथ संग्रह पर लूपिंग आप !=उन कारणों के लिए उपयोग करना चाहते हैं जो दूसरों ने बताए हैं। आप के दृश्यों पर विचार करें floatया doubleहै, तो आप से बचना चाहते हैं !=हर कीमत पर।

जो मैं इंगित करना चाहता था, वह forतब होता है जब आपको किसी अनुक्रम पर पुनरावृति करने की आवश्यकता होती है। उत्पन्न अनुक्रम में एक प्रारंभिक बिंदु, एक अंतराल और एक समाप्ति स्थिति है। ये forकथन के भीतर स्पष्ट रूप से निर्दिष्ट हैं । यदि आप अपने आप को या तो (1) forया (2) के चरण भाग को शामिल नहीं करते हैं, trueजैसे कि गार्ड की स्थिति के रूप में कुछ निर्दिष्ट करना , तो आपको forलूप का उपयोग नहीं करना चाहिए !

whileपाश प्रसंस्करण जारी रखने के लिए, जबकि एक विशिष्ट स्थिति उत्पन्न होने पर किया जाता है। यदि आप एक अनुक्रम को संसाधित नहीं कर रहे हैं, तो आप शायद whileइसके बजाय एक लूप चाहते हैं । गार्ड की स्थिति के तर्क यहां समान हैं, लेकिन whileएक forलूप के बीच का निर्णय बहुत सचेत होना चाहिए। whileपाश IMO सी ++ हलकों में अंडर सराहना की है।

यदि आप वस्तुओं के संग्रह (एक बहुत ही आम- forउपयोग) का प्रसंस्करण कर रहे हैं , तो आपको वास्तव में अधिक विशिष्ट विधि का उपयोग करना चाहिए। दुर्भाग्य से, std::for_eachकई कारणों से C ++ में बहुत दर्दनाक है। कई मामलों forमें एक फ्री-स्टैंडिंग फ़ंक्शन (जबकि कुछ दर्दनाक) में लूप के शरीर को अलग करने से बहुत अधिक क्लीनर समाधान होता है। जब संग्रह के साथ काम करने पर विचार std::for_each, std::transformया std::accumulate इस तरह से व्यक्त किए जाने पर कई एल्गोरिदम का कार्यान्वयन संक्षिप्त और क्रिस्टल स्पष्ट हो जाता है। यह उल्लेख करने के लिए नहीं कि लूप के शरीर को एक अलग फ़ंक्शन / विधि में अलग करना आपको एल्गोरिथ्म, इसकी इनपुट आवश्यकताओं और परिणामों पर ध्यान केंद्रित करने के लिए मजबूर करता है।

यदि आप जावा, पायथन, रूबी, या यहां तक ​​कि सी ++ 0x का उपयोग कर रहे हैं , तो आपको एक उचित संग्रह फोर्क लूप का उपयोग करना चाहिए । जैसे ही C ++ कंपाइलर इस सुविधा को लागू करते हैं, कई प्रकार के forलूप गायब हो जाएंगे क्योंकि इस प्रकार के विचार-विमर्श होंगे।


2
"हालांकि, कम प्रतिबंधात्मक ऑपरेटर का उपयोग करना एक बहुत ही सामान्य रक्षात्मक प्रोग्रामिंग मुहावरा है।" यह इसे कम या ज्यादा करता है।
जेम्स पी।

की तुलना के साथ आशय में मतभेद discussin के लिए +1 while, forऔर foreach(या भाषा बराबर)
केविन Peno में

सच पूछिये तो, पाश प्रसंस्करण जारी रखने के लिए प्रयोग किया जाता है जब तक एक विशिष्ट शर्त है नहीं मिले थेwhile
एल्निटैक

@Alnitak - D'oh ... मैं इसे ठीक कर दूँगा :)
D.Shawley

मैं "कम प्रतिबंधक" के दो संभावित अर्थों में उलझन में था: यह ऑपरेटर को उन मूल्यों में उदार होने का उल्लेख कर सकता है जो इसे गुजरता है ( <) या ऑपरेटर विफल मूल्यों में उत्तरदायी है ( !=)।
मतीन उलहक

4

"से कम" का उपयोग करना (आमतौर पर) शब्दार्थ रूप से सही है, आप वास्तव में गिनते हैं जब तक iकि 10 से कम न हो, इसलिए "कम" आपके इरादों को स्पष्ट रूप से व्यक्त करता है। "न के बराबर" का उपयोग स्पष्ट रूप से कॉल मामलों में काम करता है, लेकिन थोड़ा अलग अर्थ बताता है। कुछ मामलों में यह वही हो सकता है जिसकी आपको आवश्यकता है लेकिन मेरे अनुभव में ऐसा कभी नहीं हुआ। यदि आपके पास वास्तव में ऐसा मामला है जहां i10 से अधिक या कम हो सकता है, लेकिन आप लूपिंग रखना चाहते हैं जब तक कि यह 10 के बराबर न हो, तो उस कोड को वास्तव में बहुत स्पष्ट रूप से टिप्पणी करने की आवश्यकता होगी, और संभवतः कुछ अन्य निर्माणों के साथ बेहतर लिखा जा सकता है, जैसे whileशायद पाश के रूप में ।


2

एक कारण है कि मैं एक less thanपर एक एहसान क्यों not equalsएक गार्ड के रूप में कार्य करने के लिए है। कुछ सीमित परिस्थितियों में (खराब प्रोग्रामिंग या सैनिटाइजेशन) को not equalsछोड़ दिया जा सकता है जबकि less thanअभी भी प्रभावी होगा।

यहां एक उदाहरण है जहां एक सैनिटाइजेशन चेक की कमी के कारण अजीब परिणाम सामने आए हैं: http://www.michaeleisen.org/blog/?it=358


0

यहाँ एक कारण है कि आप <इसके बजाय का उपयोग करना पसंद कर सकते हैं !=। यदि आप ऐसी भाषा का उपयोग कर रहे हैं, जिसमें ग्लोबल वैरिएबल स्कोपिंग है, तो अन्य कोड को संशोधित करने पर क्या होगा i? यदि आप इसके <बजाय उपयोग कर रहे हैं !=, तो सबसे खराब यह है कि पुनरावृत्ति जल्दी समाप्त हो जाती है: शायद iदुर्घटना से कुछ अन्य कोड वेतन वृद्धि , और आप लूप के लिए कुछ पुनरावृत्तियों को छोड़ देते हैं। लेकिन क्या होगा यदि आप 10 के माध्यम से 0 लूपिंग कर रहे हैं, और लूप 9 तक पहुंच जाता है, और iकुछ अजीब कारण के लिए कुछ बुरी तरह से लिखा हुआ वेतन वृद्धि । फिर आपका लूप उस पुनरावृत्ति और वेतन वृद्धि को समाप्त करता है iताकि मान अब 11 हो। लूप ने बाहर निकलने की स्थिति को छोड़ दिया है ( i10 के बराबर कभी नहीं) अब यह अनंत रूप से लूप करेगा।

यह जरूरी नहीं है कि यह विशेष रूप से अजीब थ्रेडिंग-एंड-ग्लोबल-वैरिएबल प्रकार का तर्क है जो इसका कारण बनता है। यह सिर्फ यह हो सकता है कि आप एक लूप लिख रहे हैं जिसे पीछे करने की आवश्यकता है। यदि आप iलूप के अंदर उत्परिवर्तन कर रहे हैं और आप अपने तर्क को बढ़ा -चढ़ा कर देखते हैं , तो यह है कि यह एक अपर बाउंड के बजाय !=एक अनंत लूप में आपको छोड़ने की संभावना कम है।


3
बेशक, यह प्रत्येक छोरों और सामान्य रूप से अधिक कार्यात्मक प्रोग्रामिंग शैली के लिए एक सही तर्क की तरह लगता है। लेकिन, आप ऐसा क्यों करना चाहेंगे जब म्यूटेबल वैरिएबल बहुत अधिक मज़ेदार हों ?!
टॉम मॉरिस

3
मुझे नहीं लगता कि यह बहुत अच्छा कारण है। किसी भी तरह से आपको एक बग मिला है जिसे ढूंढने और तय करने की आवश्यकता है, लेकिन एक अनंत लूप एक बग को स्पष्ट करने के लिए जाता है।
ak2

0

एम्बेडेड दुनिया में, विशेष रूप से शोर के वातावरण में, आप रैम पर भरोसा नहीं कर सकते हैं जो आवश्यक रूप से व्यवहार करना चाहिए। सशर्त में (के लिए, जबकि, यदि) जहाँ आप '==' या '!' का उपयोग करते हुए तुलना करते हैं, तो आप हमेशा यह जोखिम उठाते हैं कि आपके चर उस महत्वपूर्ण मूल्य को छोड़ देते हैं जो लूप को समाप्त करता है - इसके विनाशकारी परिणाम हो सकते हैं - मार्स लैंडर स्तर के परिणाम। इस स्थिति में '<' या '>' का उपयोग करने से 'अज्ञात अज्ञात' को पकड़ने के लिए अतिरिक्त स्तर की सुरक्षा मिलती है।

मूल उदाहरण में, अगर iअकथनीय रूप से 10 से अधिक बड़े मान पर गुलेल लगाई गई थी, तो '<' तुलना त्रुटि को तुरंत पकड़ लेगी और लूप से बाहर निकल जाएगी, लेकिन '! =' तब तक गिना जाता रहेगा, जब तक iकि वह पिछले 0 और पीछे से लिपटा न हो! 10 से।


2
एक अन्य संबंधित भिन्नता कोड के साथ मौजूद है, for (i=4; i<length; i++) csum+=dat[i];जहां वैध पैकेट में हमेशा lengthकम से कम चार होते हैं, लेकिन कोई दूषित पैकेट प्राप्त कर सकता है। यदि अलग-अलग पैकेट प्रकारों की लंबाई अलग-अलग होती है, तो हर एक पैकेट के प्रकार के प्रसंस्करण के हिस्से के रूप में लंबाई को मान्य करना चाह सकते हैं, लेकिन पहले सामान्य तर्क के हिस्से के रूप में चेकसम को मान्य करें। यदि एक कम लंबाई वाला पैकेट प्राप्त होता है, तो यह वास्तव में कोई मायने नहीं रखता है कि चेकसम कम्प्यूट रिपोर्ट "अच्छा" या "खराब" है, लेकिन यह क्रैश नहीं होना चाहिए।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.