Hata: Vaka etiketine atla


229

Anahtar deyimlerinin kullanımını içeren bir program yazdım ... Ancak derleme gösterir:

Hata: Vaka etiketine atla.

Neden bunu yapıyor?

#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
Hangi kodu derlemeye çalışıyorsunuz? Hangi derleyiciyi kullanıyorsunuz? Her casebloğu parantez içine aldınız mı ?
Cody Gray

2
Bu etkileyici bir dolambaçlı hata mesajı
jozxyqk

Yanıtlar:


437

Sorun, açık bir blok kullanılmadıkça birinde bildirilen değişkenlerin casesonraki cases'de hala görünebilmesidir { }, ancak başlatma kodu diğerine ait olduğu için başlatılmayacaklardır case.

Aşağıdaki kodda, foo1'e eşitse, her şey yolundadır, ancak 2'ye eşitse, yanlışlıkla ivar olan ancak muhtemelen çöp içeren değişkeni kullanacağız .

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

Vakayı açık bir blokta sarmak sorunu çözer:

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
}

Düzenle

Daha ayrıntılı olarak switchifade etmek gerekirse, ifadeler sadece süslü bir tür a goto. İşte aynı sorunu sergileyen, ancak aşağıdakinin gotoyerine kullanılan analog bir kod parçası 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
Diğer açıklamalar için bu düzeltilmiş LLVM hata raporuna bakın: llvm.org/bugs/show_bug.cgi?id=7789
Francesco

70

Olgu ifadelerinde yeni değişkenlerin bildirilmesi sorunlara neden olan şeydir. Tüm caseifadelerin içine {}alınması, yeni bildirilen değişkenlerin kapsamını, o anda yürütülen ve sorunu çözen durumla sınırlar.

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

temiz düzeltme talimatı
yc_yuy

Break deyimini kıvırcık parantez içine koyarsam herhangi bir sorun olur mu?
Vishal Sharma

11

Bazı başlatmaların üzerine atlamak için C ++ 11 standardı

JohannesD şimdi standartlar için bir açıklama yaptı.

C ++ 11 N3337 standart taslak 6.7 "Beyan açıklamada" diyor:

3 Bir bloğa aktarmak mümkündür, ancak başlatmalarla bildirimleri atlayacak şekilde değil. Otomatik saklama süresine sahip bir değişkenin kapsamda olmadığı bir noktadan, değişkenin skaler tipe, önemsiz bir varsayılan kurucuya sahip sınıf tipine ve önemsiz bir sürece sahip olmadıkça kapsamının oluşmadığı noktaya atlayan bir program (87) yıkıcı, bu türlerden birinin cv nitelikli bir sürümü veya önceki türlerden bir dizi ve bir başlatıcısı olmadan bildirildi (8.5).

87) Bir anahtar ifadesinin durumundan bir vaka etiketine aktarım bu açıdan bir sıçrama olarak kabul edilir.

[ Misal:

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
}

- son örnek]

GCC 5.2'den itibaren hata mesajı şunu söylüyor:

başlatılması haçlar

C

C buna izin verir: c99 başlangıç ​​durumuna geçti

C99 N1256 standart taslak Ek I "Ortak uyarılar" diyor:

2 Otomatik saklama süresi olan bir nesnenin başlatılması ile bir blok atlanır


6

JohannesD'nin cevabı doğru, ama sorunun bir yönüyle tamamen açık olmadığını hissediyorum.

Verdiği örnek beyan ve değişken başlatır idurumda 1 ve sonra O'nun argüman anahtarı durumunda 2 düz giderse, yani 2. ihtimaline karşı kullanmaya çalışır ibaşlatıldı olmadan kullanılacak ve bir derleme var bu yüzden hata. Bu noktada, bir vakada beyan edilen değişkenler asla başka durumlarda kullanılmazsa sorun olmayacağını düşünebilir. Örneğin:

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

Bu programın derlenmesi beklenebilir, çünkü her ikisi de ive jsadece onları bildiren durumlarda kullanılır. Ne yazık ki, C ++ 'da derlenmez: Ciro Santilli 包子 露 宪 六四 事件 法轮功 açıkladığı gibi , sadece atlayamayız case 2:, çünkü bu bildirimin başlatılmasıyla atlanır ive case 2hiç kullanılmazsa ida, bu C ++ 'da hala yasak.

İlginçtir, (bir bazı düzeltmelerle #ifdefiçin #includeçünkü uygun başlığında ve etiketler sonra bir noktalı virgül, etiketler sadece ifadeler tarafından takip edilebilir ve beyanlar C ifadeleri olarak sayılmaz ), bu program yapar C derleme:

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

Gibi bir online derleyici sayesinde http://rextester.com hızlı MSVC, GCC veya çınlama kullanarak, C veya C ++ olarak ya da derlemeye deneyebilirsiniz. C olarak her zaman çalışır (sadece STDIN ayarlamayı unutmayın!), Çünkü C ++ hiçbir derleyici bunu kabul etmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.