केस स्टेटमेंट के बाद हमें ब्रेक की आवश्यकता क्यों है?


94

संकलक स्विच में प्रत्येक कोड ब्लॉक के बाद स्वचालित रूप से ब्रेक स्टेटमेंट क्यों नहीं डालता है? क्या यह ऐतिहासिक कारणों से है? आप कई कोड ब्लॉक को कब निष्पादित करना चाहेंगे?


2
JDK-12 और स्विच लेबल के बारे में एक उत्तर दिया, जिसमें सुधार नहीं किया गया था break
नमन

जवाबों:


94

कभी-कभी एक ही कोड ब्लॉक से जुड़े कई मामलों का होना मददगार होता है, जैसे कि

case 'A':
case 'B':
case 'C':
    doSomething();
    break;

case 'D':
case 'E':
    doSomethingElse();
    break;

आदि बस एक उदाहरण है।

मेरे अनुभव में, आमतौर पर "के माध्यम से गिर" करने के लिए यह बुरी शैली है और एक मामले के लिए कोड के कई ब्लॉक हैं, लेकिन कुछ स्थितियों में इसके लिए उपयोग हो सकते हैं।


28
// Intentional fallthrough.जब आप ब्रेक छोड़ते हैं तो बस लाइनों के साथ एक टिप्पणी जोड़ें । मेरी राय में "गलती से ब्रेक को भूल जाना आसान नहीं है" यह इतनी बुरी शैली नहीं है। PS के पाठ्यक्रम में सरल मामलों में नहीं, जैसा कि उत्तर में ही है।
२३

@doublep - मैं सहमत हूं। मेरी राय में, यदि संभव हो तो मैं इसे टाल दूंगा लेकिन अगर यह समझ में आता है तो सुनिश्चित करें कि यह बहुत स्पष्ट है कि आप क्या कर रहे हैं।
WildCrustacean

6
@ डब्लूडब्लू: अगर कई caseएस एक साथ इस तरह से स्टैक्ड हो जाते हैं तो मैं टिप्पणी से परेशान नहीं होता । यदि उनके बीच में कोड है तो हां, टिप्पणी शायद विलय की है।
बिली ओनेल

4
मैं एक ऐसी भाषा की कल्पना करता हूं, जहां आप एक के भीतर कई मामलों की घोषणा कर सकते हैं case, जैसे: case 'A','B','C': doSomething(); case 'D','E': doSomethingElse();मामलों के बीच विराम की आवश्यकता के बिना। पास्कल ऐसा कर सकता है: "केस स्टेटमेंट प्रत्येक चयनकर्ता के लिए अध्यादेशीय अभिव्यक्ति के मूल्य की तुलना करता है, जो एक स्थिरांक, एक सबरेंज या अल्पविराम द्वारा अलग की गई सूची हो सकती है।" ( wiki.freepascal.org/Case )
क्रिश्चियन

32

ऐतिहासिक रूप से , ऐसा इसलिए है क्योंकि यह caseअनिवार्य रूप से परिभाषित कर रहा है label, जिसे कॉल का लक्ष्य बिंदु भी कहा जाता है goto। स्विच स्टेटमेंट और इससे जुड़े मामले वास्तव में कोड की एक धारा में कई संभावित प्रवेश बिंदुओं के साथ एक मल्टीवे शाखा का प्रतिनिधित्व करते हैं।

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


30

Java C से आता है और C से वाक्य रचना है।

ऐसे समय होते हैं, जब आप एक निष्पादन पथ के लिए कई केस स्टेटमेंट चाहते हैं। नीचे एक नमूना है जो आपको बताएगा कि महीने में कितने दिन हैं।

class SwitchDemo2 {
    public static void main(String[] args) {

        int month = 2;
        int year = 2000;
        int numDays = 0;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                numDays = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                numDays = 30;
                break;
            case 2:
                if ( ((year % 4 == 0) && !(year % 100 == 0))
                     || (year % 400 == 0) )
                    numDays = 29;
                else
                    numDays = 28;
                break;
            default:
                System.out.println("Invalid month.");
                break;
        }
        System.out.println("Number of Days = " + numDays);
    }
}

4
किसी ने ऊपर तीर के लिए निशाना बनाया और चूक गए? या हो सकता है कि उन्हें आपकी ब्रेस स्टाइल या इंडेंटेशन के साथ बीफ मिला हो ...
जिम लुईस

डन्नो, तो मेरे से एक +1 है। यह एक उदाहरण है जहां गिरावट से मदद मिलती है, हालांकि मैं वास्तव में चाहता हूं कि जावा ने अधिक आधुनिक मामला बयान उठाया था। कोबोल का EVALUATE-WHEN-OTHERWISE कहीं अधिक शक्तिशाली है, और जावा को भविष्यवाणी करता है। स्काला की मैच अभिव्यक्ति एक आधुनिक उदाहरण है कि क्या किया जा सकता है।
बजे जिम फेरनस

1
मेरे छात्रों को ऐसा करने के लिए सार्वजनिक रूप से फटकारा जाएगा। यह बदसूरत है।
ncmathsadist

2
@ncmathsadist यह कुछ करने के एक तरीके पर एक बिंदु दिखाता है। मैं असहमत नहीं हूं कि यह उदाहरण शायद अतिवादी है। लेकिन यह एक वास्तविक दुनिया का उदाहरण है, जो मेरा मानना ​​है कि लोगों को एक अवधारणा को समझने में मदद करता है।
रोमेन हिप्पो

15

मुझे लगता है कि यह एक गलती है। एक भाषा के निर्माण के breakरूप में यह डिफ़ॉल्ट के रूप में आसान है और इसके बजाय एक fallthroughखोजशब्द है। मेरे द्वारा लिखे और पढ़े गए अधिकांश कोड में हर मामले के बाद एक विराम होता है।


4
मैं यह सुझाव देना चाहता हूं कि continue <case name>कौन सा मामला बयान जारी रखने के लिए स्पष्ट रूप से निर्दिष्ट करने की अनुमति देता है;
विल्क्स-

4
@Vilx जब caseवर्तमान के भीतर एक मनमाना अनुमति देता है switch, तो यह बस एक बन जाता है goto। ;-)
क्रिश्चियन सेमरू

13

केस फॉल-थ्रू आप हर तरह की दिलचस्प चीजें कर सकते हैं।

उदाहरण के लिए, हम कहते हैं कि आप सभी मामलों के लिए एक विशेष कार्रवाई करना चाहते हैं, लेकिन एक निश्चित मामले में आप उस कार्रवाई को कुछ और करना चाहते हैं। फॉल-थ्रू के साथ एक स्विच स्टेटमेंट का उपयोग करना काफी आसान होगा।

switch (someValue)
{
    case extendedActionValue:
        // do extended action here, falls through to normal action
    case normalActionValue:
    case otherNormalActionValue:
        // do normal action here
        break;
}

बेशक, breakकिसी मामले के अंत में बयान को भूलना और अप्रत्याशित व्यवहार का कारण बनाना आसान है। जब आप ब्रेक स्टेटमेंट को छोड़ते हैं तो अच्छे कंपाइलर आपको चेतावनी देंगे।


जावा में तार पर स्विच / केस का उपयोग किया जा सकता है?
स्टीव कूओ

@ सेतेव: उफ़, मुझे लगता है कि फिलहाल नहीं। के अनुसार stackoverflow.com/questions/338206/... , तार जावा के भविष्य के संस्करण में अनुमति दी जाएगी। (मैं वर्तमान में C # में अपनी अधिकांश प्रोग्रामिंग करता हूं, जो स्विच स्टेटमेंट में स्ट्रिंग्स की अनुमति देता है।) मैंने भ्रामक उद्धरणों को हटाने के लिए उत्तर संपादित किया है।
जैच जॉनसन

2
@ZachJohnson, बहुत बाद में, जावा 7 स्ट्रिंग्स पर स्विच की अनुमति देता है।
बॉब क्रॉस

7

संकलक स्विच में प्रत्येक कोड ब्लॉक के बाद स्वचालित रूप से ब्रेक स्टेटमेंट क्यों नहीं डालता है?

एक तरफ छोड़कर अच्छा इच्छा कई मामलों के लिए समान ब्लॉक (जो विशेष मामलों हो सकता है) का उपयोग करने में सक्षम हो ...

क्या यह ऐतिहासिक कारणों से है? आप कई कोड ब्लॉक को कब निष्पादित करना चाहेंगे?

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


5

breakके बाद स्विच cases स्विच बयान में fallthrough से बचने के लिए प्रयोग किया जाता है। हालांकि दिलचस्प रूप से यह अब JEP-325 के माध्यम से कार्यान्वित के रूप में नवगठित स्विच लेबल के माध्यम से प्राप्त किया जा सकता है ।

इन परिवर्तनों के breakसाथ, हर स्विच caseको आगे प्रदर्शित होने से बचा जा सकता है: -

public class SwitchExpressionsNoFallThrough {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int value = scanner.nextInt();
        /*
         * Before JEP-325
         */
        switch (value) {
            case 1:
                System.out.println("one");
            case 2:
                System.out.println("two");
            default:
                System.out.println("many");
        }

        /*
         * After JEP-325
         */
        switch (value) {
            case 1 ->System.out.println("one");
            case 2 ->System.out.println("two");
            default ->System.out.println("many");
        }
    }
}

JDK-12 के साथ उपरोक्त कोड निष्पादित करने पर , तुलनात्मक आउटपुट को देखा जा सकता है

//input
1
// output from the implementation before JEP-325
one
two
many
// output from the implementation after JEP-325
one

तथा

//input
2
// output from the implementation before JEP-325
two
many
// output from the implementation after JEP-325
two

और निश्चित रूप से बात अपरिवर्तित है

// input
3
many // default case match
many // branches to 'default' as well

4

यदि आपको एक ही काम करने के लिए कई मामलों की आवश्यकता हो तो आपको कोड दोहराना नहीं है:

case THIS:
case THAT:
{
    code;
    break;
}

या आप इस तरह की चीजें कर सकते हैं:

case THIS:
{
   do this;
}
case THAT:
{
   do that;
}

एक कैस्केड फैशन में।

वास्तव में बग / भ्रम प्रवण, यदि आप मुझसे पूछें।


क्या यह दोनों do thisऔर do thatइसके do thatलिए चलता है लेकिन सिर्फ इसके लिए?
जोनिरा

1
बस डॉक्स पढ़ें। यह अद्भुत है! कीड़े लिखने का एक आसान तरीका क्या है!
जोन्निरा

4

जहां तक ​​ऐतिहासिक रिकॉर्ड है, टोनी होरे ने 1960 के दशक में "संरचित प्रोग्रामिंग" क्रांति के दौरान केस स्टेटमेंट का आविष्कार किया था। टोनी के केस स्टेटमेंट ने प्रति मामले में कई लेबल और बिना किसी बदबू वाले breakबयानों के साथ स्वचालित निकास का समर्थन किया । एक स्पष्ट की आवश्यकता breakकुछ ऐसी थी जो BCPL / B / C लाइन से निकली थी। डेनिस रिची लिखते हैं (ACM HOPL-II में):

उदाहरण के लिए, एक BCPL स्विचन स्टेटमेंट से बचने वाला एंडकेस उस समय भाषा में मौजूद नहीं था जब हमने इसे 1960 के दशक में सीखा था, और इसलिए B और C स्विच स्टेटमेंट से बचने के लिए ब्रेक कीवर्ड का ओवरलोडिंग सचेत होने के बजाय डाइवर्टिव इवोल्यूशन के कारण होता है। परिवर्तन।

मुझे BCPL के बारे में कोई ऐतिहासिक लेखन नहीं मिला है, लेकिन रिची की टिप्पणी से पता चलता है कि breakकमोबेश यह एक ऐतिहासिक दुर्घटना थी। BCPL ने बाद में समस्या को ठीक कर दिया, लेकिन शायद रिची और थॉम्पसन भी यूनिक्स का आविष्कार करने में व्यस्त थे ताकि इस तरह के विवरण से परेशान हों :-)


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

3

जावा सी से लिया गया है, जिसकी विरासत में डफ डिवाइस के रूप में जानी जाने वाली तकनीक शामिल है । यह एक अनुकूलन है जो इस तथ्य पर निर्भर करता है कि नियंत्रण एक मामले से दूसरे तक एक break;बयान के अभाव में गिरता है । जब तक सी को मानकीकृत किया गया था, तब तक "जंगली में" जैसे बहुत सारे कोड थे, और इस तरह के निर्माणों को तोड़ने के लिए भाषा को बदलने के लिए यह प्रतिशोधात्मक होगा।


1

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

public class SwitchTester{
    private static final Log log = LogFactory.getLog(SwitchTester.class);
    public static void main(String[] args){
        log.info(monthsOfTheSeason(Season.WINTER));
        log.info(monthsOfTheSeason(Season.SPRING));
        log.info(monthsOfTheSeason(Season.SUMMER));
        log.info(monthsOfTheSeason(Season.AUTUMN));
    }

    enum Season{WINTER, SPRING, SUMMER, AUTUMN};

    static String monthsOfTheSeason(Season season){
        switch(season){
            case WINTER:
                return "Dec, Jan, Feb";
            case SPRING:
                return "Mar, Apr, May";
            case SUMMER:
                return "Jun, Jul, Aug";
            case AUTUMN:
                return "Sep, Oct, Nov";
            default:
                //actually a NullPointerException will be thrown before reaching this
                throw new IllegalArgumentException("Season must not be null");
        }        
    }
}   

निष्पादन प्रिंट:

12:37:25.760 [main] INFO lang.SwitchTester - Dec, Jan, Feb
12:37:25.762 [main] INFO lang.SwitchTester - Mar, Apr, May
12:37:25.762 [main] INFO lang.SwitchTester - Jun, Jul, Aug
12:37:25.762 [main] INFO lang.SwitchTester - Sep, Oct, Nov

जैसा सोचा था।


0

संकलक द्वारा जोड़ा गया एक स्वचालित ब्रेक नहीं होने 1 <= a <= 3से 1 और 2 से ब्रेक स्टेटमेंट को हटाकर परिस्थितियों का परीक्षण करने के लिए स्विच / केस का उपयोग करना संभव हो जाता है ।

switch(a) {
  case 1: //I'm between 1 and 3
  case 2: //I'm between 1 and 3
  case 3: //I'm between 1 and 3
          break;
}

Yecch। मुझे इससे पूरी तरह से नफरत है।
ncmathsadist

0

क्योंकि ऐसी स्थितियाँ हैं, जहाँ आप उदाहरण के लिए पहले ब्लॉक से होकर बहना चाहते हैं, क्योंकि एक ही कोड को कई ब्लॉक में लिखने से बचें, लेकिन फिर भी उन्हें एमरो कंट्रोल के लिए विभाजित करने में सक्षम हों। अन्य कारणों के एक टन भी हैं।


0

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

जैसे समय टोकन के साथ उपयोगकर्ता को प्रमाणित करने के लिए http प्रतिक्रिया कोड का उपयोग करना

सर्वर प्रतिक्रिया कोड 401 - टोकन पुराना है -> टोकन को पुन: उत्पन्न करें और उपयोगकर्ता को लॉग इन करें।
सर्वर प्रतिक्रिया कोड 200 - टोकन ठीक है -> लॉग इन उपयोगकर्ता।

मामले में बयान:

case 404:
case 500:
        {
            Log.v("Server responses","Unable to respond due to server error");
            break;
        }
        case 401:
        {
             //regenerate token
        }
        case 200:
        {
            // log in user
            break;
        }

इसका उपयोग करके आपको 401 प्रतिक्रिया के लिए उपयोगकर्ता फ़ंक्शन में लॉग कॉल करने की आवश्यकता नहीं है क्योंकि जब टोकन को पुन: उत्पन्न किया जाता है, तो रनटाइम केस 200 में कूद जाता है।


0

आप अन्य प्रकार की संख्या, माह, गणना को अलग करने के लिए आसानी से बना सकते हैं।
यह बेहतर है अगर इस मामले में;

public static void spanishNumbers(String span){

    span = span.toLowerCase().replace(" ", "");
    switch (span){
     case "1":    
     case "jan":  System.out.println("uno"); break;    
     case "2":      
     case "feb":  System.out.println("dos"); break;    
     case "3":     
     case "mar":  System.out.println("tres"); break;   
     case "4":   
     case "apr":  System.out.println("cuatro"); break;
     case "5":    
     case "may":  System.out.println("cinco"); break;
     case "6":     
     case "jun":  System.out.println("seis"); break;
     case "7":    
     case "jul":  System.out.println("seite"); break;
     case "8":    
     case "aug":  System.out.println("ocho"); break;
     case "9":   
     case "sep":  System.out.println("nueve"); break;
     case "10":    
     case "oct": System.out.println("diez"); break;
     }
 }

0

मैं अब प्रोजेक्ट पर काम कर रहा हूं जहां मुझे breakअपने स्विच स्टेटमेंट की आवश्यकता है अन्यथा कोड काम नहीं करेगा। मेरे साथ सहन करें और मैं आपको एक अच्छा उदाहरण दूंगा कि आपको breakअपने स्विच स्टेटमेंट की आवश्यकता क्यों है ।

कल्पना कीजिए कि आपके पास तीन राज्य हैं, एक जो उपयोगकर्ता के लिए एक संख्या में प्रवेश करने की प्रतीक्षा करता है, दूसरा उसकी गणना करने के लिए और तीसरा योग को मुद्रित करने के लिए।

उस मामले में आपके पास:

  1. State1 - एक नंबर दर्ज करने के लिए उपयोगकर्ता की प्रतीक्षा करें
  2. State2 - राशि प्रिंट करें
  3. राज्य 3 - राशि की गणना

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

यहाँ एक उदाहरण कोड है:

while(1){
    switch(state){
      case state1:
        // Wait for user input code
        state = state3; // Jump to state3
        break;
      case state2:
        //Print the sum code
        state = state3; // Jump to state3;
      case state3:
        // Calculate the sum code
        state = wait; // Jump to state1
        break;
    }
}

अगर हम उपयोग नहीं करते हैं break, तो यह इस क्रम में निष्पादित करेगा, राज्य 1 , राज्य 2 और राज्य 3 । लेकिन उपयोग करते हुए break, हम इस परिदृश्य से बचते हैं, और सही प्रक्रिया में आदेश दे सकते हैं, जो कि राज्य 1 से शुरू होनी है, फिर राज्य 3 और अंतिम लेकिन राज्य 2 से नहीं।


-1

बिल्कुल, क्योंकि कुछ चालाक प्लेसमेंट के साथ आप कैस्केड में ब्लॉक निष्पादित कर सकते हैं।

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