2010-08-09 15 views
9

तोड़ने मैं कुछ कोड तैयारी कर रहा हूँ:सी ++: मुख्य लूप

for(int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    for(int b = 1000; b <= 2000; b++) //loop b 
    { 
     if(b == 1555) 
      break; 
    } 

    for(int c = 2001; c <= 3000; c++) //loop c 
    { 
     . 
     . 
     . 
    } 
} 

मैं ख लूप (पाश चर int b) में एक break; बयान का उपयोग करके मुख्य लूप (पाश चर int a) को तोड़ने के लिए चाहते हैं।

मैं यह कैसे कर सकता हूं?

+3

अगर मैं सही ढंग सूचित किया गया है, कुछ भाषाओं निर्माण 'तोड़ने n' जहां' n' नेस्टेड लूप के से बाहर तोड़ने के लिए है समर्थन करते हैं। क्या मैं सही हू? –

+0

@ और http: // download-llnw।oracle.com/javase/tutorial/java/nutsandbolts/branch.html – Anycorn

+1

@Andreas: यह उनमें से एक नहीं है। @sundowatch: अपने कोड को दोबारा दोहराएं, न केवल आप अपनी समस्या का समाधान करेंगे, लेकिन आपका कोड क्लीनर और अधिक रखरखाव योग्य है। – GManNickG

उत्तर

20

मैं एक समारोह में अपने कोड पुनर्रचना की सिफारिश का प्रयोग करें। तो फिर तुम सिर्फ return कि समारोह के बजाय break का उपयोग करने का से कर सकते हैं:

void myFunc() 
{ 
    for(int a = 1; a <= 100; a++) //loop a (main loop) 
    { 
     for(int b = 1000; b <= 2000; b++) //loop b 
     { 
      if(b == 1555) // Logic is just an example, 
       return; // since it will always return 
     } 

     . 
     . 
     . 
    } 
} 

इस - या अपने कोड की शायद यह भी एक और अधिक शामिल पुनर्रचना - एक साफ, सुरुचिपूर्ण समाधान करने के लिए खुद को उधार देने चाहिए।

for(int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    bool cond = false; 

    for(int b = 1000; b <= 2000; b++) //loop b 
    { 
     if(b == 1555){ 
      cond = true; 
      break; 
     } 
    } 

    if (cond) break; 

    . 
    . 
    . 
} 

दूसरों goto का उपयोग कर सुझाव दिया है: वैकल्पिक रूप से, अगर आप सिर्फ त्वरित सुधार चाहते हैं आप एक शर्त चर का उपयोग कर सकते हैं। हालांकि यह एक और त्वरित फिक्स है, मैं इसके खिलाफ दृढ़ता से अनुशंसा करता हूं, खासकर यदि आप एक कठोर वातावरण में काम कर रहे हैं जहां कोड की समीक्षा की जाएगी और सड़क के नीचे वर्षों तक उपयोग किया जाएगा।

मेरी रायgoto दृष्टिकोण में थोड़ा मुश्किल एक समारोह/वापसी रिफैक्टरिंग से बनाए रखने के लिए, विशेष रूप से बाद में जब किसी और कोड में परिवर्तन करता रहा है। इसके अलावा आपको कोड पर ठोकर खाने वाली टीम पर किसी और को goto को उचित ठहराना होगा।

+9

यह दो स्तरों के लिए काम करता है, लेकिन उससे परे स्केल न करें। यह वह मामला है जहां आप अपने दांतों को पीसते हैं और 'गोटो' का उपयोग करते हैं। –

+14

@ जेम्स: या अपने गंदे बहु-स्तर कोड को दोबारा दोहराएं और न करें। – GManNickG

+3

@GMan: सहमत हुए। मेरा सामान्य समाधान बाहरी पाश शरीर को एक सबराउटिन में रखना होगा, और "वापसी" का उपयोग करना होगा। –

34

goto का उपयोग करें।

for(int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    for(int b = 1000; b <= 2000; b++) //loop b 
    { 
     if(b == 1555) 
      goto loopDone; 
    } 

    for(int c = 2001; c <= 3000; c++) //loop c 
    { 
     . 
     . 
     . 
    } 
} 
loopDone: 
+14

+1: यह वास्तव में असाधारण शर्त है कि भाषा में 'गोटो' छोड़ा गया था। –

+0

+1 @ जेम्स। और लोग अभी भी इसे अनावश्यक रूप से डरते हैं। ओह ठीक है .... –

+0

@sundowatch, जब तक आपके पास अधिक घोंसला वाले लूप नहीं होते .... वह विधि एक अतिरिक्त चर का भी उपयोग करती है और इसमें कोड की अधिक रेखाएं होती हैं (जिसका अर्थ टाइपो से संबंधित बग के लिए अधिक जगह है)। –

4
for(int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    for(int b = 1000; b <= 2000; b++) //loop b 
    { 
     if(b == 1555) 
      goto end; 
    } 

    for(int c = 2001; c <= 3000; c++) //loop c 
    { 
     . 
     . 
     . 
    } 
} 
end: 
4

एक समय में इस तरह के दो छोरों से बाहर सिर करने का एकमात्र तरीका goto या एक throw या एक return, और throw और return उपयुक्त नहीं हो सकता (विशेष रूप से throw है, अगर हालत 'isn असाधारण नहीं)। वैकल्पिक रूप से, आप किसी प्रकार की स्थिति (bool breakout;) सेट कर सकते हैं, और यदि यह सच है तो तोड़ना जारी रखें।

+2

यदि कोड दोबारा किया गया है तो आप 'वापसी' का भी उपयोग कर सकते हैं। इसके अलावा, चूंकि 'फेंक' अपवाद उठाता है, यह एक खराब अभ्यास की तरह लगता है जब तक कि भ्रष्ट डेटा जैसे "असाधारण" कारण के लिए ब्रेक नहीं बनाया जाता है। –

+0

@ जस्टिन: धन्यवाद - मेरे उत्तर में शामिल है। –

1

पैटर्न

इस तरह का
for(int a = 1; a <= 100; a++) 
{ 
    int breakMain = 0; 
    for(int b = 1000; b <= 2000; b++) 
    { 
     if(b == 1555) 
     { 
      breakMain = 1; 
      break; 
     } 
    } 

    if(breakMain) 
     break; 

    for(int c = 2001; c <= 3000; c++) 
    { 
     . 
     . 
     . 
    } 
} 
3
  1. का प्रयोग करें एक goto:

    for(int a = 1; a <= 100; a++) //loop a (main loop) 
    { 
        for(int b = 1000; b <= 2000; b++) //loop b 
        { 
         if(b == 1555) 
          goto done; 
        } 
        for(int c = 2001; c <= 3000; c++) //loop c 
        { 
         . 
         . 
         . 
        } 
    } 
    done: 
    
  2. सेट प्रत्येक पाश द्वारा परीक्षण एक प्रहरी मूल्य:

    bool sentinel = true ; 
    for(int a = 1; a <= 100 && sentinel ; a++) //loop a (main loop) 
    { 
        for(int b = 1000; b <= 2000 && sentinel; b++) //loop b 
        { 
         if(b == 1555) 
          sentinel = false; 
        } 
        for(int c = 2001; c <= 3000 && sentinel; c++) //loop c 
        { 
         . 
         . 
         . 
        } 
    } 
    
+0

सेंटीनेल झूठ के बाद आप लूप तोड़ना भूल गए हैं – kravemir

+0

मिरो, सभी लूप 9ओआर समाप्त नहीं होते हैं) अगर सेंटीनेल झूठा है। – tpdi

4

यदि यह उचित है, तो आप एक समारोह जो सामग्री है बना सकता है एक पाश हैं, और वापसी का उपयोग करें।

public void bigLoop() 
{ 
    for(int a = 1; a <= 100; a++) 
    { 
     for(int b = 1000; b <= 2000; b++) 
     { 
      if(b == 1555) 
       return; 
     } 

     for(int c = 2001; c <= 3000; c++) 
     { 
      . 
      . 
      . 
     } 
    } 
}//bigLoop 
2

एक सरल रणनीति चयनित बिंदु पर एक अलग समारोह में पाश डाल दिया और एक वापसी करना है:

void func() 
{ 
    for(int a = 1; a <= 100; a++) //loop a (main loop) 
    { 
     for(int b = 1000; b <= 2000; b++) //loop b 
     { 
      if(b == 1555) 
       return; 
     } 

     for(int c = 2001; c <= 3000; c++) //loop c 
     { 
      . 
      . 
      . 
     } 
    } 
} 

परिणाम किसी भी तरह का भी या के साथ एक वापसी मान वाला लौटाया जा सकता है, समारोह के लिए एक संदर्भ पैरामीटर। goto उपयोग करते हैं, throw उपयोग करते हैं, एक ध्वज है, या refactor का उपयोग करें:

+0

यह मेरा समाधान होगा। कोड (तीन लूप, पहले में एम्बेडेड दो) वैसे भी एक subroutine में सारण्य को औचित्य साबित करने के लिए पर्याप्त बुरा है। –

23

या तो चार चीजों में से एक है।

कई using goto से असहमत होंगे, लेकिन sometimes यह एक साफ समाधान है। (ज्यादातर बार, यह नहीं है, लेकिन यह किसी कारण से मौजूद है।) हालांकि, मुझे goto का उपयोग एक रिफैक्टर वारंट करता है।

दूसरा समाधान to throw कुछ विशेष अपवाद है और फिर इसे मुख्य लूप के बाहर पकड़ें। यह अपवाद प्रणाली का दुरुपयोग है और मूल रूप से एक खराब goto; इसके बजाय goto का उपयोग करें।

तीसरा समाधान के a flag का उपयोग करना होगा। यह मूल रूप से एक "सुरक्षित" goto है, लेकिन कुछ तर्क दे सकते हैं कि यह थोड़ा उलझन में है। (इस तरह के एक मामले में विशेष रूप से बहु-स्तर के साथ। हालांकि आपकी चिंता कैसे बदसूरत अपने कोड है।)

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

+1

गोटो के साथ कुछ भी गलत नहीं है (अगर सही तरीके से उपयोग किया जाता है) यह इन स्थानों में से एक है। गेटो का दुरुपयोग जो डरना चाहिए और दुरुपयोग को पहचानने की क्षमता हमारी उच्च शिक्षा सुविधाओं में इतनी कमी है। –

+0

@ मार्टिन निश्चित रूप से ... लेकिन यदि फॉर-लूप और जटिल गेटो ने एक फ़ंक्शन लंबा किया है, तो वास्तव में यह वास्तव में एक बुरा विचार है। इस उदाहरण में हमारे पास तीन जटिल-लूप और एक गोटो है ... मुझे लगता है कि यह बहुत अधिक है। मेरा व्यक्तिगत दृष्टिकोण –

2

आदर्श तरीका आपके कोड को फिर से कारक बनाना होगा ताकि आपको अब ऐसी जटिल नेस्टेड-लूप संरचना की आवश्यकता न हो। आपके शेष कोड की तरह दिखने के आधार पर, आपके b और c लूप अलग-अलग फ़ंक्शन बनने के लिए उम्मीदवार हो सकते हैं, अगर पूरे a लूप नहीं हैं।

चूंकि यह लूप b और c आसन्न श्रृंखलाओं पर फिर से दिखता है, क्यों न उन्हें संयोजित करें और थोड़ा सा घोंसला घोंसला कम करें?

for (int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    int count = 1000; 
    while (count <= 3000) // combined loops 'b' and 'c' 
    { 
     if (count <= 2000) 
     { 
      // Old loop 'b' code 
      if (b == 1555) 
       goto fullbreak; 
     } 
     else 
     { 
      // Old loop 'c' code 
      ... 
     } 
     count++; 
    } 
} 
fullbreak: 

आप goto के बजाय एक शर्त चर का भी उपयोग कर सकते हैं। यदि आप पुराने b पाश से बाहर निकलना चाहते हैं लेकिन अभी भी पुराने c लूप को संसाधित करना चाहते हैं, तो पुराने b लूप कोड के अंदर बस count = 2001 सेट करें।

आदर्श रूप में, आप कम से कम और अधिक की तरह

for (int a = 1; a <= 100; a++) //loop a (main loop) 
{ 
    if (process_inner_loop(pass, required, args)) 
     break; 
} 

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

4

\ (◕ ◡ ◕)/

[]() { 
    for(int a = 1; a <= 100; a++) //loop a (main loop) 
    { 
     for(int b = 1000; b <= 2000; b++) //loop b 
     { 
      if(b == 1555) 
       return; 
     } 

     for(int c = 2001; c <= 3000; c++) //loop c 
     { 
      . 
      . 
      . 
     } 
    } 
}(); 
+0

इस तरह के मामलों में कंपाइलर्स इनलाइन लैम्बस को अनुकूलित करना होगा? – Gunslinger47

+1

आमतौर पर, कोई भी आधुनिक कंपाइलर जटिल/लंबे कार्यों के अलावा सभी को रेखांकित करेगा, * विशेष रूप से * यदि फ़ंक्शन परिभाषा दिखाई दे रही है। (लिंक-टाइम ऑप्टिमाइज़ेशन अपेक्षाकृत नया है, और अधिक कठिन है।) इसके साथ, ध्यान दें कि लैम्ब्डा अद्वितीय छिपे हुए structs हैं, और पूरी परिभाषा हमेशा उपलब्ध होने पर उपलब्ध होती है। तो आप बहुत अधिक गारंटीकृत हैं lambda की इच्छा रेखांकित किया जाएगा। – GManNickG

संबंधित मुद्दे