Jump to case label ошибка

JohannesD’s answer is correct, but I feel it isn’t entirely clear on an aspect of the problem.

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:

switch(choice) {
    case 1:
        int i = 10; // i is never used outside of this case
        printf("i = %dn", i);
        break;
    case 2:
        int j = 20; // j is never used outside of this case
        printf("j = %dn", 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 Ciro Santilli 包子露宪 六四事件 法轮功 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++.

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 does compile as 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 = %dn", i);
            break;
        case 2:
            ;
            int j = 20; // j is never used outside of this case
            printf("j = %dn", j);
            break;
    }
}

Thanks to an online compiler like http://rextester.com you 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.

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!
}
click below button to copy the code. By c++ tutorial team
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
}
click below button to copy the code. By c++ tutorial team
switch(choice)
{
    case 1: {
       // .......
    }break;
    case 2: {
       // .......
    }break;
    case 3: {
       // .......
    }break;
}    
click below button to copy the code. By c++ tutorial team

Очень часто начинающие программисты впадают в суеверный ужас, когда видят, что компилятор нашел в тексте программы ошибку, но не понимают, в чем она заключается.

А если помножить этот факт на незнание английского языка («чего там ему не нравится?..») и слабое владение синтаксисом C++ («хм, а может, тут нужна точка с запятой…»), то проблема принимает масштаб катастрофы.

Тот факт, что компилятор в силу своих ограниченных возможностей изо всех сил старается объяснить, что конкретно неверно, не спасает ситуацию. Как быть, если гуглить неохота, а спросить не у кого?

В этом посте на правах копипаста с последующим переводом, дополнениями и исправлениями приведу описание наиболее распространенных сообщений об ошибках и предупреждений компилятора. Неприятность кроется в том факте, что разные компиляторы ругаются на одинаковые ошибки по-разному, а некоторые даже не замечают то, что другие принимают за ошибку. Все зависит от совести разработчиков компилятора, даты его выпуска, и др.

В качестве компилятора возьмем g++, который, в частности, может использоваться в среде Code::Blocks. Версия gcc (куда входит g++) для ОС Windows зовется MinGW. По ходу я буду давать аналоги ошибок из лексикона русскоязычной Microsoft Visual C++.

Итак, частые ошибки:

undeclared identifier

1) Пример

doy.cpp: In function 'int main()':
doy.cpp:25: 'DayOfYear' undeclared (first use this function)
doy.cpp:25: (Each undeclared identifier is reported only once for each function it appears in.)
doy.cpp:25: parse error before ';' token

2) Смысл
Использован идентификатор DayOfYear, но компилятор не нашел его объявления. Он не знает, что такое DayOfYear.

3) Когда бывает

  • Вы забыли включить какой-то заголовочный файл (#include...)
  • Вы где-то ошиблись в написании идентификатора (при объявлении или использовании)
  • Вы вообще забыли, что эту переменную надо объявить

Попытавшись скомпилировать это в Microsoft Visual C++, вы увидите:

error C2065: DayOfYear: необъявленный идентификатор

cout undeclared

1) Пример

xyz.cpp: In function 'int main()':
xyz.cpp:6: 'cout' undeclared (first use this function)
xyz.cpp:6: (Each undeclared identifier is reported only once for each function it appears in.)

2) Смысл
Суперклассика. Без комментариев.

3) Когда бывает

  • Вы забыли включить <iostream>
  • Вы забыли написать using namespace std;

jump to case label

1) Пример

switch.cpp: In function 'int main()':
switch.cpp:14: jump to case label
switch.cpp:11: crosses initialization of 'int y'

2) Смысл
Смысл туманен

3) Когда бывает
Вы попытались объявить и инициализировать переменную (объект, указатель и т.п.) в метке case оператора выбора switch. Правилами C++ это запрещено.

В Microsoft Visual C++ эта ошибка зовется

error C2360: пропуск инициализации 'y' из-за метки 'case'

Выход: заключите операторы этого case’а в фигурные скобки {}.

multi-line string / unterminated string

1) Пример
Программка

#include <iostream>

using namespace std;

int main()
{
cout << "Bob is my buddy;
cout << "and so is Mary" << endl;
}

вызовет бурную реакцию компилятора:

string.cpp:7:12: warning: multi-line string literals are deprecated
string.cpp: In function 'int main()':
string.cpp:7: 'so' undeclared (first use this function)
string.cpp:7: (Each undeclared identifier is reported only once for each function it appears in.)
string.cpp:7: parse error before 'Mary'
string.cpp:8:28: warning: multi-line string literals are deprecated
string.cpp:8:28: missing terminating " character
string.cpp:7:12: possible start of unterminated string literal

2) Смысл
Компилятор думает, что мы хотим создать строковую константу с содержащимся в ней переносом строки, что-то типа

"Hello
world!"

что не поддерживается языком. Также делается предположение о том, что мы, возможно, забыли поставить кавычки в конце первой строки. Собственно, так оно и есть.

3) Когда бывает
Когда не соблюдается правильное количество и положение кавычек в строковых литералах. Надо быть внимательнее.

Microsoft Visual C++ со свойственной ему детской непосредственностью, отметит, что нельзя делать переносы в строках и возмутится, где точка с запятой:

error C2001: newline в константе
error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "cout"

comparison between signed and unsigned integer expressions

1) Пример

xyz.cpp: In function 'int main()':
xyz.cpp:54: warning: comparison between signed and unsigned integer expressions

2) Смысл
Это — предупреждение компилятора, которое говорит о том, что мы пытаемся сравнить (==, и т.д.) целочисленное выражение (может принимать положительные, отрицательные значения и 0) и беззнаковое целочисленное выражение (может быть только положительным, либо 0).

3) Когда бывает
Собственно, тогда и бывает. Напомню, что тип int по умолчанию знаковый, а некоторые функции (например, vector::size()) возвращают unsigned int.
К примеру, следующий на первый взгляд безобидный код вызовет описываемое предупреждение:

for (int i = 0; i < grades.size(); i++)
{
// ...
}

Следует помнить, что в памяти знаковые и беззнаковые типы имеют разные внутренние представления, поэтому надо быть чертовски осторожными с указателями.

В Microsoft Visual C++ предупреждение выглядит так:

warning C4018: <: несоответствие типов со знаком и без знака

suggest parentheses around assignment used as truth value

1) Пример

xyz.cpp: In function `int main()':
xyz.cpp:54: warning: suggest parentheses around assignment used as truth value

2) Смысл
Тоже классика. Компилятор предполагает (и в 99% случаев прав), что вы по ошибке включили в скобки в качестве условия для if/while/for вместо условного выражения выражение присваивания.

3) Когда бывает
Чаще всего — в if‘ах, когда вместо "==" используется "="

if (length = maxLength)

вместо

if (length == maxLength)

Заминка в том, что это не ошибка, т.к. в скомпилированной программе (если мы проигнорируем предупреждение) выражение присваивания (которое возвращает значение правого аргумента) во всех случаях, кроме тех, когда оно вернет 0, будет преобразовано к true.

Ссылки для дальнейшего изучения
Ошибки построения Microsoft Visual C++
GCC Compiler error messages
GCC Warnings

P.S. Следует отметить, что кроме ошибок стадии компиляции встречаются (гораздо реже) ошибки препроцессора (например, если не найден заголовочный файл <iostram>), ошибки стадии компоновки (можно избежать, если научиться пользоваться средой программирования) и — самый гнусный тип ошибок! — ошибки стадии выполнения. Т.н. runtime error. С ними может справиться только голова программиста, вооруженная отладчиком.

  1. the switch Statement in C++
  2. Fix the Jump to case label Error in the switch Statement in C++

Jump to Case Label in the switch Statement

This article will discuss the use of switch statements in C++. Moreover, it will discuss errors that may arise while using the switch statement, including the Jump to case label error.

the switch Statement in C++

The switch statement evaluates a given Boolean or integer expression and executes the statement(s) associated with the cases based on the evaluation of the given expression. It is the best alternative to the lengthy if-else-if statements as it reduces the code length and enhances clarity.

In C/C++, the following syntax is used for the switch statement to perform the evaluation.

Syntax:

switch(exp) {
  case a:
    // Block of code
    break;
  case b:
    // Block of code
    break;
  default:
    // Block of code
}

The switch statement works in the following way:

  • The expression is evaluated once in the switch statement.
  • The case value is compared to the switch value.
  • After evaluating the switch expression with a case statement, the block of code subsequent to the matched case is executed if the condition is true.
  • The break and default keywords are optional with the switch statement. We’ll discuss these in detail at the end of this tutorial.

Suppose we want to calculate the weekday name from the weekday number.

Example Code:

#include <iostream>
using namespace std;

int main() {
  int weak_day = 3;
  switch (weak_day) {
  case 1:
    cout << "Monday";
    break;
  case 2:
    cout << "Tuesday";
    break;
  case 3:
    cout << "Wednesday";
    break;
  case 4:
    cout << "Thursday";
    break;
  case 5:
    cout << "Friday";
    break;
  case 6:
    cout << "Saturday";
    break;
  case 7:
    cout << "Sunday";
    break;
  default:
    cout << "Invalid input";
  }
}

Output:

the break Keyword

The break keyword is used with a switch statement to skip the remaining cases of the switch body after a given case is met.

In the above example, when the switch statement is evaluated and meets the criteria in case 3, it skips the remaining code block of the switch body due to the break; statement.

the default Keyword

The default keyword is used with the switch statement to execute a specified block of code when none of the cases is met in the given switch statement.

Let’s look at the following example, which demonstrates using the default keyword in the switch statement.

Example Code:

#include <iostream>
using namespace std;

int main(){

int a = 4;
switch (a) {
  case 6:
    cout << "Value of a is 6";
    break;
  case 7:
    cout << "Value of a is 7";
    break;
  default:
    cout << "The number is other than 6 or 7";
}
}

Output:

The number is other than 6 or 7

In this example, we have specified the value of the integer variable as 4, but none of the cases will satisfy the given condition during the execution. Therefore, the default block is executed.

Fix the Jump to case label Error in the switch Statement in C++

A common error that may arise while using the switch statement is a Jump to case label error. The error occurs when a declaration is made within/under some case label.

Let’s look at the following example to understand the issue:

#include <iostream>
using namespace std;

int main() {
  int a = 1;
  switch (a) {
    case 1:
      int i=66;
      cout<<i;
      break;

    case 2:
      cout<<i*3;
      break;
    default:
      cout << "Looking forward to the Weekend";
  }
  return 0;
}

In the above example, when we initialize i=66 in case 1: and execute the code. The code generates an error Jump to case label as the value of i is visible to the other cases.

A case is just a label and therefore doesn’t restrict the scope of the code written next to it. Hence, if case 2 is executed during execution, i will be an uninitialized variable.

So, a strongly typed language like C++ will never allow this to happen. Thus, it generates a compile-time error.

The scope delimiters {} within case 1 can overcome this scope issue and help execute the code without error.

#include <iostream>
using namespace std;

int main() {
  int a = 1;
  switch (a) {
    case 1:{
      int i=66;
      cout<<i;
      break;
    }
    case 2:
      cout<<"value does not exist";
      break;
    default:
      cout << "Looking forward to the Weekend";
  }
  return 0;
}

Я написал программу, которая включает в себя использование операторов switch… Однако при компиляции она показывает:

Ошибка: переход к метке case.

Почему он это делает?

#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 Directoryn";//Welcome Message
    do{
        //do-While Loop Starts
        cout<<"Select :n1.Add New Contactn2.Update Existing Contactn3.Display All Contactsn4.Search for a Contactn5.Delete a  Contactn6.Exit PhoneBooknnn";//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 Namen";
                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 Numbern";
            cin>>phno;
            d[i1].phonenumber=phno;
            cout<<"nEnter the addressn";
            cin>>add;
            d[i1].address=add;
            i1++;
            i++;
            break;//Exit Case 1 to the main menu
        case 2:
            cout<<"nEnter the namen";//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<<"nnSearching.........nn";
            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<<"nn";
                    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 namen";
                            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 numbern";
                            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 addressn";
                            cin>>add;
                            d[j].address=add;
                        }
                    }
                }
            }
            break;
        case 3 : {
            cout<<"ntContents of PhoneBook:nntNamestPhone-NumberstAddresses";
            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;
}

4b9b3361

Ответ 1

Проблема состоит в том, что переменные, объявленные в одном case, все еще видны в следующем case, если не используется явный блок { }, но они не будут инициализированы, потому что код инициализации принадлежит другому case.

В следующем коде, если 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!
}

Обертка корпуса в явном блоке решает проблему:

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

Ответ 2

Заявление о новых переменных в заявлениях о случаях вызывает проблемы. Включение всех операторов case в {} ограничивает область новых объявленных переменных текущим исполняемым случаем, который решает проблему.

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

Ответ 3

Стандарт С++ 11, перепрыгивающий через некоторые инициализации

JohannesD дал объяснение, теперь для стандартов.

Проект стандарта С++ 11 N3337 6.7 «Заявление декларации» гласит:

3 Можно передавать в блок, но не так, чтобы обойти объявления с инициализацией. Программа, которая переходит (87) из точки, в которой переменная с автоматическим хранением находится вне области действия, до точки, в которой она находится в области видимости, плохо сформирована, если переменная не имеет скалярного типа, типа класса с тривиальным конструктором по умолчанию и тривиальным деструктор, cv-квалифицированная версия одного из этих типов или массив одного из предыдущих типов и объявляется без инициализатора (8.5).

87) Переход от условия оператора switch к метке регистра считается скачком в этом отношении.

[ Пример:

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 Приложения я «Общие предупреждения» гласит:

2 Блок с инициализацией объекта, который имеет автоматическую продолжительность хранения, перемещается в

Ответ 4

JohannesD ответ правильный, но я чувствую, что не совсем ясно по аспекту проблемы.

Пример, который он приводит, объявляет и инициализирует переменную i в случае 1, а затем пытается использовать ее в случае 2. Его аргумент заключается в том, что если бы переключение перешло прямо к случаю 2, i бы использовал его без инициализации, и именно поэтому ошибка компиляции. В этот момент можно подумать, что не будет проблем, если переменные, объявленные в одном случае, никогда не будут использоваться в других случаях. Например:

switch(choice) {
    case 1:
        int i = 10; // i is never used outside of this case
        printf("i = %dn", i);
        break;
    case 2:
        int j = 20; // j is never used outside of this case
        printf("j = %dn", j);
        break;
}

Можно ожидать, что эта программа скомпилируется, так как i и j используются только внутри случаев, которые их объявляют. К сожалению, в C++ он не компилируется: как объяснил Ciro Santilli 包子 露 宪 六四 事件 法轮功, мы просто не можем перейти к case 2: так как это пропустит объявление с инициализацией i, и даже если case 2 вообще не использует i, это все еще запрещено в 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 = %dn", i);
            break;
        case 2:
            ;
            int j = 20; // j is never used outside of this case
            printf("j = %dn", j);
            break;
    }
}

Благодаря онлайн-компилятору, например http://rextester.com, вы можете быстро попытаться скомпилировать его как C или C++, используя MSVC, GCC или Clang. Как C всегда работает (только не забудьте установить STDIN!), Как C++ ни один компилятор не примет это.

Понравилась статья? Поделить с друзьями:
  • Java ошибка для minecraft 1
  • Java ошибка no main classes found
  • Java ошибка illegal start of expression
  • Java ошибка failed to download required installation files
  • Java ошибка could not find or load main class