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
Error: Jump to case label
提问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 case
are still visible in the subsequent case
s unless an explicit {?}
block is used, but they will not be initializedbecause the initialization code belongs to another case
.
问题是在 onecase
中声明的变量在后续case
s中仍然可见,除非使用显式{?}
块,但它们不会被初始化,因为初始化代码属于 another case
。
In the following code, if foo
equals 1, everything is ok, but if it equals 2, we'll accidentally use the i
variable 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, switch
statements are just a particularly fancy kind of a goto
. Here's an analoguous piece of code exhibiting the same issue but using a goto
instead 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 case
statements 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 i
in case 1, and then tries to use it in case 2. His argument is that if the switch went straight to case 2, i
would 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 i
and j
are 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 2
doesn't use i
at all, this is still forbidden in C++.
人们可以期望这个程序能够编译,因为i
和j
仅在声明它们的情况下使用。不幸的是,在 C++ 中它不能编译:正如fxsc 包子露宪所解释的那样,我们根本无法跳转到case 2:
,因为这将跳过初始化为 的声明i
,即使case 2
根本不使用i
,这在 C++ 中仍然是禁止的。
Interestingly, with some adjustments (an #ifdef
to #include
the 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++ 没有编译器接受它。