오류 : 사례 라벨로 이동


229

switch 문을 사용하는 프로그램을 작성했지만 컴파일시 다음과 같이 표시됩니다.

오류 : 사례 라벨로 이동합니다.

왜 그렇게합니까?

#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 버그 보고서를 참조하십시오. llvm.org/bugs/show_bug.cgi?id=7789
Francesco

70

경우 문에서 새 변수를 선언하면 문제가 발생합니다. 모든 case명령문을 묶으면 {}새로 선언 된 변수의 범위가 현재 실행중인 케이스로 제한되어 문제가 해결됩니다.

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

더 명확한 수정 지시
yc_yuy

중괄호 안에 break 문을 넣으면 문제가 있습니까?
Vishal Sharma

10

일부 초기화에 대한 C ++ 11 표준

요하네스 는 이제 표준에 대해 설명했습니다.

C ++ 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 표준 초안 부속서 I "공통 경고"는 말합니다 :

2 자동 저장 기간이있는 객체를 초기화 한 블록으로 이동


6

JohannesD의 대답 은 정확하지만 문제의 측면에서 완전히 명확하지 않다고 생각합니다.

i사례 1은 사례 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;
}

하나는 둘 다 있기 때문에,이 프로그램을 컴파일 기대할 수 ij그들을 선언의 경우 내부에만 사용됩니다. 불행히도 C ++에서는 컴파일되지 않습니다 : Ciro Santilli 包子 露 宪 六四 事件 法轮功가 설명했듯이case 2: 으로 초기화 할 때 선언을 건너 뛰고 사용하지 i않더라도 간단히 이동할 수 없습니다.case 2i 전혀, C ++에서는 여전히 금지되어 있습니다.

흥미롭게도, (AN 일부 조정과 #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;
    }
}

http://rextester.com 과 같은 온라인 컴파일러 덕분에 MSVC, GCC 또는 Clang을 사용하여 C 또는 C ++로 빠르게 컴파일 할 수 있습니다. C에서는 항상 작동하지만 (STDIN을 설정해야 함을 기억하십시오!) C ++ 컴파일러는 그것을 허용하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.