C++ 错误:跳转到案例标签

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5685471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:39:58  来源:igfitidea点击:

Error: Jump to case label

c++

提问by Frustrated Coder

I wrote a program which involves use of switch statements... However on compilation it shows:

我写了一个涉及使用 switch 语句的程序......但是在编译时它显示:

Error: Jump to case label.

错误:跳转到案例标签。

Why does it do that?

为什么这样做?

#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;
}

回答by JohannesD

The problem is that variables declared in one caseare still visible in the subsequent cases unless an explicit {?}block is used, but they will not be initializedbecause the initialization code belongs to another case.

问题是在 onecase中声明的变量在后续cases中仍然可见,除非使用显式{?}块,但它们不会被初始化,因为初始化代码属于 another case

In the following code, if fooequals 1, everything is ok, but if it equals 2, we'll accidentally use the ivariable which does exist but probably contains garbage.

在下面的代码中,如果foo等于 1,则一切正常,但如果等于 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!
}

Wrapping the case in an explicit block solves the problem:

将案例包装在一个显式块中解决了这个问题:

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
}

Edit

编辑

To further elaborate, switchstatements are just a particularly fancy kind of a goto. Here's an analoguous piece of code exhibiting the same issue but using a gotoinstead of a switch:

更详细地说,switch语句只是一种特别奇特的 a goto。这是一段类似的代码,显示了相同的问题,但使用了 agoto而不是 a 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;
}

回答by Mahesh

Declaration of new variables in case statements is what causing problems. Enclosing all casestatements in {}will limit the scope of newly declared variables to the currently executing case which solves the problem.

在 case 语句中声明新变量是导致问题的原因。将所有case语句括起来{}会将新声明的变量的范围限制在解决问题的当前正在执行的案例中。

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

回答by Fabio says Reinstate Monica

JohannesD's answeris correct, but I feel it isn't entirely clear on an aspect of the problem.

JohannesD 的回答是正确的,但我觉得问题的某个方面并不完全清楚。

The example he gives declares and initializes the variable iin case 1, and then tries to use it in case 2. His argument is that if the switch went straight to case 2, iwould be used without being initialized, and this is why there's a compilation error. At this point, one could think that there would be no problem if variables declared in a case were never used in other cases. For example:

他举的例子i在case 1中声明并初始化了变量,然后在case 2中尝试使用它。他的论点是,如果switch直接进入case 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;
}

One could expect this program to compile, since both iand jare used only inside the cases that declare them. Unfortunately, in C++ it doesn't compile: as fxsc 包子露宪 explained, we simply can't jump to case 2:, because this would skip the declaration with initialization of i, and even though case 2doesn't use iat all, this is still forbidden in C++.

人们可以期望这个程序能够编译,因为ij仅在声明它们的情况下使用。不幸的是,在 C++ 中它不能编译:正如fxsc 包子露宪所解释的那样,我们根本无法跳转到case 2:,因为这将跳过初始化为 的声明i,即使case 2根本不使用i,这在 C++ 中仍然是禁止的。

Interestingly, with some adjustments (an #ifdefto #includethe appropriate header, and a semicolon after the labels, because labels can only be followed by statements, and declarations do not count as statements in C), this program doescompile as C:

有趣的是,有一些调整(一#ifdef#include适当的标题,标签后分号,因为标签只能跟着声明,并声明不算作C语句),这个程序确实编译为C:

// 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;
    }
}

Thanks to an online compiler like http://rextester.comyou can quickly try to compile it either as C or C++, using MSVC, GCC or Clang. As C it always works (just remember to set STDIN!), as C++ no compiler accepts it.

感谢像http://rextester.com这样的在线编译器,您可以使用 MSVC、GCC 或 Clang 快速尝试将其编译为 C 或 C++。因为 C 它总是有效(只要记住设置 STDIN!),因为 C++ 没有编译器接受它。