त्रुटि: जंप टू केस लेबल


229

मैंने एक प्रोग्राम लिखा जिसमें स्विच स्टेटमेंट का उपयोग शामिल है ... हालाँकि संकलन पर यह पता चलता है:

त्रुटि: जंप टू केस लेबल।

वह ऐसा क्यों करता है?

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>

using namespace std;

class contact
{
public:
    string name;
    int phonenumber;
    string address;
    contact() {
        name= "Noname";
        phonenumber= 0;
        address= "Noaddress";
    }
};

int main() {
    contact *d;
    d = new contact[200];
    string name,add;
    int choice,modchoice,t;//Variable for switch statement
    int phno,phno1;
    int i=0;
    int initsize=0, i1=0;//i is declared as a static int variable
    bool flag=false,flag_no_blank=false;

    //TAKE DATA FROM FILES.....
    //We create 3 files names, phone numbers, Address and then abstract the data from these files first!
    fstream f1;
    fstream f2;
    fstream f3;
    string file_input_name;
    string file_input_address;
    int file_input_number;

    f1.open("./names");
    while(f1>>file_input_name){
        d[i].name=file_input_name;
        i++;
    }
    initsize=i;

    f2.open("./numbers");
    while(f2>>file_input_number){
        d[i1].phonenumber=file_input_number;
        i1++;
    }
    i1=0;

    f3.open("./address");
    while(f3>>file_input_address){
        d[i1].address=file_input_address;
        i1++;
    }

    cout<<"\tWelcome to the phone Directory\n";//Welcome Message
    do{
        //do-While Loop Starts
        cout<<"Select :\n1.Add New Contact\n2.Update Existing Contact\n3.Display All Contacts\n4.Search for a Contact\n5.Delete a  Contact\n6.Exit PhoneBook\n\n\n";//Display all options
        cin>>choice;//Input Choice from user

        switch(choice){//Switch Loop Starts
        case 1:
            i++;//increment i so that values are now taken from the program and stored as different variables
            i1++;
            do{
                cout<<"\nEnter The Name\n";
                cin>>name;
                if(name==" "){cout<<"Blank Entries are not allowed";
                flag_no_blank=true;
                }
            }while(flag_no_blank==true);
            flag_no_blank=false;
            d[i].name=name;
            cout<<"\nEnter the Phone Number\n";
            cin>>phno;
            d[i1].phonenumber=phno;
            cout<<"\nEnter the address\n";
            cin>>add;
            d[i1].address=add;
            i1++;
            i++;
            break;//Exit Case 1 to the main menu
        case 2:
            cout<<"\nEnter the name\n";//Here it is assumed that no two contacts can have same contact number or address but may have the same name.
            cin>>name;
            int k=0,val;
            cout<<"\n\nSearching.........\n\n";
            for(int j=0;j<=i;j++){
                if(d[j].name==name){
                    k++;
                    cout<<k<<".\t"<<d[j].name<<"\t"<<d[j].phonenumber<<"\t"<<d[j].address<<"\n\n";
                    val=j;
                }
            }
            char ch;
            cout<<"\nTotal of "<<k<<" Entries were found....Do you wish to edit?\n";
            string staticname;
            staticname=d[val].name;
            cin>>ch;
            if(ch=='y'|| ch=='Y'){
                cout<<"Which entry do you wish to modify ?(enter the old telephone number)\n";
                cin>>phno;
                for(int j=0;j<=i;j++){
                    if(d[j].phonenumber==phno && staticname==d[j].name){
                        cout<<"Do you wish to change the name?\n";
                        cin>>ch;
                        if(ch=='y'||ch=='Y'){
                            cout<<"Enter new name\n";
                            cin>>name;
                            d[j].name=name;
                        }
                        cout<<"Do you wish to change the number?\n";
                        cin>>ch;
                        if(ch=='y'||ch=='Y'){
                            cout<<"Enter the new number\n";
                            cin>>phno1;
                            d[j].phonenumber=phno1;
                        }
                        cout<<"Do you wish to change the address?\n";
                        cin>>ch;
                        if(ch=='y'||ch=='Y'){
                            cout<<"Enter the new address\n";
                            cin>>add;
                            d[j].address=add;
                        }
                    }
                }
            }
            break;
        case 3 : {
            cout<<"\n\tContents of PhoneBook:\n\n\tNames\tPhone-Numbers\tAddresses";
            for(int t=0;t<=i;t++){
                cout<<t+1<<".\t"<<d[t].name<<"\t"<<d[t].phonenumber<<"\t"<<d[t].address;
            }
            break;
                 }
        }
    }
    while(flag==false);
    return 0;
}

1
आप किस कोड को संकलित करने का प्रयास कर रहे हैं? आप किस कंपाइलर का उपयोग कर रहे हैं? क्या आपने प्रत्येक caseब्लॉक को ब्रेसिज़ में संलग्न किया है?
कोड़ी ग्रे

2
यह एक प्रभावशाली राउंडअबाउट त्रुटि संदेश है
jozxyqk

जवाबों:


437

समस्या यह है कि एक में घोषित चर caseअभी भी बाद की caseएस में दिखाई दे रहे हैं जब तक कि एक स्पष्ट { }ब्लॉक का उपयोग नहीं किया जाता है, लेकिन उन्हें प्रारंभ नहीं किया जाएगा क्योंकि प्रारंभिक कोड दूसरे से संबंधित है case

निम्नलिखित कोड में, यदि foo1 के बराबर है , तो सब कुछ ठीक है, लेकिन अगर यह 2 के बराबर है, तो हम गलती से उस iचर का उपयोग करेंगे जो मौजूद है, लेकिन शायद कचरा है।

switch(foo) {
  case 1:
    int i = 42; // i exists all the way to the end of the switch
    dostuff(i);
    break;
  case 2:
    dostuff(i*2); // i is *also* in scope here, but is not initialized!
}

एक स्पष्ट ब्लॉक में मामले को लपेटकर समस्या हल करती है:

switch(foo) {
  case 1:
    {
        int i = 42; // i only exists within the { }
        dostuff(i);
        break;
    }
  case 2:
    dostuff(123); // Now you cannot use i accidentally
}

संपादित करें

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

int main() {
    if(rand() % 2) // Toss a coin
        goto end;

    int i = 42;

  end:
    // We either skipped the declaration of i or not,
    // but either way the variable i exists here, because
    // variable scopes are resolved at compile time.
    // Whether the *initialization* code was run, though,
    // depends on whether rand returned 0 or 1.
    std::cout << i;
}

1
अन्य स्पष्टीकरणों के लिए यह निर्धारित एलएलवीएम बग रिपोर्ट देखें: llvm.org/bugs/show_bug.cgi?id=7789
फ्रांसेस्को

70

मामले के बयानों में नए चर की घोषणा के कारण समस्याएँ पैदा हो रही हैं। सभी caseबयानों को संलग्न {}करने से वर्तमान में निष्पादित मामले में नए घोषित चर के दायरे को सीमित किया जाएगा जो समस्या को हल करता है।

switch(choice)
{
    case 1: {
       // .......
    }break;
    case 2: {
       // .......
    }break;
    case 3: {
       // .......
    }break;
}    

क्लीनर तय निर्देश
yc_yuy

अगर मैं घुंघराले ब्रेस के अंदर ब्रेक स्टेटमेंट डालती हूं तो क्या कोई समस्या होगी?
विशाल शर्मा

10

C ++ 11 मानक कुछ इनिशियलाइज़ेशन पर कूदने पर

जोहान्सड ने एक स्पष्टीकरण दिया, अब मानकों के लिए।

सी ++ 11 N3337 मानक मसौदा 6.7 "घोषणा बयान" कहते हैं:

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

87) स्विच स्टेटमेंट की स्थिति से केस लेबल में स्थानांतरण को इस संबंध में एक छलांग माना जाता है।

[ उदाहरण:

void f() {
   // ...
  goto lx;    // ill-formed: jump into scope of a
  // ...
ly:
  X a = 1;
  // ...
lx:
  goto ly;    // OK, jump implies destructor
              // call for a followed by construction
              // again immediately following label ly
}

- अंतिम उदाहरण]

GCC 5.2 के अनुसार, त्रुटि संदेश अब कहता है:

के आरंभीकरण को पार करता है

सी

C इसे अनुमति देता है: c99 गोटो पिछले आरंभीकरण

C99 N1256 मानक प्रारूप अनुलग्नक "सामान्य चेतावनियां" कहते हैं:

2 एक ऐसी वस्तु के आरम्भिकरण के साथ एक ब्लॉक जिसमें स्वत: भंडारण अवधि होती है


6

जोहान्सड का उत्तर सही है, लेकिन मुझे लगता है कि यह समस्या के एक पहलू पर पूरी तरह से स्पष्ट नहीं है।

वह उदाहरण जो घोषित करता है और iमामले 1 में चर को आरंभीकृत करता है, और फिर मामले 2 में इसका उपयोग करने की कोशिश करता है। उनका तर्क है कि यदि स्विच सीधे केस 2 में चला गया, iतो इसका उपयोग प्रारंभिक किए बिना किया जाएगा, और यही कारण है कि एक संकलन है त्रुटि। इस बिंदु पर, कोई सोच सकता है कि अगर किसी मामले में घोषित चर को अन्य मामलों में उपयोग नहीं किया जाता है तो कोई समस्या नहीं होगी। उदाहरण के लिए:

switch(choice) {
    case 1:
        int i = 10; // i is never used outside of this case
        printf("i = %d\n", i);
        break;
    case 2:
        int j = 20; // j is never used outside of this case
        printf("j = %d\n", j);
        break;
}

एक इस कार्यक्रम को संकलित करने की उम्मीद कर सकता है, दोनों के बाद से iऔर jकेवल मामलों है कि उन्हें घोषित अंदर किया जाता है। दुर्भाग्यवश, C ++ में यह संकलित नहीं है: जैसा कि Ciro Santilli 露 it it it can't ने समझाया , हम केवल case 2:इसलिए नहीं कूद सकते , क्योंकि यह घोषणा के आरंभ के साथ छोड़ देता है i, और भले ही case 2यह बिल्कुल भी उपयोग न करता हो i, यह अभी भी C ++ में निषिद्ध है।

दिलचस्प बात यह है कुछ समायोजन (एक साथ #ifdefकरने के लिए #includeउचित हेडर, और लेबल के बाद अर्धविराम, क्योंकि लेबल केवल बयान के बाद किया जा सकता है, और घोषणाओं सी में बयान के रूप में गिनती नहीं है ), इस कार्यक्रम करता संकलन सी के रूप में:

// Disable warning issued by MSVC about scanf being deprecated
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#ifdef __cplusplus
#include <cstdio>
#else
#include <stdio.h>
#endif

int main() {

    int choice;
    printf("Please enter 1 or 2: ");
    scanf("%d", &choice);

    switch(choice) {
        case 1:
            ;
            int i = 10; // i is never used outside of this case
            printf("i = %d\n", i);
            break;
        case 2:
            ;
            int j = 20; // j is never used outside of this case
            printf("j = %d\n", j);
            break;
    }
}

Http://rextester.com जैसे ऑनलाइन कंपाइलर के लिए धन्यवाद, आप MSVC, GCC या क्लैंग का उपयोग करके जल्दी से इसे C या C ++ के रूप में संकलित करने का प्रयास कर सकते हैं। सी के रूप में यह हमेशा काम करता है (बस स्टैडिन सेट करना याद रखें!), क्योंकि सी ++ कोई संकलक इसे स्वीकार नहीं करता है।

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