क्या यह गोटो बयान को सही ठहराता है?


15

मुझे यह सवाल एक दूसरे से पहले आया था, और मैं वहां से कुछ सामग्री खींच रहा हूं: क्या 'ब्रेक एन' निर्माण का कोई नाम है?

यह लोगों के लिए एक अनावश्यक रूप से जटिल तरीका प्रतीत होता है ताकि प्रोग्राम को लूप के लिए डबल-नेस्टेड से बाहर तोड़ने का निर्देश दिया जा सके:

for (i = 0; i < 10; i++) {
    bool broken = false;
    for (j = 10; j > 0; j--) {
        if (j == i) {
            broken = true;
            break;
        }
    }
    if (broken)
        break;
}

मुझे पता है कि पाठ्यपुस्तकें यह कहना चाहती हैं कि गोटो के बयान शैतान हैं, और मैं उन सभी के लिए खुद को पसंद नहीं कर रहा हूं, लेकिन क्या यह नियम के अपवाद को सही ठहराता है?

मैं उन उत्तरों की तलाश में हूं जो लूप के लिए एन-नेस्टेड के साथ सौदा करते हैं।

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


2
यदि आप आंतरिक लूप स्थिति लिख सकते हैं for (j = 10; j > 0 && !broken; j--)तो आपको break;कथन की आवश्यकता नहीं होगी । यदि आप brokenबाहरी लूप शुरू होने से पहले की घोषणा को आगे बढ़ाते हैं , तो यदि वह लिखा जा सकता है for (i = 0; i < 10 && !broken; i++)तो मुझे लगता है कि कोई break; भी आवश्यक नहीं है।
FrustratedWithFormsDesigner 21

8
यह देखते हुए उदाहरण C # से है - C # संदर्भ ऑन goto: गोटो (C # संदर्भ) - "गोटो स्टेटमेंट गहरी नेस्टेड लूप से बाहर निकलने के लिए भी उपयोगी है।"

OMG, मुझे कभी नहीं पता था कि c # का एक गोटो स्टेटमेंट है! StackExchange पर जो चीजें आप सीखते हैं। (मुझे पिछली बार याद नहीं आया कि मैंने एक गोटो स्टेटमेंट क्षमता की कामना की थी, यह कभी सामने नहीं आता है)।
जॉन वू

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

1
gotoपहले केस के अंदर किसी भी कोड को अंजाम देने के बाद @JohnWu को वास्तव में C # स्विच टू थ्रू किसी अन्य मामले में आवश्यक है। यह एकमात्र मामला है, जिसका मैंने गोटो उपयोग किया है, हालांकि।
डैन ल्यों

जवाबों:


33

जाने के लिए स्पष्ट कथन की आवश्यकता है कि आप छोरों के लिए खराब सशर्त अभिव्यक्ति का चयन करते हैं

आप कहते हैं कि आप चाहते थे कि बाहरी पाश लंबे समय तक जारी रहे i < 10और अंतरतम लंबे समय तक जारी रहे j > 0

लेकिन वास्तव में वह नहीं है जो आप चाहते थे , आप बस उन वास्तविक स्थिति को नहीं बताते थे जिन्हें आप उन्हें मूल्यांकन करना चाहते थे, फिर आप इसे ब्रेक या गोटो का उपयोग करके हल करना चाहते हैं।

यदि आप छोरों को अपने सच्चे इरादों के साथ शुरू करने के लिए कहते हैं , तो ब्रेक या गोटो की कोई आवश्यकता नहीं है।

bool alsoThis = true;
for (i = 0; i < 10 && alsoThis; i++)
{    
    for (j = 10; j > 0 && alsoThis; j--)
    {
        if (j == i)
        {
            alsoThis = false;
        }
    }
}

अन्य उत्तरों पर मेरी टिप्पणियाँ देखें। iबाहरी लूप के अंत में मूल कोड प्रिंट होता है, इसलिए वेतन वृद्धि को कम-कोडित करना कोड को 100% समतुल्य बनाने के लिए महत्वपूर्ण है। मैं आपके उत्तर में कुछ भी गलत नहीं कह रहा हूं, मैं केवल यह बताना चाहता था कि लूप को तुरंत तोड़ना कोड का एक महत्वपूर्ण पहलू था।
pswg

1
@pswg मुझे iओपी के प्रश्न में बाहरी लूप के अंत में कोई कोड प्रिंटिंग दिखाई नहीं देती है ।
ट्यूलेंस कोर्डोवा

ओपी ने यहां मेरे प्रश्न से कोड का संदर्भ दिया , लेकिन उस हिस्से को छोड़ दिया। मैंने आपको नीचे नहीं किया, बीटीडब्लू। पाश स्थितियों को सही ढंग से चुनने के संबंध में उत्तर पूरी तरह से सही है।
pswg

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

1
कोड का उद्देश्य के लिए एक वैध उपयोग के मामले प्रदान नहीं किया गया था goto(मुझे यकीन है कि वहाँ बेहतर कर रहे हैं), भले ही यह एक सवाल है जो इसे इस तरह के रूप में उपयोग करने लगता है, लेकिन break(n)भाषाओं में बुनियादी कार्रवाई का वर्णन करने के लिए जो नहीं किया था ' t इसका समर्थन करें।
pswg

34

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

bool isBroken() {
    for (i = 0; i < 10; i++)
        for (j = 10; j > 0; j--)
            if (j == i) return true;

    return false;
}

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

2
बस एक साइड नोट: मूल कोड में यह iबाहरी लूप के अंत के बाद प्रिंट करता है। तो वास्तव में प्रतिबिंबित करने के iलिए यह महत्वपूर्ण मूल्य है, यहां return true;और return false;दोनों को होना चाहिए return i;
pswg

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

6

नहीं, मुझे नहीं लगता कि gotoयह आवश्यक है। यदि आप इसे इस तरह लिखते हैं:

bool broken = false;
saved_i = 0;
for (i = 0; i < 10 && !broken; i++)
{
    broken = false;
    for (j = 10; j > 0 && !broken; j--)
    {
        if (j == i)
        {
            broken = true;
            saved_i = i;
        }
    }
}

&&!brokenदोनों छोरों पर होने से आप दोनों छोरों से बाहर निकल सकते हैं i==j

मेरे लिए, यह दृष्टिकोण बेहतर है। लूप की स्थितियां बेहद स्पष्ट हैं i<10 && !broken:।

एक कार्यशील संस्करण यहां देखा जा सकता है: http://rextester.com/KFMH48414

कोड:

public static void main(String args[])
{
    int i=0;
    int j=0;
    boolean broken = false;
    for (i = 0; i < 10 && !broken; i++)
    {
        broken = false;
        for (j = 10; j > 0 && !broken; j--)
        {
            if (j == i)
            {
                broken = true;
                System.out.println("loop breaks when i==j=="+i);
            }
        }
    }
    System.out.println(i);
    System.out.println(j);
}

आउटपुट:

लूप टूट जाता है जब मैं == j == 1
2
0

तुम भी brokenअपने पहले उदाहरण में उपयोग क्यों करते हो ? बस आंतरिक लूप पर ब्रेक का उपयोग करें। इसके अलावा, यदि आप पूरी तरह से उपयोग करना चाहते हैं, तो brokenइसे छोरों के बाहर क्यों घोषित करें? बस यह घोषणा अंदरi पाश। के रूप में whileपाश, कि का उपयोग नहीं करें। मैं ईमानदारी से लगता है कि यह गोटो संस्करण की तुलना में कम पठनीय होने का प्रबंधन करता है ।
22

@luiscubal: नाम वाले एक चर brokenका उपयोग किया जाता है क्योंकि मुझे breakकथन का उपयोग करना पसंद नहीं है (स्विच-केस को छोड़कर, लेकिन यह इसके बारे में है)। जब आप सभी लूप को तोड़ना चाहते हैं तो यह बाहरी लूप के बाहर घोषित किया जाता है i==j। आप सही कह रहे हैं, सामान्य तौर पर, brokenकेवल सबसे बाहरी लूप से पहले घोषित किए जाने की आवश्यकता है कि यह टूट जाएगा।
FrustratedWithFormsDesigner

आपके अपडेट में, i==2लूप के अंत में। सफलता की स्थिति भी शॉर्ट-सर्किट बढ़ानी चाहिए अगर यह 100% के बराबर हो break 2
pswg

2
मैं व्यक्तिगत रूप से इफ के broken = (j == i)बजाय पसंद करता हूं और, अगर भाषा इसकी अनुमति देती है, तो बाहरी लूप इनिशियलाइज़ेशन के अंदर टूटी हुई घोषणा को डालना। हालांकि इस विशिष्ट उदाहरण के लिए इन चीजों को कहना कठिन है, क्योंकि पूरा लूप एक नहीं है (यह कुछ भी नहीं देता है और इसका कोई साइड इफेक्ट नहीं है) और अगर यह कुछ करता है, तो यह संभवतः ऐसा करता है अगर अंदर (हालांकि मुझे अभी भी broken = (j ==i); if broken { something(); }बेहतर पसंद है व्यक्तिगत रूप से)
Martijn

@Martijn मेरे मूल कोड में यह iबाहरी लूप के अंत के बाद प्रिंट करता है। दूसरे शब्दों में, वास्तव में महत्वपूर्ण विचार यह है कि वास्तव में बाहरी लूप से टूट जाता है।
pswg

3

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

सामान्यतया, एक ही फ़ंक्शन में आगे बढ़ने वाला एक गोटो अक्सर स्वीकार्य होता है, खासकर अगर कूद बहुत लंबा नहीं है। नेस्टेड लूप छोड़ने का आपका उपयोग मामला "इतना बुरा नहीं" गोटो के ज्ञात उदाहरण में से एक है।


2

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

अपने भविष्य के समीक्षक के बारे में सोचें: s / उसे सोचना होगा, "क्या यह व्यक्ति एक बुरा कोडर है या यह वास्तव में ऐसा मामला है जहां गोटो इसके लायक था? मुझे इसे स्वयं तय करने में 5 मिनट लगने चाहिए या इस पर शोध करना चाहिए?" इंटरनेट।" जब आप पूरी तरह से गोटो का उपयोग नहीं कर सकते हैं तो पृथ्वी पर आप अपने भविष्य के कोडर के साथ ऐसा क्यों करेंगे?

सामान्य तौर पर यह मानसिकता सभी "खराब" कोड पर लागू होती है और यहां तक ​​कि इसे परिभाषित भी करती है: यदि यह अब काम करता है, और इस मामले में अच्छा है, लेकिन यह सत्यापित करने का प्रयास करता है कि यह सही है, जो इस युग में एक गोटो हमेशा करेगा, तो नहीं कर दो।

यह कहा जा रहा है, हां, आपने थोड़े थोर्नियर मामलों का उत्पादन किया है। आप कर सकते हैं:

  • दोनों छोरों को तोड़ने के लिए, बूलियन ध्वज की तरह अधिक जटिल नियंत्रण संरचनाओं का उपयोग करें
  • अपने अंदर के पाश को अपनी दिनचर्या (संभावित आदर्श) के अंदर रखें
  • दोनों छोरों को एक दिनचर्या में रखें और तोड़ने के बजाय वापस लौटें

मेरे लिए एक ऐसा मामला बनाना बहुत मुश्किल है, जहां डबल-लूप इतना सामंजस्यपूर्ण न हो कि इसे वैसे भी अपनी दिनचर्या न बनाया जाए।

वैसे, मैंने जो सबसे अच्छी चर्चा देखी है वह स्टीव मैककोनेल का कोड कम्प्लीट है । यदि आप गंभीर रूप से इन समस्याओं के बारे में सोचने का आनंद लेते हैं, तो मैं दृढ़ता से पढ़ने की सलाह देता हूं, यहां तक ​​कि इसकी अपरिपक्वता के बावजूद कवर-टू-कवर।


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

1
@ डाटबुड्डा को स्वीकार किए गए सॉफ्टवेयर कोडिंग सम्मेलनों का उल्लंघन करने में लागत है जिसे पर्याप्त रूप से ध्यान में रखा जाना चाहिए। एक कार्यक्रम में उपयोग की जाने वाली नियंत्रण संरचनाओं की विविधता को बढ़ाने में लागत होती है, भले ही यह नियंत्रण संरचना किसी स्थिति के लिए एक अच्छी फिट हो सकती है। कोड के स्थिर विश्लेषण को तोड़ने में लागत है। यदि यह सब अभी भी इसके लायक है तो मैं कौन हूँ बहस करने के लिए।
djechlin

1

TLD; DR: विशिष्ट में नहीं, हाँ सामान्य तौर पर

आपके द्वारा उपयोग किए जाने वाले विशिष्ट उदाहरण के लिए मैं कहूंगा कि उन्हीं कारणों के लिए जो कई अन्य ने इंगित किए हैं। आप आसानी से एक समान रूप से अच्छे फॉर्म में कोड को रीफैक्टर कर सकते हैं जो की आवश्यकता को समाप्त करता है goto

सामान्य रूप से इसके खिलाफ अभियोजन gotoएक सामान्यता है जो कि इसके उपयोग की समझ gotoऔर लागत पर आधारित है। सॉफ्टवेयर इंजीनियरिंग का एक हिस्सा कार्यान्वयन निर्णय ले रहा है। उन फैसलों का औचित्य लाभ के खिलाफ लागत को तौलने से होता है और जब भी लाभ लागत को लागू करता है, तो उचित है। लागत और लाभ दोनों के अलग-अलग मूल्यांकन के कारण विवाद पैदा होता है।

मुद्दा यह है कि हमेशा अपवाद होंगे जहां ए gotoन्यायसंगत है, लेकिन केवल कुछ के लिए अलग-अलग वैल्यूएशन के कारण। अफ़सोस की बात यह है कि कई इंजीनियर उद्देश्यपूर्ण अज्ञानता में तकनीकों को छोड़ देते हैं क्योंकि वे इसे समझने के लिए समय निकालने के बजाय इंटरनेट पर पढ़ते हैं।


क्या आप मूल्य के बारे में बताते हुए गोटो बयान पर कोई लेख सुझा सकते हैं?
Thys

-1

मुझे नहीं लगता कि यह मामला अपवाद को सही ठहराता है, क्योंकि इसे इस प्रकार लिखा जा सकता है:

def outerLoop(){
    for (i = 0; i < 10; i++) {
        if( broken?(i) )
          return; // broken
    }
}

def broken?(i){
   for (j = 10; j > 0; j--) {
        if (j == i) {
            return true; // broken
        }
   }
   return false; // not broken
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.