{}} जबकि (झूठा)


125

मैं एक व्यक्ति द्वारा कुछ कोड देख रहा था और उसने देखा कि उसके कार्यों में एक पैटर्न है:

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

यह बुरा नहीं है , अधिक अजीब (वास्तविक कोड काफी साफ और भद्दा है)। यह कुछ ऐसा नहीं है जिसे मैंने पहले देखा है और मुझे आश्चर्य है कि क्या कोई इसके पीछे किसी तर्क के बारे में सोच सकता है - एक अलग भाषा में पृष्ठभूमि?


2
क्या आपने इसे "सामान्य" संस्करण में बदलने की कोशिश की है और देखते हैं कि क्या यह अभी भी संकलित है? यदि यह सामान्य रूप से लिखे जाने पर संकलित करने में विफल रहता है, तो संकलक त्रुटि इस बात का सुराग दे सकती है कि ऐसा क्यों किया गया था।
मार्क बायर्स

11
उसके इरादे पर हमें अनुमान लगाने के बजाय "व्यक्तिगत" क्यों नहीं पूछा?

1
हो सकता है कि उनके प्रोफेसर को उनके उपयोग की आवश्यकता हो do...while()और उन्होंने उस कोड का उपयोग फ़ंक्शन टेम्पलेट के रूप में किया हो।
होगन

6
@ नील ... मैं जब मैं उससे भिड़ता हूं तो वह गूंगा दिखने से बचना चाहता है और वह सुपर-उन्नत सी ++ उपयोग के बारे में बताता है जिसके बारे में मैंने कभी नहीं सोचा था।
मिस्टर बॉय

6
लगता है कि पहले से ही कुछ अलग-अलग उत्तर हैं, क्या आप मूल लेखक से पूछ सकते हैं कि उनके इरादे क्या थे और वापस पोस्ट करें?
nevets1219

जवाबों:


175

आप breakबाहर कर सकते हैंdo{...}while(false)


95
+1 क्योंकि यह संभवतः कोड का आशय है, लेकिन ऐसा कुछ करना केवल एक मूर्खतापूर्ण रूप से प्रच्छन्न गोटो है। यदि आपको लगता है कि एक गोटो नौकरी के लिए सही उपकरण है, तो आपको बस एक # $ (* # @ गोटो का उपयोग करना चाहिए।
dschacha

55
यह एक प्रच्छन्न गोटो से अधिक है। यह एक प्रतिबंधित (संरचित) गोटो है।
थॉमस ईडिंग

19
किस तरह से यह "प्रतिबंधित" है? केवल आगे की ओर कूदना शायद ही "प्रतिबंध" है। एक गोटो एक गोटो है, और एक को ड्रेसिंग करने के लिए यह देखो कि यह एक ऐसा नहीं है जो सिर्फ एक गोटो को पहली जगह का उपयोग करने से भी बदतर है।
आनन।

44
@ बंदूक: आगे की ओर कूदना एक गोटो पर प्रतिबंध है, और बाहर कूदना निश्चित रूप से प्रतिबंध है। गोटो के साथ वास्तविक समस्या स्पेगेटी कोड है, और आगे और बाहर कूद की सीमा बहुत अधिक है।
डेविड थॉर्नले

33
एक वास्तविक लूप शब्दार्थ रूप से गोटो नहीं है। सशर्त एक शब्दार्थ नहीं है। "समारोह के अंत में जाना और सफाई कोड करना" है शब्दार्थ एक गोटो। जब शब्दार्थ लागू होते हैं, तो गोटो का उपयोग करें, कुछ अलग शब्द न करें क्योंकि आप उनसे डरते हैं।
आनन।

126

बहुत सारे लोग बताते हैं कि इसका उपयोग अक्सर "गोटो" लिखने के अजीब तरीके से किया जाता है। यह शायद सच है अगर यह सीधे फ़ंक्शन में लिखा है।

एक मैक्रो में, OTOH, do { something; } while (false)मैक्रो इनवोकेशन के बाद अर्धविराम के लिए एक सुविधाजनक तरीका है, बिल्कुल किसी अन्य टोकन का पालन करने की अनुमति नहीं है।

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


18
मैक्रोज़ में इसकी उपयोगिता का उल्लेख करने के लिए +1; मुझे आश्चर्य है कि किसी और ने उल्लेख नहीं किया है!
निक मेयर

7
हां, स्थूल चीज वास्तव में इस का पूरी तरह से वैध उपयोग है। ); बेशक, बाहर मैक्रो की, यह सिर्फ मूर्ख है ...
jalf

12
यह अजीब नहीं है, यह उपयोगी है, क्योंकि यह एक स्कॉप्ड गोटो है - इसका मतलब है कि आपके द्वारा लूप में घोषित कोई भी चर नष्ट हो जाता है, जबकि गोटो ऐसा नहीं करता है।
एना बेट्स

9
@ पाओल: कुछ भी नहीं आपको इस व्यवहार को गोटो के साथ मजबूर करने के लिए बयानों के एक समूह के आसपास ब्रेसिज़ जोड़ने से रोकता है।
erkkallen

5
@Paul: एक ब्लॉक के बाहर गोटो सबसे निश्चित रूप से स्थानीय चर को C ++ में नष्ट करने का कारण बनता है, जो कि ब्रेक के समान है। और सी चर में वास्तव में नष्ट नहीं कर रहे हैं, उनके ढेर अंतरिक्ष बस पुनः प्राप्त है।
बेन वोइगट

25

गोटो के रूप में ब्रेक शायद जवाब है, लेकिन मैं एक दूसरे के विचार को आगे रखूंगा।

हो सकता है कि वह स्थानीय रूप से परिभाषित चर रखना चाहता था और इस निर्माण का उपयोग एक नया दायरा पाने के लिए करता था।

याद रखें जबकि हाल ही में C ++ {...}कहीं भी अनुमति देता है , यह हमेशा ऐसा नहीं था।


30
वह उस मामले में सिर्फ घुंघराले ब्रेसिज़ का इस्तेमाल कर सकता था।
नेमेनजा ट्रिफ़ुनोविक

2
@ नीमजा, आपको आश्चर्य होगा कि कितने डेवलपर्स को यह पता नहीं है और होगन जो सुझाव दे रहे हैं उससे संबंधित कुछ करने की कोशिश करें
पोलारिस878

8
@Polaris @Nemanja, यह til नहीं था कि मैं C / C ++ में प्रोग्रामिंग कर रहा था जैसे कि मुझे 4 साल में पता चला कि आप {} कहीं भी एक नया स्थानीय दायरा बना सकते हैं .. यह switch-caseकोड में विशेष रूप से उपयोगी है
अर्ल

1
@ निमंजा: मुझे ठीक से पता नहीं है कि कब, लेकिन मुझे यकीन है कि {...}कहीं भी C ++ में अधिक आधुनिक विकास है (याद रखें कि पहले C ++ का उपयोग मैंने एक प्री-प्रोसेसर के साथ किया था और यह इस आधुनिक उपयोग की अनुमति नहीं देता है।) लेखक सिर्फ पुराने स्कूल था।
होगन

2
इसने हर जगह ब्रेसिज़ की अनुमति कब नहीं दी? मैंने 15 साल पहले प्रोग्रामिंग शुरू की थी, और तब इसकी अनुमति दी गई थी (मेरी पाठ्य पुस्तक और मेरे द्वारा संकलित प्रत्येक लेख में)।
एरिक्कलेन

20

मैंने देखा है कि यह एक उपयोगी पैटर्न के रूप में उपयोग किया जाता है जब फ़ंक्शन के लिए कई संभावित निकास बिंदु होते हैं, लेकिन फ़ंक्शन को बाहर निकलने के तरीके की परवाह किए बिना एक ही सफाई कोड की हमेशा आवश्यकता होती है।

यह एक थकाऊ बना सकता है अगर / और-अगर पेड़ को पढ़ने में बहुत आसान है, तो बस जब भी कोई निकास बिंदु तक पहुंच जाए, तो बाकी तर्क इनलाइन के साथ तोड़कर।

यह पैटर्न उन भाषाओं में भी उपयोगी है जिनके पास गोटो स्टेटमेंट नहीं है। शायद यही वह जगह है जहाँ मूल प्रोग्रामर ने पैटर्न सीखा।


15
तो बस एक पतले प्रच्छन्न गोटो के बजाय एक ईमानदार, सीधे गोटो का उपयोग करें।
dsimcha

4
मुझे यह तरीका बेहतर लगता है। यह पढ़ना आसान है और एक गोटो का कलंक नहीं है।
कैमरून

8
गोटो आसानी से और स्थानीय रूप से इस्तेमाल किया जाता है, तो पढ़ने के लिए आसान कर रहे हैं। जब वे प्रवाह नियंत्रण के मुख्य रूप थे और सैकड़ों लाइनों में कूद रहे थे, तो उन्हें अपना कलंक वापस मिल गया।
dsimcha

13
"कलंक" के कारण गोटो का उपयोग न करना कार्गो-पंथ प्रोग्रामिंग का एक निश्चित संकेत है।
आनन।

6
यह उल्लेख नहीं करने के लिए कि सफाई कोड का एक द्रव्यमान एक बुरी गंध है। यह C ++ होने के नाते, सफाई कोड आमतौर पर RAII प्रसंस्करण के दौरान बुलाया जाने वाले विध्वंसक में होना चाहिए।
डेविड थॉर्नले

12

मैंने कोड को इस तरह देखा है ताकि आप breakएक gotoप्रकार के रूप में उपयोग कर सकें ।


10

यह सिर्फ़ whileशब्दार्थ पाने के लिए एक विकृति हैgoto tidy-up गोटो शब्द का उपयोग किए बिना ।

यह खराब रूप है क्योंकि जब आप बाहरी के अंदर अन्य छोरों का उपयोग करते हैं तो पाठक के लिए अस्पष्ट हो जाता है। "क्या यह गोटो से बाहर निकलना है? या क्या इसका उद्देश्य केवल आंतरिक लूप से बाहर निकलना है?"whilebreaks


10

मुझे लगता है कि इसके breakबजाय लिखना अधिक सुविधाजनक है goto end। आपको उस लेबल के लिए एक नाम भी सोचने की ज़रूरत नहीं है जो इरादा स्पष्ट करता है: आप एक विशिष्ट नाम के साथ लेबल पर कूदना नहीं चाहते हैं। आप यहां से निकलना चाहते हैं।

इसके अलावा संभावना है कि आप वैसे भी ब्रेस की आवश्यकता होगी। तो यह do{...}while(false);संस्करण है:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

और यदि आप इसका उपयोग करना चाहते हैं तो यह आपको इसे व्यक्त करना होगा goto:

{
   // code
   if (condition) goto end;
   // more code
}
end:

मुझे लगता है कि पहले संस्करण का अर्थ समझ से बहुत आसान है। इसके अलावा लिखना आसान है, विस्तार करना आसान है, उस भाषा का अनुवाद करना आसान है जो समर्थन नहीं करती है goto, आदि।


इसके उपयोग के बारे में सबसे अधिक चिंता breakकी बात यह है कि यह एक बुरी तरह से प्रच्छन्न है goto। लेकिन वास्तव breakमें अधिक समानता है return: दोनों निर्देश कोड के एक ब्लॉक से बाहर कूदते हैं जो कि तुलना में बहुत अधिक संरचित है goto। फिर भी दोनों निर्देश कोड के एक ब्लॉक में कई निकास बिंदुओं की अनुमति देते हैं जो कभी-कभी भ्रमित हो सकते हैं। आखिरकार मैं सबसे स्पष्ट समाधान के लिए जाने की कोशिश करूंगा, जो भी विशिष्ट स्थिति में है।


ओह, मैंने अभी देखा कि मैं उत्तर देने से पहले सवाल को पूरी तरह से नहीं समझ पाया। मुझे लगा कि यह do{ ... }while(false);सामान्य रूप से उपयोग के बारे में था । लेकिन वास्तव में यह किसी तरह का अनुकरण करने के लिए इसका उपयोग करने के बारे में है try{ ... }finally{ ... }
रॉबर्ट

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

7

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


7

यह एक बहुत ही आम बात है। में सी । मैं यह सोचने की कोशिश करता हूं कि क्या आप एक तरह से खुद से झूठ बोलना चाहते हैं "मैं उपयोग नहीं कर रहा हूं goto"। इसके बारे में सोचना, gotoसमान रूप से इस्तेमाल के साथ कुछ भी गलत नहीं होगा । वास्तव में यह इंडेंटेशन स्तर को भी कम करेगा।

हालांकि, मैंने कहा, बहुत बार यह do..whileलूप बढ़ता है। और फिर वे अंदर से ifएस और elseएस प्राप्त करते हैं , कोड का प्रतिपादन वास्तव में बहुत पठनीय नहीं है, अकेले परीक्षण करने योग्य है।

वे do..whileआम तौर पर एक सफाई करने का इरादा है । हर तरह से संभव है कि मैं RAII का उपयोग करना पसंद करूं और एक छोटे से समारोह से जल्दी लौटूं । दूसरी ओर, सी आपको सी ++ के रूप में उतनी अधिक उपयुक्तता प्रदान नहीं करता है, जो एक सफाई करने के लिए सबसे अच्छा तरीका है।do..while


6

यह एक सी प्रोग्रामर की तरह दिखता है। C ++ में, स्वचालित चर में विध्वंसक होते हैं जिनका उपयोग आप साफ करने के लिए करते हैं, इसलिए वापसी से पहले कुछ भी जरूरी नहीं होना चाहिए। C में, आपके पास यह RAII मुहावरा नहीं था , इसलिए यदि आपके पास कॉमन क्लीन कोड है, तो आप या तोgoto इसे या एक बार उपयोग करें या ऊपर दिए गए लूप के माध्यम से।

C ++ मुहावरे के साथ तुलना में इसका मुख्य नुकसान यह है कि अगर शरीर में अपवाद को फेंक दिया जाए तो यह ठीक नहीं होगा। C के पास अपवाद नहीं थे, इसलिए यह कोई समस्या नहीं थी, लेकिन यह C ++ में एक बुरी आदत है।


4

कई स्पष्टीकरण। पहला आम है, दूसरा एक पैरामीटर के साथ C प्रीप्रोसेसर मैक्रोज़ के लिए विशिष्ट है:

प्रवाह नियंत्रण

मैंने इसे सादे C कोड में उपयोग किया है। मूल रूप से, यह गोटो का एक सुरक्षित संस्करण है, क्योंकि आप इससे बाहर निकल सकते हैं और सभी मेमोरी ठीक से साफ हो जाती है।

कुछ goto- कुछ अच्छा क्यों होगा ? ठीक है, अगर आपके पास कोड है जहां बहुत अधिक हर पंक्ति एक त्रुटि वापस कर सकती है, लेकिन आपको उन सभी को उसी तरह से प्रतिक्रिया करने की आवश्यकता है (जैसे कि सफाई के बाद अपने कॉलर को त्रुटि सौंपकर), यह आमतौर पर एक से बचने के लिए अधिक पठनीय हैif( error ) { /* cleanup and error string generation and return here */ } के रूप में यह साफ-सफाई कोड के दोहराव से बचा जाता है।

हालाँकि, C ++ में आपके पास इस उद्देश्य के लिए अपवाद + RAII है, इसलिए मैं इसे खराब कोडिंग शैली मानूंगा।

अर्धविराम की जाँच

यदि आप फ़ंक्शन-जैसे मैक्रो इनवोकेशन के बाद अर्धविराम भूल जाते हैं, तो तर्क अवांछित तरीके से अनुबंध कर सकते हैं और मान्य सिंटैक्स में संकलित कर सकते हैं। स्थूल की कल्पना करो

#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");

जिसे गलती से कहा जाता है

if( foo )
    PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
    doSomethingElse();

"और" के साथ संबद्ध माना जाएगा gDebugModeOn, इसलिए जब fooहैfalse , तो इसका ठीक उल्टा मतलब होगा।

अस्थायी चरों के लिए एक गुंजाइश प्रदान करना।

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

"संभवतः अवांछित अर्धविराम" चेतावनी से बचना

कुछ मैक्रोज़ केवल डीबग बिल्ड में सक्रिय होते हैं। आप उन्हें परिभाषित करते हैं:

#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n) 
#endif

अब यदि आप एक सशर्त के अंदर रिलीज बिल्ड में इसका उपयोग करते हैं, तो यह संकलन करता है

if( foo )
    ;

कई कंपाइलर इसे ऐसे ही देखते हैं

if( foo );

जो अकस्मात गलती से लिखा जाता है। तो आपको एक चेतावनी मिलती है। Do {} जबकि (झूठा) इसे संकलक से छुपाता है, और इसे एक संकेत के रूप में स्वीकार किया जाता है कि आप वास्तव में यहां कुछ नहीं करना चाहते हैं।

सशर्त द्वारा लाइनों पर कब्जा करने से बचना

पिछले उदाहरण से मैक्रो:

if( foo )
    DBG_PRINT_NUM(42)
doSomething();

अब, एक डिबग बिल्ड में, चूंकि हमने आदतन अर्धविराम को भी शामिल किया है, यह ठीक संकलन करता है। हालाँकि, रिलीज़ बिल्ड में यह अचानक बदल जाता है:

if( foo )

doSomething();

या अधिक स्पष्ट रूप से स्वरूपित

if( foo )
    doSomething();

जो बिल्कुल नहीं था, जो इरादा था। मैक्रो के चारों ओर {...} करते हुए (अनुपलब्ध) अनुपलब्ध अर्धविराम को संकलित त्रुटि में बदल देता है।

ओपी के लिए इसका क्या मतलब है?

सामान्य तौर पर, आप त्रुटि से निपटने के लिए C ++ में अपवादों का उपयोग करना चाहते हैं, और मैक्रोज़ के बजाय टेम्पलेट। हालांकि, बहुत दुर्लभ मामले में जहां आपको अभी भी मैक्रोज़ की जरूरत है (जैसे कि टोकन चिपकाने का उपयोग करके वर्ग के नाम उत्पन्न करते समय) या सादे सी तक सीमित हैं, यह एक उपयोगी पैटर्न है।


स्कूपिंग के बारे में, आपको लूप तंत्र की आवश्यकता नहीं है; एक "अनियंत्रित" ब्लॉक कानूनी है x =1; y = 2; { int tmp = y; y = x; x = tmp; }:।
Chepner

एक अनियंत्रित ब्लॉक हालांकि एक लापता अर्धविराम की उपस्थिति को लागू नहीं करता है, जो अवांछित दुष्प्रभाव हो सकता है। जबकि ऐसा(); अर्धविराम की पुष्टि करें और इस प्रकार जैसे कि निम्नलिखित बयानों को "यदि" में खींचा जाने वाला कारण नहीं बनता है यदि मैक्रो किसी रिलीज बिल्ड में कुछ भी परिभाषित नहीं करता है, तो ऊपर मेरे उदाहरण की तरह।
ulvitness साप 6'17

केवल मैक्रो के लिए एक बेहतर परिभाषा प्रदान करने से नहीं बचा जा सकता है? #define DBG_PRINT_NUM(n) {}
चेपनर

1
नहीं, क्योंकि {} एक पूर्ण कथन है, अर्थात ";" के बराबर। इसलिए यदि आप लिखते हैं तो if(a) DBG_PRINT_NUM(n); else other();यह संकलन नहीं करेगा। केवल if(a) {} else other();या if(a) ; else other();मान्य है, लेकिन if(a) {}; else other();ऐसा नहीं है, क्योंकि यह "अगर" खंड दो बयानों से मिलकर बनता है।
ulvitness

2

शायद इसका उपयोग किया जाता है ताकि breakकिसी भी बिंदु पर आगे कोड के निष्पादन को समाप्त करने के लिए अंदर का उपयोग किया जा सके:

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);

7
ऐसा करने से ऐसा लगता है gotoकि किसी ने सिर्फ इसलिए इस्तेमाल करने से बचने का प्रयास किया क्योंकि किसी ने सुना कि यह "बुरा" है।
आनन।

1
शायद, लेकिन C ++ में इसके बहुत कारण हैं।
टेड


2

यह सरल है: जाहिरा तौर पर आप breakबयान का उपयोग करके किसी भी समय नकली लूप से बाहर निकल सकते हैं । इसके अलावा, doब्लॉक एक अलग क्षेत्र है (जिसे भी हासिल किया जा सकता है{ ... } केवल )।

ऐसी स्थिति में, RAII का उपयोग करना एक बेहतर विचार हो सकता है (जब फ़ंक्शन समाप्त होता है, तो ऑब्जेक्ट्स स्वचालित रूप से सही ढंग से विनाश कर रहे हैं)। एक अन्य समान निर्माण का उपयोग है goto- हां, मुझे पता है कि यह बुराई है , लेकिन इसका उपयोग आम सफाई कोड की तरह किया जा सकता है:

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(एक तरफ के रूप में: लुया में गुम continueबयान के लिए आने के लिए डू-ए-झूठे निर्माण का उपयोग किया जाता है ।)


2

कई जवाब देने वालों ने इसका कारण बताया do{(...)break;}while(false)। मैं चित्र को एक और वास्तविक जीवन उदाहरण द्वारा पूरक करना चाहूंगा।

निम्नलिखित कोड में मुझे पॉइंटर operationद्वारा इंगित पते के आधार पर एन्यूमरेटर सेट करना था data। क्योंकि एक स्विच-केस का उपयोग केवल स्केलर प्रकारों पर किया जा सकता है पहले मैंने इसे अक्षम रूप से इस तरह से किया था

if (data == &array[o1])
    operation = O1;
else if (data == &array[o2])
    operation = O2;
else if (data == &array[on])
    operation = ON;

Log("operation:",operation);

लेकिन चूंकि लॉग () और बाकी कोड ऑपरेशन के किसी भी चुने हुए मूल्य के लिए दोहराता है, मैं भटक रहा था कि पता चलने पर बाकी तुलनाओं को कैसे छोड़ें। और do{(...)break;}while(false)यहीं काम आता है।

do {
    if (data == &array[o1]) {
        operation = O1;
        break;
    }
    if (data == &array[o2]) {
        operation = O2;
        break;
    }
    if (data == &array[on]) {
        operation = ON;
        break;
    }
} while (false);

Log("operation:",operation);

एक को आश्चर्य हो सकता है कि वह breakएक ifबयान में ऐसा क्यों नहीं कर सकता , जैसे:

if (data == &array[o1])
{
    operation = O1;
    break;
}
else if (...)

breakपूरी तरह से निकटतम एन्कोडिंग लूप या स्विच के साथ बातचीत करता है , चाहे वह ए for, whileया do .. whileप्रकार हो, इसलिए दुर्भाग्य से यह काम नहीं करेगा।


1

लेखक की आयु कितनी थी?

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


1

पहले से ही उल्लेखित 'गोटो उदाहरणों' के अलावा, ... (0) मुहावरे का उपयोग कभी-कभी परिभाषा में कोष्ठक प्रदान करने के लिए एक स्थूल परिभाषा में किया जाता है और फिर भी एक अर्ध उपनिवेश के अंत में जोड़ने के साथ संकलक का काम होता है एक मैक्रो कॉल।

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=while+(0)


0

मैं पतले प्रच्छन्न गोटो के रूप में उपयोग के बारे में अधिकांश पोस्टर से सहमत हूं। मैक्रों को शैली में कोड लिखने के लिए एक संभावित प्रेरणा के रूप में भी उल्लेख किया गया है।

मैंने इस निर्माण को मिश्रित सी / सी ++ वातावरण में एक गरीब आदमी के अपवाद के रूप में भी देखा है। एक "ब्रेक" के साथ "do {} (झूठी)" का उपयोग कोड ब्लॉक के अंत में छोड़ने के लिए किया जा सकता है, ऐसा कुछ होना चाहिए जो सामान्य रूप से लूप में एक अपवाद का सामना करना पड़ सकता है।

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


0

मैं एडोब इनडिजाइन एसडीके के साथ काम करता हूं, और इनडिजाइन एसडीके उदाहरणों में लगभग हर फ़ंक्शन इस तरह लिखा गया है। यह इस तथ्य के कारण है कि फ़ंक्शन आमतौर पर वास्तव में लंबे होते हैं। जहां आपको एप्लिकेशन ऑब्जेक्ट मॉडल से कुछ भी प्राप्त करने के लिए QueryInterface (...) करने की आवश्यकता है। तो आमतौर पर हर QueryInterface के बाद ifअच्छी तरह से नहीं जाना है, ब्रेक।


0

कई लोगों ने पहले ही इस निर्माण और ए के बीच समानता की बात कही है goto, और गोटो के लिए प्राथमिकता व्यक्त की है। शायद इस व्यक्ति की पृष्ठभूमि में एक ऐसा वातावरण शामिल था जहां गोटो को दिशानिर्देशों को कोड करने से कड़ाई से मना किया गया था?


0

दूसरा कारण जो मैं सोच सकता हूं, वह यह है कि यह ब्रेसिज़ को सजाता है, जबकि मेरा मानना ​​है कि एक नया सी ++ मानक नग्न ब्रेसिज़ ठीक नहीं है (आईएसओ सी उन्हें पसंद नहीं है)। अन्यथा लिंट की तरह एक स्थिर विश्लेषक को शांत करने के लिए।

सुनिश्चित नहीं हैं कि आप उन्हें क्यों चाहते हैं, हो सकता है कि चर गुंजाइश हो, या डिबगर के साथ लाभ हो।

सामान्य लूप को लूप करते हुए देखें , और ब्रेस सी 2 से अच्छे हैं

मेरी शब्दावली को स्पष्ट करने के लिए (जो मेरा मानना ​​है कि मानक उपयोग निम्नानुसार है):

नग्न ब्रेसिज़ :

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

खाली ब्रेसिज़ (NOP):

{}

जैसे

while (1)
   {}  /* Do nothing, endless loop */

ब्लॉक :

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

जो बन जाएगा

if (finished)
     closewindows(&windows);
freememory(&cache);

यदि ब्रेसिज़ को हटा दिया जाता है, तो इस प्रकार निष्पादन का प्रवाह बदल जाता है, न कि केवल स्थानीय चर का दायरा। इस प्रकार 'फ्रीस्टैंडिंग' या 'नग्न' नहीं।

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


वास्तव में? कि एक शर्म की बात है। कुछ चीजों में से एक जो मुझे सी के बारे में पसंद थी, वह यह थी कि आप कहीं भी बस एक नया नेस्टेड गुंजाइश घोषित करें।
TED

1
अजीब दुर्घटनाओं को ठीक करने के लिए कभी-कभी नग्न ब्रेसिज़ सहायक होते हैं। ब्लॉगs.msdn.com/oldnewthing/archive/2004/05/20/135841.aspx देखें ।
ब्रायन

1
C ++ में, एक ब्लॉक (यानी आपकी "नग्न ब्रेसिज़") का उपयोग कहीं भी किया जा सकता है, एक भी कथन की अनुमति होगी।
बेन वोइगट

@BenVoigt खाली ब्रेसेस यानी NOP एक "नग्न ब्रेसिज़" से अलग है, जो निर्देशों के एक रैखिक अनुक्रम के आसपास जोड़ा गया एक ब्लॉक है। जैसे `प्रिंटफ़ (" हैलो "); {पुश्त (','); putchar (0x20); } प्रिंटफ ("दुनिया! \ n"); `जहां ब्रेस लूप या शाखा नियंत्रण का हिस्सा नहीं हैं ।
mctylr 15

@mctylr: मैं खाली ब्रेसिज़ के बारे में बात नहीं कर रहा था।
बेन वोइगट

0

यह एक GOTOव्यावहारिक तरीका है, क्योंकि इन दोनों का अनुकरण करना व्यावहारिक रूप से समान है:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

तथा:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

दूसरी ओर, इन दोनों को वास्तव में ifs के साथ किया जाना चाहिए :

if (!someCondition) {
    // some code be here
}
// more code be here

हालांकि अगर आप सिर्फ आगे की लंबी स्ट्रिंग GOTOको नेस्टेड ifs में घुमाते हैं तो घोंसला थोड़ा बदसूरत हो सकता है । वास्तविक उत्तर उचित रीफैक्टरिंग है, हालांकि, पुरातन भाषा निर्माणों का अनुकरण नहीं है।

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

मैं किसी भी सी-लाइक लैंग्वेज से वाकिफ नहीं हूं, जहां वास्तव में किसी भी चीज के लिए एक मुहावरेदार समाधान है।

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


1
एलन, do..while(false)है नहीं चल रहा है कई बार "अपरिभाषित" संख्या के लिए, इसे चलाने के लिए है एक बार
दिमित्री

2
यदि आप एक सशर्त continueबयान जारी कर रहे हैं, जैसा कि मैंने दिखाया है तो यह अंत में एक सशर्त विवरण है। तक undefinedमैं बस का मतलब है कि आप नहीं जानते कि क्या यह एक बार जब तक आप भविष्यवाणी कर सकते हैं की स्थिति एक विशिष्ट यात्रा पर पूरा किया जाएगा कि क्या की तुलना में अधिक चल रहा है। इसमें कोई भी continues के बिना , do..while(false)एक बार चलेगा, लेकिन बिना किसी breaks के, while(true)हमेशा के लिए चलेगा, इसलिए "डिफ़ॉल्ट व्यवहार" यह समझने के लिए वास्तव में प्रासंगिक नहीं है कि छोरों के साथ क्या किया जा सकता है।
एलन प्लम

यह उपयोगी है जब आप एक मैक्रो को परिभाषित करते हैं जिसमें कई कथन होते हैं। यदि आप उन्हें एक do / / (false) में लपेटते हैं, तो आप मैक्रो का उपयोग किसी अन्य फ़ंक्शन कॉल की तरह if / if कथन में कर सकते हैं। एक उपन्यास के लिए नॉवेल्थोरी.com/TechPapers/ORE.htm देखें
जॉन

5
कोई व्यक्ति शब्दार्थ को नहीं समझता है continuecontinueलूप को दोहराता नहीं है। " continueबयान केवल एक पुनरावृति-कथन में होगा और नियंत्रण के छोटे -से- कम भाग वाले भाग को पारित करने के लिए नियंत्रण - कारण -कथन को लूप के अंत तक ले जाता है।"
बेन वोइगेट

-1, शीर्ष दो कथन उन कारणों के लिए समान नहीं हैं जो @BenVoigt बताते हैं।
cmh

0

कुछ कोडर केवल अपने कार्यों से एक ही निकास / वापसी करना पसंद करते हैं। डमी का उपयोग {(}) करते हुए (झूठा); एक बार समाप्त होने के बाद आपको डमी लूप के "ब्रेक आउट" की अनुमति देता है और अभी भी एक ही रिटर्न है।

मैं एक जावा कोडर हूं, इसलिए मेरा उदाहरण कुछ ऐसा होगा

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class p45
{
    static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
    static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());

    public static  void main(String[] argv)
    {
        for (int i = 0; i < 4; i++)
        {
            System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
        }
    }


    static String describeCake(int typeOfCake)
    {
        String result = "unknown";
        do {
            // ensure type of cake is valid
            if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;

            if (forbidden.contains(typeOfCake)) {
                result = "not for you!!";
                break;
            }

            result = cakeNames.get(typeOfCake);
        } while (false);
        return result;
    }
}


-1

यह मनोरंजक है। संभवतः लूप के अंदर ब्रेक होते हैं जैसा कि दूसरों ने कहा है। मैंने इसे इस तरह किया होगा:

while(true)
{
   <main code for function>
   break; // at the end.
}

2
लूपिंग की क्षमता के साथ हमेशा के लिए? do..while(false)हमेशा बाहर निकलता है, while(true)जोखिम भरे पक्ष में अधिक होता है।
दिमित्री

1
while(true)अधिकांश भाषाओं में सही मुहावरा है। आप अक्सर इसे GUI अनुप्रयोगों में प्रोग्राम के मुख्य लूप के रूप में पाएंगे। क्योंकि आप मूल रूप से मान रहे हैं कि कार्यक्रम को तब तक नहीं मरना चाहिए जब तक कि ऐसा करने के लिए नहीं कहा जाता है, do..while(false)इससे सभी प्रकार के आकस्मिक तर्क हो सकते हैं। यह दृष्टिकोण एक पूर्णतावादी POV से अधिक संक्षिप्त हो सकता है, लेकिन यह शब्दार्थ से आसान है और इस प्रकार मानव प्रोग्रामर (क्षमा करें, स्काईनेट) के लिए कम त्रुटि वाला है।
एलन प्लम

2
@ डमिट्री do{...}while(false)बिल्कुल वैसी ही हैwhile(true){ .. break;}
N 1.1

4
@ N1.1: की उपस्थिति में नहीं continue, वे समान नहीं हैं।
बेन वोयगेट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.