क्या मैं 'छोरों' के लिए कई नेस्टेड से बाहर निकलने के लिए ब्रेक का उपयोग कर सकता हूं?


305

क्या breakकई नेस्टेड forछोरों से बाहर निकलने के लिए फ़ंक्शन का उपयोग करना संभव है ?

यदि हां, तो आप यह करने के बारे में कैसे जाएंगे? क्या आप यह भी नियंत्रित कर सकते हैं कि कितने छोरों को breakबाहर निकालता है?


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

जवाबों:


239

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


317
gotoसबसे अच्छा विकल्प है अगर एक का उपयोग करने के लिए डरो मत ।
जिक्स

18
मैं एक नया C ++ प्रोग्रामर हूं (और किसी भी औपचारिक प्रोग्रामिंग प्रशिक्षण के बिना) इस प्रकार गोटो पर लोगों के किराए के बारे में पढ़ने के बाद। मुझे डर है कि मेरे कार्यक्रम में अचानक इसका इस्तेमाल करने और मुझे मारने के लिए इसका इस्तेमाल करने में मुझे संकोच हो रहा है। इसके अलावा, जब मैं अपने ti-83 (उबाऊ गणित वर्ग के पाठ्यक्रम में) पर कार्यक्रम लिखता था, तो बुनियादी संपादक द्वारा दिए गए कार्यों में गोटो के उपयोग की आवश्यकता होती थी।
FCC

26
@ मुक्त: दो प्रकार के प्रोग्रामर उपयोग करते हैं goto: खराब प्रोग्रामर, और व्यावहारिक प्रोग्रामर। पूर्व स्वयं व्याख्यात्मक हैं। उत्तरार्द्ध, जिसे आप फिट करेंगे यदि आप उन्हें अच्छी तरह से उपयोग करने के लिए चुनते हैं, तो तथाकथित "बुराई" अवधारणा का उपयोग करें जब यह (दो) बुराइयों से कम हो। इसे कुछ C ++ अवधारणाओं की बेहतर समझ के लिए पढ़ें, जिन्हें आपको समय-समय पर उपयोग करने की आवश्यकता हो सकती है (मैक्रोज़, गोटो, प्रीप्रोसेसर, सरणियाँ): parashift.com/c++-faq-lite/big-pureure.html#faq-6.15
jkeys

41
@ मुक्त: गोटो का उपयोग करने में कुछ भी गलत नहीं है। यह एक गोजा का दुरुपयोग कर रहा है जो परेशान करने वाला है।
हर कोई 4

28
@ देखा: यह सही है, सिवाय इसके कि gotoशायद ही कभी का उपयोग करना सबसे अच्छा विकल्प है। क्यों अपने स्वयं के कार्य में छोरों को नहीं रखा ( inline, यदि आप गति के बारे में चिंतित हैं) और returnइससे?
sbi

265

नहीं, इसे किसी के साथ खराब मत करो break। के उपयोग के लिए यह अंतिम शेष गढ़ है goto


19
MISRA C ++ कोडिंग मानक इस सटीक प्रकार की स्थिति को कवर करने के लिए गोटो के उपयोग की अनुमति देता है।
रिचर्ड कॉर्डन

11
वास्तविक प्रोग्रामर गोटो का उपयोग करने से डरते नहीं हैं। 25 साल के लिए यह किया - कोई पछतावा नहीं - विकास के समय का एक टन बचाया।
डग नल

1
मैं सहमत हूँ। यदि आपके पास 8K पिक्सेल नहीं है, तो गोटो एक होना चाहिए, और 30 विंडोज ओएस कॉल के अनुक्रम को कॉल करने की आवश्यकता है।
माइकल रॉय

या एक फ़ंक्शन में कोड डालकर एक सरल "वापसी"।
तारा

68

लैम्ब्डा का उपयोग करके स्पष्ट उत्तर जोड़ने के लिए:

  for (int i = 0; i < n1; ++i) {
    [&] {
      for (int j = 0; j < n2; ++j) {
        for (int k = 0; k < n3; ++k) {
          return; // yay we're breaking out of 2 loops here
        }
      }
    }();
  }

बेशक इस पैटर्न की एक निश्चित सीमाएँ हैं और जाहिर सी बात है C ++ 11 लेकिन मुझे लगता है कि यह काफी उपयोगी है।


7
यह पाठक को यह सोचने में भ्रमित कर सकता है कि वापसी का कारण फ़ंक्शन लैंबडा को वापस करना है, न कि लैम्बडा को ही।
Xunie

3
@Xunie: यदि आपका लूप इतना जटिल है, कि आप भूल जाते हैं कि आप एक लंबोदर में हैं, तो उन्हें एक अलग फ़ंक्शन में रखने का समय है, लेकिन सरल मामलों के लिए, यह काफी अच्छी तरह से काम करना चाहिए।
17

17
मुझे लगता है कि यह समाधान सुंदर है
tuket

आप एक RIIA टेम्पलेट में लैम्ब्डा को कैप्चर कर सकते हैं जो इसे एक नाम देता है और इसे dtor (उर्फ स्कोप गौर) में कहता है। इससे कोई प्रदर्शन लाभ नहीं मिलेगा, लेकिन पठनीयता में सुधार हो सकता है और फ़ंक्शन कॉल कोष्ठक गुम होने के जोखिम को कम कर सकता है।
रेड.वेग

56

नेस्टेड लूप से बाहर निकलने का एक अन्य तरीका यह है कि दोनों छोरों को एक अलग फ़ंक्शन में फैक्टर करें, और returnउस फ़ंक्शन से जब आप बाहर निकलना चाहते हैं।

बेशक, यह दूसरे तर्क को सामने लाता है कि क्या आपको कभी returnभी किसी फ़ंक्शन से अंत के अलावा कहीं और स्पष्ट रूप से मिलना चाहिए ।


7
वह C समस्या है। आरआईएए के साथ जल्दी वापसी एक समस्या नहीं है क्योंकि शुरुआती रिटर्न से जुड़ी सभी समस्याओं को सही ढंग से नियंत्रित किया जाता है।
मार्टिन यॉर्क

4
मैं समझता हूं कि RIAA के उचित अनुप्रयोग से C ++ में रिसोर्स क्लीनअप समस्या को हल किया जा सकता है, लेकिन मैंने अन्य वातावरणों और भाषाओं में शुरुआती रिटर्न के खिलाफ दार्शनिक तर्क को देखा है। एक प्रणाली जिस पर मैंने काम किया था, जहां कोडिंग मानक ने शुरुआती रिटर्न को निषिद्ध किया था, बूलियन चर (जैसे नाम continue_processing) के साथ फंसे हुए फ़ंक्शन थे जो फ़ंक्शन में कोड के ब्लॉक के निष्पादन को और नीचे नियंत्रित करते थे।
ग्रेग हेवगिल

21
RIAA क्या है? क्या RAII जैसा कुछ भी है? = D
jkeys

1
निर्भर करता है कि उसके पास कितने लूप हैं और घोंसला कितना गहरा है ... क्या आप नीली गोली या लाल गोली चाहते हैं?
मैट

34

ब्रेक केवल अंतरतम लूप से बाहर निकलेगा जिसमें यह होगा।

आप किसी भी संख्या में छोरों को तोड़ने के लिए गोटो का उपयोग कर सकते हैं ।

बेशक गोटो को अक्सर हानिकारक माना जाता है

क्या ब्रेक फंक्शन का उपयोग करना उचित है [...]?

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


16
इसमें एक अच्छा जवाब यह बताता है कि "गोटो हानिकारक है" मेम दृढ़ता से अधिक सामान्यीकृत "नियंत्रण प्रवाह रुकावट से बंधा है" यह कथन हानिकारक है। यह कहना "गोटो हानिकारक है", और फिर घूम और उपयोग करने की अनुशंसा अर्थहीन है breakया return
पावेल मिनाएव

6
@ पावेल: breakऔर returnइसका फायदा यह है gotoकि आपको एक लेबल के लिए शिकार करने की आवश्यकता नहीं है ताकि वे कहां जाएं। हां, नीचे वे कुछ प्रकार के हैं goto, लेकिन एक बहुत ही प्रतिबंधित है। वे अप्रतिबंधित की तुलना में प्रोग्रामर के पैटर्न-मिलान मस्तिष्क द्वारा समझने में बहुत आसान हैं goto। तो IMO वे बेहतर हैं।
sbi

@ एसएसबी: सच है, लेकिन ब्रेक अभी भी संरचित प्रोग्रामिंग का हिस्सा नहीं है। यह सिर्फ एक से बेहतर सहन किया है goto
jkeys

2
@KarlVoigtland दिक्जस्ट्रा लिंक पुराना है; यह कार्य करता प्रतीत होता है: blog.plover.com/2009/07
आरोन ब्रेजर

3
इस स्थिति में गोटो का उपयोग करने में कुछ भी गलत नहीं है। एक अच्छी तरह से रखा गोटो कई प्रस्तावित समाधानों की तुलना में बेहतर और अधिक पठनीय है और अन्यथा प्रस्तावित है।
जेम्स

22

हालाँकि यह उत्तर पहले ही प्रस्तुत किया गया था, मुझे लगता है कि एक अच्छा तरीका निम्नलिखित है:

for(unsigned int z = 0; z < z_max; z++)
{
    bool gotoMainLoop = false;
    for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
    {
        for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
        {
                          //do your stuff
                          if(condition)
                            gotoMainLoop = true;
        }
    }

}

5
जो अच्छा है, लेकिन फिर भी इतना पठनीय नहीं है, मैं उस मामले में गोटो पसंद करूंगा
Пет Пр Петров

2
इससे आपका कोड "काफी" धीमा हो जाता gotoMainLoopहै क्योंकि हर चक्र की जाँच की जाती है
थॉमस

1
इस मामले में, असली का उपयोग gotoकोर को अधिक पठनीय और बेहतर प्रदर्शन करता है।
Пет17р Петров

20

इस बारे में कैसा है?

for(unsigned int i=0; i < 50; i++)
{
    for(unsigned int j=0; j < 50; j++)
    {
        for(unsigned int k=0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                j=50;
                k=50;
            }
        }
    }
}

2
दिलचस्प तरीका है, लेकिन मैं निश्चित रूप से जिस तरह से @ inf.ig.sh को संभालता हूं वह इसे पसंद करता है। for (अहस्ताक्षरित int y = 0; y <y_max &&; gotoMainLoop; y ++)।
एंडी

15

एक कोड उदाहरण का उपयोग कर gotoऔर एक नेस्टेड लूप से बाहर निकलने के लिए एक लेबल:

for (;;)
  for (;;)
    goto theEnd;
theEnd:

11

कई नेस्टेड छोरों को तोड़ने का एक अच्छा तरीका है कि आप किसी फ़ंक्शन में अपने कोड को रिफलेक्टर करें:

void foo()
{
    for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < 50; j++)
        {
            for(unsigned int k=0; k < 50; k++)
            {
                // If condition is true
                return;
            }
        }
    }
}

4
... जो एक विकल्प नहीं है अगर हमें इस फ़ंक्शन को स्टैक बनाने के लिए 10-20 चर पास करना है।
Пет13р Петров

1
@ Пет aрПетров फिर एक लंबोदर के लिए जाएं जो बेहतर है क्योंकि आप इसे परिभाषित कर सकते हैं कि आपको इसकी आवश्यकता कहां है।
DaroP

लैम्बदास के लिए +1 लेकिन गेम इंजन कोर में ओवरहाल जहां एक स्टैक फ्रेम अभी भी एक अड़चन है। बताने के लिए क्षमा करें, लेकिन मेमने कम से कम MSVC 2010 में इतने हल्के नहीं हैं।
Петър Петров

@ Пет pairрПетров फिर एक वर्ग में कार्यों की जोड़ी को बदलते हैं, और निजी सदस्यों में स्टैक चर।
आर्थर टाका

यह केवल पहले से ही जटिल कोड को ओवरकम्प्लीकेट करता है :) कभी-कभी, गोटो एकमात्र समाधान है। या यदि आप "गोटो स्टेट एक्स" प्रलेखन के साथ जटिल ऑटोमेटा लिखते हैं, तो गोटो वास्तव में दस्तावेज में लिखे गए कोड को पढ़ रहा है। इसके अलावा, सी # और गो दोनों का एक उद्देश्य के साथ गोटो है: कोई भी भाषा गोटो के बिना ट्यूरिंग-पूर्ण नहीं है, और गोटोस अक्सर मध्यवर्ती अनुवादक या असेंबली जैसे कोड लिखने के लिए सबसे अच्छा उपयोग किए जाने वाले उपकरण हैं।
Пететр Петров

5

नेस्टेड छोरों को तोड़ने के लिए गोटो बहुत मददगार हो सकता है

for (i = 0; i < 1000; i++) {
    for (j = 0; j < 1000; j++) {
        for (k = 0; k < 1000; k++) {
             for (l = 0; l < 1000; l++){
                ....
                if (condition)
                    goto break_me_here;
                ....
            }
        }
    }
}

break_me_here:
// Statements to be executed after code breaks at if condition

3

breakबयान निकटतम संलग्नित के निष्पादन समाप्त हो जाता है do, for, switch, या whileबयान है जिसमें यह प्रतीत होता है। नियंत्रण उस कथन को पास करता है जो समाप्त कथन का अनुसरण करता है।

से MSDN


3

मुझे लगता है कि gotoइस परिस्थिति में मान्य है:

एक अनुकरण करने के लिए break/ continue, आप चाहते हैं चाहते हैं:

टूटना

for ( ;  ;  ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            goto theEnd;
        }
    }
}
theEnd:

जारी रखें

for ( ;  ; ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            i++;
            goto multiCont;
        }
    }
    multiCont:
}

"जारी रखें" वहां काम नहीं करेगा, क्योंकि पहले लूप की पुनरावृति अभिव्यक्ति को निष्पादित नहीं किया जाएगा
फैबियो ए।

मैं मान रहा हूँ कि पहले लूप के लिए पुनरावृत्ति है i। इसलिए i++गोटो से पहले
JuliusAlphonso

0

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


0

मुझे पता है यह पुरानी पोस्ट है। लेकिन मैं थोड़ा तार्किक और सरल उत्तर देना चाहूंगा।

for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < conditionj; j++)
        {
            for(unsigned int k=0; k< conditionk ; k++)
            {
                // If condition is true

                j= conditionj;
               break;
            }
        }
    }

3
j = conditionjयदि आप इसके बजाय एक जटिल विधेय है, तो यह बहुत स्केलेबल समाधान नहीं होगा j < conditionj
सर्जेई

0

boolनीचे दिए गए केवल एक चर से किसी भी संख्या में छोरों को तोड़ें :

bool check = true;

for (unsigned int i = 0; i < 50; i++)
{
    for (unsigned int j = 0; j < 50; j++)
    {
        for (unsigned int k = 0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                check = false;
                break;
            }
        }
        if (!check)
        {
            break;
        }
    }
    if (!check)
    {
        break;
    }
}

इस कोड में हम break;सभी छोरों।


0

मुझे यकीन नहीं है अगर यह इसके लायक है, लेकिन आप कुछ सरल मैक्रोज़ के साथ जावा के नामित लूप का अनुकरण कर सकते हैं:

#define LOOP_NAME(name) \
    if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
    { \
        [[maybe_unused]] CAT(_namedloop_break_,name): break; \
        [[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
    } \
    else

#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)

#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y

उदाहरण का उपयोग:

#include <iostream>

int main()
{
    // Prints:
    // 0 0
    // 0 1
    // 0 2
    // 1 0
    // 1 1

    for (int i = 0; i < 3; i++) LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << i << ' ' << j << '\n';
            if (i == 1 && j == 1)
                BREAK(foo);
        }
    }
}

एक और उदाहरण:

#include <iostream>

int main()
{
    // Prints: 
    // 0
    // 1
    // 0
    // 1
    // 0
    // 1

    int count = 3;
    do LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << ' ' << j << '\n';
            if (j == 1)
                CONTINUE(foo);
        }
    }
    while(count-- > 1);
}

-1
  while (i<n) {
    bool shouldBreakOuter = false;
    for (int j=i + 1; j<n; ++j) {
      if (someCondition) {
          shouldBreakOuter = true;
      }
    }

    if (shouldBreakOuter == true)
      break;

  }

-3

आप कोशिश ... पकड़ का उपयोग कर सकते हैं।

try {
    for(int i=0; i<10; ++i) {
        for(int j=0; j<10; ++j) {
            if(i*j == 42)
                throw 0; // this is something like "break 2"
        }
    }
}
catch(int e) {} // just do nothing
// just continue with other code

यदि आपको एक साथ कई लूप्स को तोड़ना है, तो यह अक्सर एक अपवाद है।


1
मैं इसका कारण जानना चाहूंगा कि इस उत्तर को इतना अधिक वोट क्यों मिले।
hkBattousai

6
@hkBattousai समाधान में नीचे वोट हैं क्योंकि यह निष्पादन प्रवाह को नियंत्रित करने के लिए एक अपवाद का उपयोग कर रहा है। जैसा कि नाम से पता चलता है, अपवाद केवल असाधारण मामलों पर ही उपयोग किए जाने चाहिए।
हेलियो सैंटोस

4
@HelioSantos क्या यह एक असाधारण स्थिति नहीं है जिसके लिए भाषा उचित समाधान की आपूर्ति नहीं कर रही है?
hkBattousai

8
अपवाद धीमे हैं।
गॉर्डन

2
फेंक का प्रदर्शन प्रभाव उस चीज के लिए बहुत बड़ा है जो 99% समय के लिए अपरिवर्तनीय त्रुटि नहीं है।
माइकल रॉय

-4

फ़ोर-लूप से बाहर निकलना मेरे लिए थोड़ा अजीब है, क्योंकि फ़ोर-लूप के शब्दार्थ आमतौर पर संकेत देते हैं कि यह निर्दिष्ट समय को निष्पादित करेगा। हालाँकि, यह सभी मामलों में बुरा नहीं है; यदि आप किसी संग्रह में कुछ खोज रहे हैं और उसे खोजने के बाद उसे तोड़ना चाहते हैं, तो यह उपयोगी है। नेस्टेड छोरों से बाहर निकलना, हालांकि, सी ++ में संभव नहीं है; यह लेबल विराम के उपयोग के माध्यम से अन्य भाषाओं में है। आप एक लेबल और एक गोटो का उपयोग कर सकते हैं, लेकिन यह आपको रात में नाराज़गी दे सकता है ..? हालांकि सबसे अच्छा विकल्प लगता है।


11
यह बिल्कुल भी अजीब नहीं है। यदि आप किसी चीज़ को देखने के लिए संग्रह पर ध्यान दे रहे हैं (और खोज का तेज़ तरीका नहीं है), तो लूप को पूरा करने का कोई मतलब नहीं है। (एक उदाहरण के रूप में)
जो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.