क्या? लूप ’के लिए 1 में इंक्रीमेंट करने पर = के बजाय = (<) का उपयोग करने का एक तकनीकी कारण है?


198

मैं लगभग कभी forइस तरह से एक लूप नहीं देखता :

for (int i = 0; 5 != i; ++i)
{}

एक लूप में 1 से वृद्धि करते समय उपयोग करने के बजाय >या <इसके लिए एक तकनीकी कारण है ? या यह एक सम्मेलन का अधिक है?!=for


104
यह इसे और अधिक पठनीय बनाता है, के साथ साथ, अगर आप कभी भी बदल i++करने के लिए i+=2(उदाहरण के लिए), यह (हमेशा के लिए या संभवतः) एक बहुत लंबे समय के लिए चलेंगे। अब, चूंकि आप आम तौर पर <उन मामलों के लिए उपयोग करते हैं, जहां आप 1 से अधिक द्वारा पुनरावृत्त वृद्धि करते हैं , तो आप <उस मामले के लिए भी उपयोग कर सकते हैं जहां आप इसे 1 (वृद्धि के लिए) बढ़ाते हैं।
बराक मानोस

112
5 != iबुराई है
स्लाव

27
आपको हमेशा सचेत रहना चाहिए कि आप क्या कर रहे हैं, लेकिन आप वैसे भी गलतियाँ करेंगे। इस कोड में बग का परिचय देते हुए किसी का उपयोग करने की संभावना कम हो जाती है।
15

40
@OleTange आप चल बिन्दु संख्या का उपयोग पुनरावृत्ति रहे हैं, तो आप पहले से ही खराब कर रहे हैं ..
CaptainCodeman

29
@ स्लाव ... बुराई नहीं। आप जाहिरा तौर पर कभी नहीं एक साधारण से सी में थोड़ा किया गया है के बीच अंतर बना रही टाइपो if ( i == 5 ) ...और if ( i = 5 )। बहुत अलग चीजें। ऑपरेंडर्स को उलट देना समस्या को रोकता है: चूंकि शाब्दिक नहीं हैं lvals, उन्हें सौंपा नहीं जा सकता है और कंपाइलर टाइपो पर चोट करता है। @ ज़िंगम: अच्छी रक्षात्मक प्रोग्रामिंग!
निकोलस कैरी

जवाबों:


303
while (time != 6:30pm) {
    Work();
}

शाम 6:31 बजे है ... धिक्कार है, अब मेरे घर जाने का अगला मौका कल है! :)

यह दर्शाता है कि मजबूत प्रतिबंध जोखिमों को कम करता है और शायद समझने के लिए अधिक सहज है।


25
कभी-कभी, "जोखिम कम करने" का प्रयास करने से बग छिप जाता है। यदि लूप के डिज़ाइन को 6:30 अपराह्न को फिसलने से रोकना चाहिए, तो उपयोग <करने से बग छिप जाएगा लेकिन उपयोग !=करने से यह स्पष्ट हो जाएगा कि कोई समस्या है।
एड्रियन मैक्कार्थी

27
@ AdrianMcCarthy: जरूरी नहीं; यह सिर्फ एक दूसरे बग का परिचय दे सकता है, जिससे निदान कठिन हो जाता है
कक्षा

4
@ AdrianMcCarthy: यह मेरी बात की तरह है; आपके पास इसके कुछ उदाहरण हो सकते हैं, जिन्हें आपने अभी तक नहीं देखा है;)
ऑर्बिट में हल्कापन दौड़

6
Iterators मेरे विचार से @ AdrianMcCarthy बिंदु का एक आदर्श उदाहरण हैं। उनके लिए अनुशंसित तुलना है! = के बजाय <।
ताकाहन

5
मैंने वास्तव में इस त्रुटि को देखा है (और यह डिबगिंग के 3 महीने का कारण है) - लेकिन यह जवाब पूरी तरह से बिंदु को याद करता है। दिए गए उदाहरण में अंतिम स्थिति को याद किया जाना असंभव है । आप यह भी कह सकते हैं कि जानबूझकर चुनने के लिए! = ओवर <इस तथ्य का एक मजबूत दावा करना है। एक जोखिम को कम करना जो निश्चित रूप से मौजूद नहीं है, मेरे लिए एक कोड गंध है। (ऐसा कहने के बाद, आप समान रूप से यह तर्क दे सकते हैं कि <यह मुहावरेदार है, कि यह उतना ही अच्छा है जितना कि इसे इस्तेमाल करने का एक कारण।)
इयान गोल्डबी

95

कोई तकनीकी कारण नहीं है। लेकिन जोखिम, रखरखाव और कोड की बेहतर समझ का शमन है।

<या >अधिक से !=अधिक मामलों में सटीक प्रतिबंधों को पूरा करने के लिए मजबूत होते हैं (मैं सभी व्यावहारिक मामलों में भी कहूंगा)।

यहाँ डुप्लिकेट प्रश्न है ; और एक दिलचस्प जवाब


6
कुछ प्रकार हैं, जैसे कि पुनरावृत्तियाँ, जो <या> का समर्थन नहीं करते हैं, लेकिन समर्थन == और! = करते हैं।
सिमोन बी

1
यह इंट के साथ लूप के लिए है । कोई चलने वाला नहीं।
ईली

7
"लेकिन जोखिम, रखरखाव और कोड की बेहतर समझ का शमन है।" जिनमें से सभी, ठीक से, तकनीकी कारण हैं। :-)
टीजे क्राउडर

@TJCrowder यह किस प्रकार का कारण है जब आप केवल इस बारे में बात करना चाहते हैं कि मशीनें परिणामस्वरूप क्या करेंगी?
ब्रिलियन्ड

1
@DanSheppard मैं आम तौर पर व्यावसायिक कारणों से जोखिम और रखरखाव की शमनता और कोड की बेहतर समझ को एक सामाजिक कारण मानता हूं (हालांकि उन कारणों को इस मामले में तकनीकी मामले में लागू किया जा रहा है)। "जोखिम की बाध्यता" विचार किसी भी तरह से तकनीकी मामलों तक सीमित नहीं हैं, और "कोड की बेहतर समझ" विचार बदल सकते हैं यदि आप अपने आप को लोगों के एक अलग समूह के साथ काम करते हुए पाते हैं (भले ही इसमें शामिल मशीनें बिल्कुल भी नहीं बदलती हैं। )।
ब्रिलियनड

85

हाँ एक कारण है। यदि आप लूप के लिए (सादा पुराना सूचकांक आधारित) इस तरह लिखते हैं

for (int i = a; i < b; ++i){}

तो यह रूप में के किसी भी मूल्यों के लिए उम्मीद से काम करता है aऔर b(यानी शून्य पुनरावृत्तियों जब a > bअनंत के बजाय अगर आप का इस्तेमाल किया था i == b;)।

दूसरी ओर, पुनरावृत्तियों के लिए आप लिखेंगे

for (auto it = begin; it != end; ++it) 

क्योंकि किसी भी पुनरावृत्ति को लागू करना चाहिए operator!=, लेकिन प्रत्येक पुनरावृत्त के लिए यह संभव नहीं है कि वह प्रदान करे operator<

सीमा-आधारित छोरों के लिए भी

for (auto e : v)

केवल फैंसी चीनी नहीं हैं, लेकिन वे गलत तरीके से गलत कोड लिखने की संभावना को कम करते हैं।


4
अच्छा उदाहरण है। मुझे !=इसके बजाय एक मामले में दिलचस्पी होगी <। मैंने व्यक्तिगत रूप से कभी ऐसा नहीं किया जो मुझे लगता है।
ऐली

@ एलिसिन मुझे एक अच्छा नहीं मिला, और मैं एक बुरा पोस्ट नहीं करना चाहता: कल्पना करो कि आपके पास किसी प्रकार का परिपत्र कंटेनर है, जहां आप + x मोडुलो द्वारा कंटेनर एन के आकार में वृद्धि करते हैं और जब आप लूप को रोकना चाहते हैं एक निश्चित सूचकांक तक पहुँचने .... अच्छी तरह से एक बहुत बुरा उदाहरण है। शायद मुझे एक बेहतर मिल जाएगा
idclev 463035818

एक ही लूप के साथ! = <के बजाय यह स्पष्ट करता है कि इस संदर्भ में <(या>) का क्या फायदा है। for (int i=a; i != b; i++) {}
पॉल स्मिथ

10
!=पुनरावृत्तियों के अलावा कुछ भी उपयोग करना काफी खतरनाक है, क्योंकि कभी-कभी पुनरावृत्तियों की तुलना में कम हो सकता है (यह उदाहरण के लिए एक संकेतक है) लेकिन तुलना अर्थहीन है (यह एक लिंक की गई सूची है)।
ज़ेन लिंक्स

1
सफेद स्थान का उपयोग करना सीखें, गंभीरता से।
माइल्स राउत

70

आपके पास कुछ हो सकता है

for(int i = 0; i<5; ++i){
    ...
    if(...) i++;
    ...
}

यदि आपका लूप वैरिएबल इनर कोड द्वारा लिखा गया है, तो i!=5वह लूप को तोड़ नहीं सकता है। यह असमानता की जाँच करने के लिए अधिक सुरक्षित है।

पठनीयता के बारे में संपादित करें । असमानता का तरीका अधिक बार उपयोग किया जाता है। इसलिए, यह पढ़ने में बहुत तेज है क्योंकि समझने के लिए कुछ विशेष नहीं है (मस्तिष्क का भार कम हो जाता है क्योंकि कार्य सामान्य है)। इसलिए इन आदतों का उपयोग करना पाठकों के लिए अच्छा है।


6
इस प्रकार की आंतरिक "अगर (स्थिति) तो i ++" पहली चीज है जिसके बारे में मैंने सोचा था।
वर्नरसीडी

3
यह सबसे अधिक मतदान का जवाब होने की उम्मीद में आया था; मुझे आश्चर्य हुआ कि मुझे इसे खोजने के लिए दूर तक स्क्रॉल करना पड़ा। यह "अच्छी तरह से, आपको सबसे मजबूत स्थिति का उपयोग करना चाहिए" की तुलना में नौसिखिया प्रोग्रामर को समझाने की दिशा में बहुत कुछ करता है। अन्य उत्तर, यदि वे शीर्ष पर रहते हैं, तो इसे ओपी के प्रस्तावित कोड के साथ क्या गलत हो सकता है, इसकी स्पष्ट और स्पष्ट व्याख्या के रूप में शामिल करना चाहिए।
एमएसथ जूल

1
@msouth मैं पूरी तरह सहमत हूं, लेकिन मेरा पीओवी काफी व्यक्तिपरक है;)
जोहान डी।

3
@msouth मुझे यह पसंद है जब अप्रत्याशित उत्पादन व्यवहार मेरे कीड़े को उजागर करता है, है न? :-)
डेवॉर्ड

3
@msouth देखो, हमें बस यही करना है कि कभी कोई गलती न हो और सबकुछ ठीक हो जाए। साधारण।
डेवॉर्ड

48

और आखिरी लेकिन कम से कम नहीं, इसे रक्षात्मक प्रोग्रामिंग कहा जाता है , जिसका अर्थ है कार्यक्रम को प्रभावित करने वाली वर्तमान और भविष्य की त्रुटियों से बचने के लिए हमेशा सबसे मजबूत मामला लेना।

एकमात्र मामला जहां रक्षात्मक प्रोग्रामिंग की आवश्यकता नहीं है, जहां राज्यों को पूर्व और बाद की स्थितियों से साबित किया गया है (लेकिन फिर, यह साबित करना सभी प्रोग्रामिंग का सबसे रक्षात्मक है)।


2
इसके समर्थन में एक अच्छा उदाहरण: मेमोरी विकिरण के कारण होने वाले बिट फ्लैप ( एसईयू ) की चपेट में है । intकिसी i != 15स्थिति के लिए उपयोग करते समय , काउंटर लंबे समय तक चल रहा होगा यदि चौथी बिट के ऊपर कुछ भी फ़्लिप किया जाता है, खासकर मशीनों पर जहां sizeof(int)64 है। एसईयू उच्च ऊंचाई पर या अंतरिक्ष में एक बहुत ही वास्तविक चिंता है (उच्च विकिरण के कारण) , या बड़े सुपर कंप्यूटरों में (क्योंकि बहुत स्मृति मौजूद है)।
जोश सैनफोर्ड

2
यह सोचते हुए कि आपका कार्यक्रम ठीक चलेगा जब विकिरण बदल रहा है आपकी याददाश्त एक आशावादी तरीका है और सोच का एंटीकैस्ट्रोफिक तरीका है ... अच्छी टिप्पणी! :)
लुइस कोलोराडो

37

मैं तर्क दूंगा कि एक अभिव्यक्ति की तरह

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

अधिक है आशय का अर्थपूर्ण है की तुलना में

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

पूर्व स्पष्ट रूप से कहता है कि हालत एक सीमा पर एक विशेष ऊपरी सीमा के लिए एक परीक्षण है; उत्तरार्द्ध एक बाहर निकलने की स्थिति का एक द्विआधारी परीक्षण है। और अगर लूप का शरीर गैर-तुच्छ है, तो यह स्पष्ट नहीं हो सकता है कि सूचकांक केवल forबयान में ही संशोधित किया गया है।


13
"मैं चाहता हूं कि यह लूप अधिकतम 5 बार चल सके" बनाम "मैं इस लूप को कई बार आवश्यक रूप से चलाना चाहता हूं, बिल्कुल 5 बार को छोड़कर, जो मैं नहीं चाहता।"
बिशप

एक सीमा पर ऊपरी बाउंड का उल्लेख करने के लिए +1। मुझे लगता है कि यह संख्यात्मक श्रेणियों के लिए महत्वपूर्ण है। ! = इन जैसे लूप के लिए एक उचित रेंज को परिभाषित नहीं करता है
तत्व 11

22

Iterators एक महत्वपूर्ण मामला है जब आप सबसे अधिक बार !=अंकन का उपयोग करते हैं:

for(auto it = vector.begin(); it != vector.end(); ++it) {
 // do stuff
}

दी गई: व्यवहार में, मैं उसी पर निर्भर रहना लिखूंगा range-for:

for(auto & item : vector) {
 // do stuff
}

लेकिन बात बनी हुई है: एक आम तौर पर का उपयोग ==कर पुनरावृत्तियों की तुलना या !=


2
Iterators अक्सर केवल समानता / असमानता की धारणा रखते हैं और एक आदेश नहीं देते हैं, यही कारण है कि आप !=उनके लिए उपयोग करते हैं। उदाहरण के लिए, std::vectorआप इसमें उपयोग कर सकते हैं <जैसे कि सूचक इंडेक्स / पॉइंटर से बंधा हुआ है, लेकिन std::setइसमें ऐसा कोई सख्त आदेश नहीं है, क्योंकि यह एक द्विआधारी पेड़ चलता है।
मार्टिन सी।

19

लूप स्थिति एक लागू लूप अपरिवर्तनीय है।

मान लीजिए कि आप लूप के शरीर को नहीं देखते हैं:

for (int i = 0; i != 5; ++i)
{
  // ?
}

इस मामले में, आप लूप पुनरावृत्ति की शुरुआत में जानते हैं जो iबराबर नहीं है 5

for (int i = 0; i < 5; ++i)
{
  // ?
}

इस मामले में, आप लूप पुनरावृत्ति की शुरुआत में जानते हैं जो iइससे कम है 5

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

आप प्रोग्राम की स्थिति के बारे में अधिक जानते हैं, कम कोड पढ़ने से, साथ की <तुलना में !=। और आधुनिक सीपीयू पर, वे उतना ही समय लेते हैं जितना कोई अंतर नहीं होता है।

यदि आपके iलूप शरीर में हेरफेर नहीं किया गया था, और इसे हमेशा 1 से बढ़ाया गया था, और यह कम से कम शुरू हुआ 5, कोई अंतर नहीं होगा। लेकिन यह जानने के लिए कि क्या इसमें हेरफेर किया गया है, आपको इनमें से प्रत्येक तथ्य की पुष्टि करनी होगी।

इनमें से कुछ तथ्य अपेक्षाकृत आसान हैं, लेकिन आप गलत हो सकते हैं। लूप के पूरे शरीर की जांच करना, हालांकि, एक दर्द है।

C ++ में आप एक indexesप्रकार लिख सकते हैं जैसे:

for( const int i : indexes(0, 5) )
{
  // ?
}

दोनों ऊपर के forछोरों में से एक के रूप में एक ही बात करता है , यहां तक ​​कि एक ही कोड के लिए इसे अनुकूलित करने वाले कंपाइलर के नीचे। हालांकि, आप जानते हैं कि iलूप के शरीर में हेरफेर नहीं किया जा सकता है, क्योंकि यह घोषित किया गया है const, बिना कोड भ्रष्ट मेमोरी।

अधिक जानकारी आप संदर्भ को समझने के बिना कोड की एक पंक्ति से बाहर निकल सकते हैं, यह आसान है कि नीचे क्या गलत हो रहा है। <पूर्णांक छोरों के मामले में आपको उस रेखा पर कोड की स्थिति के बारे में अधिक जानकारी मिलती !=है।


13

हाँ; OpenMP !=स्थिति के साथ छोरों को समानांतर नहीं करता है ।


13

ऐसा हो सकता है कि चर iकुछ बड़े मूल्य पर सेट है और यदि आप बस !=ऑपरेटर का उपयोग करते हैं तो आप एक अंतहीन लूप में समाप्त हो जाएंगे।


1
वास्तव में अंतहीन नहीं - सी के अधिकांश कार्यान्वयन पर, iचुपचाप चारों ओर लपेटेंगे जब इसकी अधिकतम पर। लेकिन हाँ, सबसे अधिक संभावना है कि आप प्रतीक्षा करने के लिए तैयार हैं।
usr2564301

12

जैसा कि आप अन्य कई उत्तरों से देख सकते हैं, इसके बजाय <का उपयोग करने के कारण हैं! = जो किनारे के मामलों, प्रारंभिक स्थितियों, अनपेक्षित लूप काउंटर संशोधन, आदि में मदद करेगा ...

ईमानदारी से, मुझे नहीं लगता कि आप सम्मेलन के महत्व पर जोर दे सकते हैं। इस उदाहरण के लिए अन्य प्रोग्रामर के लिए यह देखना काफी आसान होगा कि आप क्या करने की कोशिश कर रहे हैं, लेकिन यह एक दोहरे कारण का कारण होगा। प्रोग्रामिंग करते समय नौकरियों में से एक यह संभव के रूप में पढ़ने योग्य और सभी के लिए परिचित है, इसलिए अनिवार्य रूप से जब किसी को आपके कोड को अपडेट / बदलना होता है, तो यह पता लगाने में बहुत प्रयास नहीं करते हैं कि आप विभिन्न कोड ब्लॉक में क्या कर रहे थे । अगर मैंने किसी को उपयोग करते देखा !=, तो मैं मान सकता हूँ कि एक कारण था कि वे इसके बजाय इसका इस्तेमाल करते थे <और अगर यह एक बड़ा लूप होता तो मैं पूरी चीज़ों के माध्यम से यह पता लगाने की कोशिश करता कि आपने ऐसा क्या किया है जो आवश्यक हो ... और वह व्यर्थ समय।


12

जैसा कि इयान न्यूज़न ने पहले ही कहा था, आप एक अस्थायी चर पर विश्वसनीय रूप से लूप नहीं कर सकते हैं और साथ बाहर निकल सकते हैं !=। उदाहरण के लिए,

for (double x=0; x!=1; x+=0.1) {}

वास्तव में हमेशा के लिए लूप होगा, क्योंकि 0.1 को फ़्लोटिंग पॉइंट में बिल्कुल नहीं दिखाया जा सकता है, इसलिए काउंटर संकीर्ण रूप से छूट जाता है। 1. साथ < जाता है। समाप्त हो जाता है।

(ध्यान दें कि यह मूल रूप से अपरिभाषित व्यवहार है कि क्या आपको 0.9999 मिलता है ... अंतिम स्वीकृत संख्या के रूप में - किस तरह की धारणा से कम उल्लंघन करता है - या पहले से ही 1.0000000000000001 पर बाहर निकलें।)


10

मैं विशेषण "तकनीकी" का अर्थ भाषा व्यवहार / क्वर्क और संकलक साइड इफेक्ट्स जैसे कि उत्पन्न कोड के प्रदर्शन से लेता हूं।

यह अंत करने के लिए, जवाब है: नहीं (*)। (*) "कृपया अपने प्रोसेसर मैनुअल से परामर्श करें"। यदि आप कुछ एज-केस RISC या FPGA सिस्टम के साथ काम कर रहे हैं, तो आपको यह जांचने की आवश्यकता हो सकती है कि क्या निर्देश उत्पन्न होते हैं और उनकी लागत क्या है। लेकिन अगर आप किसी भी पारंपरिक आधुनिक वास्तुकला का उपयोग कर रहे हैं, तो , और , और lt, लागत में कोई महत्वपूर्ण प्रोसेसर स्तर अंतर नहीं है ।eqnegt

यदि आप एक बढ़त मामले का उपयोग कर रहे आप पा सकते हैं कि !=तीन परिचालन (की आवश्यकता है cmp, not, beq) दो (बनाम cmp, blt xtr myo)। फिर, उस मामले में आरटीएम।

अधिकांश भाग के लिए, कारण रक्षात्मक / सख्त होते हैं, खासकर जब संकेत या जटिल छोरों के साथ काम करते हैं। विचार करें

// highly contrived example
size_t count_chars(char c, const char* str, size_t len) {
    size_t count = 0;
    bool quoted = false;
    const char* p = str;
    while (p != str + len) {
        if (*p == '"') {
            quote = !quote;
            ++p;
        }
        if (*(p++) == c && !quoted)
            ++count;
    }
    return count;
}

एक कम वंचित उदाहरण वह होगा जहां आप वेतन वृद्धि करने के लिए रिटर्न मान का उपयोग कर रहे हैं, उपयोगकर्ता से डेटा स्वीकार करना:

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i != len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;

        std::cin >> step;
        i += step; // here for emphasis, it could go in the for(;;)
    }
}

इसे आज़माएं और 1, 2, 10, 999 मानों को इनपुट करें।

आप इसे रोक सकते हैं:

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i != len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;
        std::cin >> step;
        if (step + i > len)
            std::cout << "too much.\n";
        else
            i += step;
    }
}

लेकिन जो आप शायद चाहते थे

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i < len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;
        std::cin >> step;
        i += step;
    }
}

एक कन्वेंशन बायस की ओर भी कुछ है <, क्योंकि मानक कंटेनरों में ऑर्डर करना अक्सर निर्भर करता है operator<, उदाहरण के लिए कई एसटीएल कंटेनरों में हैशिंग कहकर समानता का निर्धारण करते हैं

if (lhs < rhs) // T.operator <
    lessthan
else if (rhs < lhs) // T.operator < again
    greaterthan
else
    equal

यदि lhsऔर rhsकोई उपयोगकर्ता परिभाषित वर्ग है जो इस कोड को लिख रहा है

if (lhs < rhs) // requires T.operator<
    lessthan
else if (lhs > rhs) // requires T.operator>
    greaterthan
else
    equal

कार्यान्वयनकर्ता को दो तुलनात्मक कार्य करने होंगे। इसलिए <पसंदीदा ऑपरेटर बन गया है।


पठनीयता के लिए i = = चरण नियंत्रण भाग के लिए होना चाहिए। अगर आप कदम रखेंगे = 0
मिकेल क्रिस्टियनसेन

1
हालांकि यह अच्छे कोड की पठनीयता में मदद करेगा, मैं गलत संस्करण में दोष पर जोर देना चाहता था
kfsone

9

किसी भी तरह के कोड (आमतौर पर) को लिखने के कई तरीके हैं, इस मामले में बस दो तरीके होते हैं (तीन यदि आप <= और> = गिनते हैं)।

इस मामले में, लोग यह सुनिश्चित करने के लिए> और <पसंद करते हैं कि भले ही कुछ अप्रत्याशित लूप में हो (जैसे बग), यह असीम रूप से लूप नहीं करेगा (बीएडी)। उदाहरण के लिए, निम्नलिखित कोड पर विचार करें।

for (int i = 1; i != 3; i++) {
    //More Code
    i = 5; //OOPS! MISTAKE!
    //More Code
}

यदि हम (i <3) का उपयोग करते हैं, तो हम एक अनंत लूप से सुरक्षित होंगे क्योंकि इसने एक बड़ा प्रतिबंध लगा दिया था।

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

उम्मीद है कि इस मदद की!


कोई तर्क दे सकता है कि अनंत लूप गलती का एक अच्छा संकेतक होगा, लेकिन फिर एक और तर्क देगा कि i = 5 जरूरी नहीं कि एक गलती हो
njzk2

7

उपयोग करने का सबसे आम कारण < सम्मेलन है। अधिक प्रोग्रामर इस तरह से छोरों के बारे में सोचते हैं "जब तक सूचकांक" सीमा में है "तब तक" जब तक कि सूचकांक अंत तक नहीं पहुंचता है। " जब आप कर सकते हैं तो मूल्य सम्मेलन से चिपके रहते हैं।

दूसरी ओर, कई उत्तर यहां दावा कर रहे हैं कि <फार्म का उपयोग करने से कीड़े से बचने में मदद मिलती है। मेरा तर्क है कि कई मामलों में यह सिर्फ छिपाने में मदद करता है कीड़े । यदि लूप इंडेक्स को अंतिम मान तक पहुंचने के लिए माना जाता है, और, इसके बजाय, यह वास्तव में इससे आगे निकल जाता है, तो ऐसा कुछ हो रहा है जिसकी आपको उम्मीद नहीं थी, जिससे खराबी हो सकती है (या किसी अन्य बग का साइड इफेक्ट हो सकता है)। <संभावना बग की खोज में विलंब होगा। !=अधिक एक स्टाल, लटका, या यहाँ तक कि एक दुर्घटना है, जो आप बग जल्दी ही स्थान में मदद मिलेगी के लिए नेतृत्व की संभावना है। जितनी जल्दी एक बग पाया जाता है, उतना ही सस्ता इसे ठीक करना है।

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

उदाहरण के लिए, यदि आप एक सादे सी स्ट्रिंग के माध्यम से कदम रख रहे हैं, तो यह आम तौर पर लिखने के लिए अधिक सामान्य है:

for (char *p = foo; *p != '\0'; ++p) {
  // do something with *p
}

से

int length = strlen(foo);
for (int i = 0; i < length; ++i) {
  // do something with foo[i]
}

एक चीज के लिए, यदि स्ट्रिंग बहुत लंबी है, तो दूसरा रूप धीमा होगा क्योंकि strlenस्ट्रिंग के माध्यम से एक और पास है।

C ++ std :: string के साथ, आप लूप के लिए रेंज-आधारित, एक मानक एल्गोरिथ्म या पुनरावृत्तियों का उपयोग करेंगे, भले ही लंबाई आसानी से उपलब्ध हो। यदि आप पुनरावृत्तियों का उपयोग कर रहे हैं, तो सम्मेलन का उपयोग !=इसके बजाय करना है <:

for (auto it = foo.begin(); it != foo.end(); ++it) { ... }

इसी तरह, एक पेड़ या एक सूची या एक छलावे का पुनरावृत्ति करना आमतौर पर जाँच के बजाय एक सूचक या अन्य प्रहरी के लिए देखना शामिल होता है कि क्या कोई सूचकांक एक सीमा के भीतर रहता है।


3
आप प्रोग्रामिंग में मुहावरे के महत्व पर जोर देने के लिए काफी सही हैं। अगर मैं कुछ कोड को देखता हूं और इसका एक परिचित पैटर्न है, तो मुझे पैटर्न का उल्लेख करने के लिए समय बर्बाद करने की आवश्यकता नहीं है, लेकिन सीधे इसके मूल में जा सकते हैं। मुझे लगता है कि योडा की तुलना के साथ मेरी मुख्य पकड़ है - वे मुहावरेदार नहीं लगते हैं, इसलिए मैं अंत में उन्हें दो बार पढ़ने के लिए सुनिश्चित करता हूं कि उनका मतलब है कि मुझे लगता है कि उनका मतलब है।
टोबे स्पाइट

7

इस निर्माण का उपयोग नहीं करने का एक कारण फ्लोटिंग पॉइंट नंबर है। !=फ्लोट्स के साथ उपयोग करने के लिए एक बहुत ही खतरनाक तुलना है क्योंकि यह शायद ही कभी सच का मूल्यांकन करेगा भले ही संख्या समान दिखें। <या >इस जोखिम को दूर करता है।


यदि आपका लूप इटरेटर एक फ्लोटिंग पॉइंट नंबर है, तो !=बनाम <आपकी समस्याओं में से सबसे कम है।
लुंडिन

7

इस प्रथा का पालन करने के लिए दो संबंधित कारण हैं कि दोनों को इस तथ्य के साथ करना है कि एक प्रोग्रामिंग भाषा है, आखिरकार, एक ऐसी भाषा जो मनुष्यों द्वारा पढ़ी जाएगी (दूसरों के बीच)।

(१) थोड़ी सी अतिरेक। प्राकृतिक भाषा में, हम आमतौर पर कड़ाई से आवश्यक जानकारी प्रदान करते हैं, एक त्रुटि सुधार कोड की तरह। यहाँ अतिरिक्त जानकारी यह है कि लूप वैरिएबल i(देखें कि मैंने यहाँ अतिरेक का उपयोग कैसे किया? यदि आप नहीं जानते कि 'लूप वैरिएबल' का क्या अर्थ है, या यदि आप लूप वेरिएबल पढ़ने के बाद चर का नाम भूल गए हैं, तोi " को तो आपके पास पूर्ण है जानकारी) लूप के दौरान 5 से कम है, न कि केवल 5 से अलग। अतिरेक पठनीयता को बढ़ाता है।

(२) कन्वेंशन। भाषाओं में कुछ स्थितियों को व्यक्त करने के विशिष्ट मानक तरीके हैं। यदि आप कुछ कहने के स्थापित तरीके का पालन नहीं करते हैं, तो भी आपको समझ में आ जाएगा, लेकिन आपके संदेश के प्राप्तकर्ता के लिए प्रयास अधिक है क्योंकि कुछ अनुकूलन काम नहीं करेंगे। उदाहरण:

गर्म मैश के आसपास बात मत करो। बस कठिनाई रोशन!

पहला वाक्य जर्मन मुहावरे का शाब्दिक अनुवाद है। दूसरा एक सामान्य अंग्रेजी मुहावरा है जिसमें मुख्य शब्दों को पर्यायवाची शब्दों से बदल दिया गया है। परिणाम समझ में आता है, लेकिन इसे समझने में बहुत अधिक समय लगता है:

झाड़ी के आसपास मत मारो। बस समस्या की व्याख्या करें!

अंग्रेजी मुहावरे में पारंपरिक शब्दों की तुलना में स्थिति को बेहतर बनाने के लिए पहले संस्करण में प्रयुक्त पर्यायवाची शब्द होने पर भी यह सच है। जब प्रोग्रामर कोड पढ़ते हैं तो इसी तरह की ताकत लागू होती है। यह भी क्यों है 5 != iऔर 5 > iइसे लगाने के अजीब तरीके हैं जब तक कि आप एक ऐसे वातावरण में काम नहीं कर रहे हैं जिसमें यह सामान्य i != 5और i < 5इस तरह से स्वैप करने के लिए मानक है । इस तरह के बोली समुदाय मौजूद हैं, शायद इसलिए कि संगति 5 == iके कारण प्राकृतिक लेकिन त्रुटि प्रवण के बजाय लिखना आसान हो जाता है i == 5


1
Ausgezeichnet । इसी तरह, कोई i < 17+(36/-3)भी परीक्षा को नहीं लिखेगा (भले ही ये स्थिरांक अन्यत्र उपयोग किए गए हों; तब आपको इनका नाम स्पष्टता के लिए लिखना चाहिए !)।
usr2564301

6

ऐसे मामलों में संबंधपरक तुलनाओं का उपयोग करना किसी भी चीज़ की तुलना में अधिक लोकप्रिय आदत है। इसने अपनी लोकप्रियता उस समय में वापस प्राप्त की जब इस तरह के वैचारिक श्रेणियों के रूप में पुनरावृत्तियां और उनकी तुलना को उच्च प्राथमिकता नहीं माना जाता था।

मैं कहूंगा कि जब भी संभव हो, रिलेशनल तुलना के बजाय समानता तुलना का उपयोग करना पसंद करना चाहिए, क्योंकि समानता तुलना मूल्यों की तुलना में कम आवश्यकताओं को लागू करती है। होने के नाते EqualityComparable जा रहा है की तुलना में कम आवश्यकता है LessThanComparable

एक अन्य उदाहरण है कि इस तरह के संदर्भों में समानता तुलना के व्यापक प्रयोज्यता दर्शाता है को लागू करने के साथ लोकप्रिय पहेली है unsignedयात्रा करने के लिए नीचे 0। यह के रूप में किया जा सकता है

for (unsigned i = 42; i != -1; --i)
  ...

ध्यान दें कि उपरोक्त हस्ताक्षरित और अहस्ताक्षरित पुनरावृत्ति दोनों के लिए समान रूप से लागू है, जबकि संबंधपरक संस्करण अहस्ताक्षरित प्रकारों के साथ टूट जाता है।


2

उदाहरणों के अलावा, जहां लूप वैरिएबल (अनजाने में) शरीर के अंदर बदल जाता है, छोटे-से-अधिक या अधिक से अधिक संचालकों का उपयोग करने के लिए अन्य आश्वासन हैं:

  • नकारात्मकता कोड को समझने में कठिन बनाती है
  • <या >केवल एक चार है, लेकिन !=दो

4
दूसरी गोली सबसे अच्छा कारण है। कोड सही और स्पष्ट होना चाहिए। कॉम्पैक्ट बहुत कम महत्वपूर्ण है।
जोनाथन लेफ़लर

@JonathanLeffler खैर, TDD REPL में, अतिरिक्त चरित्र पार्सिंग के लिए एक अतिरिक्त नैनो-सेकंड है, और लेखन के कारण बग को खोजने के लिए एक अरब पुनरावृत्तियों का समय है 5 != $i, कि मेरे जीवन का सिर्फ एक सेकंड पूरा हुआ। उह ... छलनी
बिशप

1

विभिन्न लोगों के अलावा जिन्होंने उल्लेख किया है कि यह जोखिम को कम करता है, यह विभिन्न मानक पुस्तकालय घटकों के साथ बातचीत करने के लिए आवश्यक फ़ंक्शन ओवरलोड की संख्या को भी कम करता है। एक उदाहरण के रूप में, यदि आप चाहते हैं कि आपका प्रकार std::setकिसी के लिए महत्वपूर्ण है std::map, या एक कुंजी के रूप में उपयोग किया जाता है , या कुछ खोज और सॉर्टिंग एल्गोरिदम के साथ उपयोग किया जाता है, तो मानक पुस्तकालय आमतौर पर std::lessवस्तुओं की तुलना करने के लिए उपयोग करता है क्योंकि अधिकांश एल्गोरिदम को केवल एक सख्त कमजोर आदेश की आवश्यकता होती है । इस प्रकार <तुलना के बजाय तुलना का उपयोग करना एक अच्छी आदत बन जाती है !=(जहां यह समझ में आता है, निश्चित रूप से)।


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

0

वाक्यविन्यास परिप्रेक्ष्य से कोई समस्या नहीं है, लेकिन उस अभिव्यक्ति के पीछे तर्क 5!=iध्वनि नहीं है।

मेरी राय में, !=लूप की सीमा निर्धारित करने के लिए उपयोग करना तार्किक रूप से ध्वनि नहीं है क्योंकि लूप के लिए या तो वृद्धि सूचकांक में वृद्धि या घटती है, इसलिए लूप को पुनरावृति तक सेट करना जब तक कि पुनरावृत्ति सूचकांक सीमा से बाहर न हो जाए (!= कुछ करने के लिए) उचित कार्यान्वयन।

यह काम करेगा, लेकिन जब इसका उपयोग करते समय सीमा डेटा हैंडलिंग खो जाती है तो यह दुर्व्यवहार का खतरा होता है != (जिसका अर्थ है कि आप शुरू से ही पता है कि यह वेतन वृद्धि या decrements) एक वृद्धिशील समस्या के लिए, है यही कारण है कि बजाय उपयोग किया जाता है।!=<>>==>


2
तर्क बिलकुल ठीक है। जब iहै 5पाश बाहर निकलता है। क्या आपके कहने का मतलब कुछ और था?
डैन गेट्ज़

1
यदि गर्मी के कारण डेटा सही तरीके से स्थानांतरित नहीं होता है, तो इलेक्ट्रोमैग्नेटिक आपके कोड को हमेशा के लिए चलाता है। यदि आप ईसीसी रैम के साथ एक नियमित वर्कस्टेशन या सर्वर पर ऐसा करते हैं तो कोई समस्या नहीं है (न ही तार्किक, तकनीकी और न ही भौतिक)
मार्कस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.