Lỗi: Chuyển đến nhãn trường hợp


229

Tôi đã viết một chương trình liên quan đến việc sử dụng các câu lệnh chuyển đổi ... Tuy nhiên, khi biên dịch, nó hiển thị:

Lỗi: Chuyển đến nhãn trường hợp.

Tại sao nó làm điều đó?

#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
Mã nào bạn đang cố gắng biên dịch? Trình biên dịch nào bạn đang sử dụng? Bạn đã bao vây từng casekhối trong niềng răng?
Cody Grey

2
đó là một thông báo lỗi vòng xoay ấn tượng
jozxyqk

Câu trả lời:


437

Vấn đề là các biến được khai báo trong một casevẫn được hiển thị trong các cases tiếp theo trừ khi sử dụng một { }khối rõ ràng , nhưng chúng sẽ không được khởi tạo vì mã khởi tạo thuộc về một mã khác case.

Trong đoạn mã sau, nếu foobằng 1, mọi thứ đều ổn, nhưng nếu bằng 2, chúng ta sẽ vô tình sử dụng ibiến tồn tại nhưng có thể chứa rác.

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!
}

Gói trường hợp trong một khối rõ ràng giải quyết vấn đề:

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
}

Biên tập

Để giải thích thêm, các switchtuyên bố chỉ là một loại đặc biệt lạ mắt của a goto. Đây là một đoạn mã tương tự thể hiện cùng một vấn đề nhưng sử dụng gotothay vì 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
Xem báo cáo lỗi LLVM cố định này để biết các giải thích khác: llvm.org/bugs/show_orms.cgi?id=7789
Francesco

70

Khai báo các biến mới trong báo cáo trường hợp là nguyên nhân gây ra vấn đề. Việc bao gồm tất cả các casecâu lệnh trong {}sẽ giới hạn phạm vi của các biến mới được khai báo trong trường hợp hiện đang thực thi để giải quyết vấn đề.

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

hướng dẫn sửa lỗi sạch hơn
yc_yuy

Sẽ có vấn đề gì nếu tôi đặt câu lệnh break bên trong dấu ngoặc nhọn?
Vishal Sharma

10

Tiêu chuẩn C ++ 11 về nhảy qua một số khởi tạo

JohannesD đã đưa ra một lời giải thích, bây giờ cho các tiêu chuẩn.

Các C ++ 11 N3337 tiêu chuẩn dự thảo 6,7 "Tuyên bố tuyên bố" nói:

3 Có thể chuyển thành một khối, nhưng không phải theo cách bỏ qua các khai báo với khởi tạo. Một chương trình nhảy (87) từ một điểm trong đó một biến có thời gian lưu trữ tự động không nằm trong phạm vi đến một điểm mà nó nằm trong phạm vi không được định dạng trừ khi biến đó có kiểu vô hướng, loại lớp với hàm tạo mặc định tầm thường và một hàm tầm thường hàm hủy, một phiên bản đủ điều kiện cv của một trong các loại này hoặc một mảng của một trong các loại trước đó và được khai báo mà không có bộ khởi tạo (8.5).

87) Việc chuyển từ điều kiện của câu lệnh chuyển sang nhãn trường hợp được coi là một bước nhảy trong khía cạnh này.

[ Thí dụ:

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
}

- ví dụ kết thúc]

Kể từ GCC 5.2, thông báo lỗi hiện cho biết:

vượt qua khởi tạo

C

C cho phép nó: c99 goto quá trình khởi tạo

Các C99 N1256 tiêu chuẩn dự thảo Phụ lục I "cảnh báo chung" nói:

2 Một khối với khởi tạo một đối tượng có thời gian lưu trữ tự động được nhảy vào


6

Câu trả lời của JohannesD là đúng, nhưng tôi cảm thấy nó không hoàn toàn rõ ràng về một khía cạnh của vấn đề.

Ví dụ anh ta khai báo và khởi tạo biến itrong trường hợp 1, và sau đó cố gắng sử dụng nó trong trường hợp 2. Đối số của anh ta là nếu chuyển đổi sang trường hợp 2, isẽ được sử dụng mà không được khởi tạo, và đây là lý do tại sao có một trình biên dịch lỗi. Tại thời điểm này, người ta có thể nghĩ rằng sẽ không có vấn đề gì nếu các biến được khai báo trong một trường hợp không bao giờ được sử dụng trong các trường hợp khác. Ví dụ:

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

Người ta có thể mong đợi chương trình này biên dịch, vì cả hai ijchỉ được sử dụng trong các trường hợp khai báo chúng. Thật không may, trong C ++ nó không biên dịch: như Ciro Santilli包子露宪六四事件法轮功giải thích , chúng tôi chỉ đơn giản là không thể nhảy đến case 2:, vì điều này sẽ bỏ qua phần khai báo với khởi của i, và mặc dù case 2không sử dụng iở tất cả, điều này vẫn bị cấm trong C ++.

Điều thú vị là, với một số điều chỉnh (một #ifdefđể #includetiêu đề thích hợp, và một dấu chấm phẩy sau nhãn, bởi vì nhãn chỉ có thể được theo sau bởi các báo cáo, tờ khai và không được tính như báo cáo trong C ), chương trình này không biên dịch như 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;
    }
}

Nhờ một trình biên dịch trực tuyến như http://rextester.com, bạn có thể nhanh chóng cố gắng biên dịch nó dưới dạng C hoặc C ++, sử dụng MSVC, GCC hoặc Clang. Vì C luôn hoạt động (chỉ cần nhớ đặt STDIN!), Vì C ++ không có trình biên dịch nào chấp nhận nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.