о брекетах в выписке дела в свитче - PullRequest
2 голосов
/ 12 августа 2011

сегодня, когда я пытался написать код, чтобы просто сложить и вычесть две матрицы 2 * 2, в которых я использовал оператор switch, я получил ошибку регистр инициализации локальной переменной в функции main ()

#include <iostream.h>
#include <conio.h>
#include <string.h>

int 
main()
{
    int mat1[2][2], mat2[2][2], mat3[2][2];

    cout << "Enter the elements in the first matrix";
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            cin >> mat1[i][j];
        }
    }

    cout << "\n\nEnter the elements of the second matrix";

    for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
            cin >> mat2[k][l];
        }
    }

    cout << "\n\nsaved......";

    int choice;
    cout << "\n\n\nFor adding these two matrices,press 1";
    cout << "\nFor subtracting these two matrices,press 2";
    cin >> choice;

    switch (choice) {
    case 1:

        cout << "The addition of the two matrices will yield";
        for (int a = 0; a <= 1; a++) {
            for (int b = 0; b <= 1; b++) {
                mat3[a][b] = mat1[a][b] + mat2[a][b];
            }
        }
        break;

    case 2:
        cout << "The subtraction of the two matrices will yield";
        for (int c = 0; c <= 1; c++) {
            for (int d = 0; d <= 1; d++) {
                mat3[c][d] = mat1[c][d] - mat2[c][d];
            }
        }
        break;
    }
    getch();
    return 0;
}

Я также обнаружил, что могу избавиться от этой ошибки, поместив код (ы) в скобки, СЕЙЧАС,

  1. Моя путаницао error ...
  2. и требованиях скобок в case ....

(я знаю, что я не использовал новые соглашения о кодировании, например<iostream>, пространство имен std и т. Д. И т. Д., Как я написал это в компиляторе turbo c ++, так что ответ на конкретный вопрос смиренно запрашивается)

Ответы [ 3 ]

17 голосов
/ 12 августа 2011

Оператор switch - это просто набор меток и goto, выполняемый компилятором в зависимости от значения вещи в тесте switch.

Когда у вас есть локальная переменная в функции, вы можете использовать ее после объявления этой переменной. Например:

int a;
// can use a now

Однако в операторе switch, если у вас есть локальная переменная:

case a:
    int a;
    break;
case b:
    // we can use a here because these cases are just labels used in a goto
    // i.e. the cases do *not* create a new scope

Таким образом, когда у вас есть переменная в case, переменная существует в case s под ней, но переменная не будет существовать, потому что код, который ее инициализировал, был пропущен оператором case. Мне трудно объяснить, может быть, кто-то другой сможет сделать лучше.

Скобки решают эту проблему, потому что они делают переменную локальной, чтобы она не существовала в последующих case s. Он создается только в том случае, если введен этот конкретный case, и если вы забудете break и элемент управления перейдет к следующему case, окончание } завершит область действия и приведет к уничтожению переменной, поэтому она не будет доступны из следующего case, и инициализация не может быть пропущена.

Так что просто помните, что все case разделяют область действия. Это может помочь вам понять это.

5 голосов
/ 12 августа 2011

После повторного отступа в коде и изменения нескольких вещей, чтобы он компилировался в моей системе, g ++ компилирует его без предупреждений.

Мое лучшее предположение заключается в том, что он как-то связан со старыми правилами для области видимости объекта, объявленного в цикле for (раньше он работал до конца включающей области; в современном C ++ он ограничен самим циклом ), но я не совсем уверен.

Чтобы помочь нам понять это, пожалуйста, сделайте отступ в коде правильно и покажите нам точное сообщение об ошибке, включая номер строки. Если в сообщении об ошибке указано «строка 42: ...», добавьте комментарий в свой источник, например // this is line 42.

РЕДАКТИРОВАТЬ: Да, я думаю, что это проблема. В современном C ++ ваш код в порядке, потому что переменные цикла ограничены самими циклами. Очевидно, Turbo реализует очень старую версию языка, поэтому ваша переменная a, например, видна до самого конца оператора switch. Заключение каждой петли for в фигурные скобки должно исключать предупреждение:

{
    for (int a = 0; a <= 1; a++) {
        for (int b = 0; b <= 1; b++) {
            mat3[a][b] = mat1[a][b] + mat2[a][b];
        }
    }
}

EDIT2: Или еще лучше, прекратите использовать Turbo C ++ и получите современный компилятор.

EDIT3: И причина, по которой компилятор предупреждает об этом, заключается в том, что даже если кажется, что i всегда инициализируется перед использованием, вы можете в принципе обратиться к i в разделе case 2:, минуя инициализацию. (Опять же, это относится только к старым правилам.)

Более понятный способ обойти это, вероятно, заключить каждую секцию case в фигурные скобки:

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

(или, опять же, получите современный компилятор, если у вас нет действительно веской причины придерживаться Turbo C ++).

1 голос
/ 12 августа 2011
Блок

A case сам по себе не является новой областью действия. Любая переменная, которую вы объявляете внутри одной, видна для остальной части оператора switch. Но в других case блоках он неинициализирован. Добавляя фигурные скобки, вы создаете новую область видимости, чтобы другие блоки не могли ее видеть.

Например:

switch (choice)
{
case 0:
    int a = 42;
    break;


case 1:
    std::cout << a << std::endl; // 'a' is uninitialized here
    break;
}


switch (choice)
{
case 0:
    {
        int a = 42;
        break;
    }


case 1:
    std::cout << a << std::endl; // error -- 'a' is not declared here
    break;
}

Я не вижу подобной ситуации в опубликованном вами коде, но именно это и означает сообщение об ошибке.

...