Error: Salte a la etiqueta del caso

Escribí un progtwig que implica el uso de instrucciones de cambio … Sin embargo, en la comstackción muestra:

Error: salta a la etiqueta de la caja.

¿Porque hace eso?

#include  #include  #include  #include  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<>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<>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<>phno; d[i1].phonenumber=phno; cout<>add; d[i1].address=add; i1++; i++; break;//Exit Case 1 to the main menu case 2: cout<>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<>ch; if(ch=='y'|| ch=='Y'){ cout<>phno; for(int j=0;j<=i;j++){ if(d[j].phonenumber==phno && staticname==d[j].name){ cout<>ch; if(ch=='y'||ch=='Y'){ cout<>name; d[j].name=name; } cout<>ch; if(ch=='y'||ch=='Y'){ cout<>phno1; d[j].phonenumber=phno1; } cout<>ch; if(ch=='y'||ch=='Y'){ cout<>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; } 

El problema es que las variables declaradas en un case siguen siendo visibles en el case subsiguiente a menos que se use un bloque { } explícito, pero no se inicializarán porque el código de inicialización pertenece a otro case .

En el siguiente código, si foo es igual a 1, todo está bien, pero si es igual a 2, accidentalmente usaremos la variable i que existe pero que probablemente contenga basura.

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

Envolver la caja en un bloque explícito resuelve el problema:

 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 } 

Editar

Para seguir elaborando, las declaraciones de switch son solo un tipo de goto particularmente elegante. Aquí hay una pieza de código análoga que muestra el mismo problema pero que utiliza un goto lugar de un 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; } 

La statement de nuevas variables en las declaraciones de casos es lo que causa problemas. Encerrar todas las declaraciones de case en {} limitará el scope de las variables recién declaradas al caso de ejecución actual que resuelve el problema.

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

Estándar C ++ 11 saltando sobre algunas inicializaciones

JohannesD dio una explicación, ahora para los estándares.

Proyecto estándar C ++ 11 N3337 6.7 Declaración de statement 3) dice:

Es posible transferir a un bloque, pero no de una manera que puentee las declaraciones con la inicialización. Un progtwig que salta (87) desde un punto donde una variable con duración de almacenamiento automática no está en scope hasta un punto en el que está dentro del scope está mal formado a menos que la variable tenga tipo escalar, tipo de clase con un constructor trivial predeterminado y un trivial destructor, una versión cv-calificada de uno de estos tipos, o una matriz de uno de los tipos anteriores y se declara sin un inicializador (8.5).

87) La transferencia de la condición de una statement de cambio a una etiqueta de caso se considera un salto en este sentido.

[Ejemplo:

 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 } 

– ejemplo final]

A partir de GCC 5.2, el mensaje de error ahora dice:

cruza la inicialización de

do

C lo permite: c99 pasó a la inicialización

C99 N1256 proyecto estándar Anexo I Advertencias comunes 2) dice:

Se salta a un bloque con inicialización de un objeto que tiene una duración de almacenamiento automática

La respuesta de JohannesD es correcta, pero creo que no está del todo claro en un aspecto del problema.

El ejemplo que él da declara e inicializa la variable i en el caso 1, y luego trata de usarla en el caso 2. Su argumento es que si el interruptor fuera directo al caso 2, se usaría sin inicializar, y esta es la razón por la cual hay un error de comstackción En este punto, uno podría pensar que no habría problemas si las variables declaradas en un caso nunca se usaran en otros casos. Por ejemplo:

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

Uno podría esperar que este progtwig comstackra, ya que tanto i como j se usan solo dentro de los casos que los declaran. Desafortunadamente, en C ++ no comstack: como explicó Ciro Santilli, 露,,,,, simplemente no podemos saltar al case 2: porque esto omitirá la statement con la inicialización de i , y aunque el case 2 no lo hace No uso i en absoluto, esto todavía está prohibido en C ++.

Curiosamente, con algunos ajustes (un #ifdef para #ifdef el encabezado apropiado, y un punto y coma después de las tags, porque las tags solo pueden ser seguidas por las declaraciones, y las declaraciones no cuentan como declaraciones en C ), este progtwig se comstack como C:

 // Disable warning issued by MSVC about scanf being deprecated #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #ifdef __cplusplus #include  #else #include  #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; } } 

Gracias a un comstackdor en línea como http://rextester.com , puede intentar comstackrlo rápidamente como C o C ++, utilizando MSVC, GCC o Clang. Como C siempre funciona (¡simplemente recuerde establecer STDIN!), Como C ++ ningún comstackdor lo acepta.