Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Прерывание внешнего - помеченного цикла


Автор: korob2001 30.11.2010, 17:40
Всем привет!
Столкнулся с такой проблемой.
У меня есть два цикла один из них вложенный. Внутри вложенного цикла через switch проверяется некоторое условие, при наступлении одного из условий в switch определяется необходим ли дальнейши сбор информации, т.е. в одном из case переключателя находится проверка условия через if. Врочем наверное будет всё гораздо понятнее, если посмотреть на код.
Код

do { // Внешний цикл - Начало
    do { // Внутренний цикл - Начало
        switch (.....) {
            case 0:
                // Собираем информацию
                break;
            case 1:
                // Собираем информацию
                break;
            case 2:
                // Проверяем нужно ли продолжать сбор информации
                if (.....) {
                    // Продолжаем сбор
                } else {
                    // Сбор информации необходимо прервать, т.е. необходимо досрочно прервать внутренний цикл с помощью break
                    // или же через continue перейти на следующую итерацию внешнего цикла
                    break INNER:
                }
                break;
            case 3:
                // Собираем информацию
                break;
        }
    } while (....);  // Внутренний цикл - Конец
} while (.....); // Внешний цикл - Конец

Собственно из коментариев понятно, что в блоке else необходимо сделать либо прерывание внутреннего цикла, либо досрочно перейти к следующей итерации внешнего цикла. С прерыванием внутреннего цикла не возникло бы проблем, если заменить переключатель switch на условную конструкцию if ... else if ... else if ... else, так как в моём случае break прерывает не цикл, do .. while, а переключатель switch. Логически здесь подходит именно switch. Я хотел сказать, что не нужно предлагать заменить switch на if ... else if ... else if ... else.
Я знаю что нужно, но не понял как это делается в С#. В Java я бы пометил внутренний цикл, после чего прервал бы его по метке, в C# с этим возникли проблемы. :((((((

Вот, как бы это выглядело на Java:
Код

do { // Внешний цикл - Начало
    INNER: do { // Внутренний цикл - Начало
        switch (.....) {
            case 0:
                // Собираем информацию
                break;
            case 1:
                // Собираем информацию
                break;
            case 2:
                // Проверяем нужно ли продолжать сбор информации
                if (.....) {
                    // Продолжаем сбор
                } else {
                    // Сбор информации необходимо прервать, т.е. необходимо досрочно прервать внутренний цикл с помощью break
                    // или же через continue перейти на следующую итерацию внешнего цикла
                    break INNER;
                }
                break;
            case 3:
                // Собираем информацию
                break;
        }
    } while (....);  // Внутренний цикл - Конец
} while (.....); // Внешний цикл - Конец

Так же можно было бы добавить и метку к внешнему циклу например OUTER, после чего при наступлении условия перейти к следующей итерации с помощью continue OUTER, предварительно ункрементировав переменную внешнего цикла. Вобщем мне нужно добиться идентичного результата, но только в C#. Нашёл в Google, что это нужно делать с помощью goto, но пока не разобрался, каким образом goto может прервать цикл. Попутно продолжу поиски.

Автор: jonie 30.11.2010, 18:23
пример для goto:
Код

int length = 10;
            for (int i = 0; i < length; i++)
            {
            nextLoop:
                for (int j = 0; j < length; j++)
                {
                    goto nextLoop;
                }
            }


а вообще наверно стоит обернуть в функию и делать return

Автор: i2m 30.11.2010, 18:26
Если я вас правильно понял, то наверное так.

Код

do { // Внешний цикл - Начало
    do { // Внутренний цикл - Начало
        switch (.....) {
            case 0:
                // Собираем информацию
                break;
            case 1:
                // Собираем информацию
                break;
            case 2:
                // Проверяем нужно ли продолжать сбор информации
                if (.....) {
                    // Продолжаем сбор
                } else {
                    // Сбор информации необходимо прервать, т.е. необходимо досрочно прервать внутренний цикл с помощью break
                    // или же через continue перейти на следующую итерацию внешнего цикла
                    goto EXIT:
                }
                break;
            case 3:
                // Собираем информацию
                break;
        }
    } while (....);  // Внутренний цикл - Конец
EXIT: // Вышли из внутреннего цикла, или поставить куда точно нужно прыгнуть, можно выше объявления, например перед do
} while (.....); // Внешний цикл - Конец


PS согласен с jonie, вообще goto зло, если возможно сделать без него, то нужно делать.

Автор: Экскалупатор 30.11.2010, 21:14
не уверен что до конца понял что требуется, но мне кажется очевидным было бы ввести переменную bool. сразу делать ее true, а когда надо выйти из цикла делать ее false. в условии цикла проверять ее.
Код

[color=red]bool flag;[/color]
do { // Внешний цикл - Начало
[color=red]flag = true;[/color]
    do { // Внутренний цикл - Начало
        switch (.....) {
            case 0:
                // Собираем информацию
                break;
            case 1:
                // Собираем информацию
                break;
            case 2:
                // Проверяем нужно ли продолжать сбор информации
                if (.....) {
                    // Продолжаем сбор
                } else {
[color=red]flag = false;//когда нужно что бы эта итерация была последней[/color]
                    // Сбор информации необходимо прервать, т.е. необходимо досрочно прервать внутренний цикл с помощью break
                    // или же через continue перейти на следующую итерацию внешнего цикла
                    break INNER:
                }
                break;
            case 3:
                // Собираем информацию
                break;
        }
    } while ([color=red](какое то условие цикла)&&(flag)[/color]);  // Внутренний цикл - Конец
} while (.....); // Внешний цикл - Конец


Добавлено через 1 минуту и 19 секунд
что то теги цвета не срабатывают, но думаю что мысль понятна...

Автор: korob2001 1.12.2010, 11:24
Большое спасибо, всем. Использовал прерывание с меткой которое предложил i2m.

boolean флаг в данном контексте лишняя переменная + лишняя проверка на каждой итерации. Собственно метки для того и нужны.

Цитата(i2m @  30.11.2010,  15:26 Найти цитируемый пост)
PS согласен с jonie, вообще goto зло, если возможно сделать без него, то нужно делать.

Не думаю, что с помощью этого goto получится сделать скачёк в любую точку программы. Злом goto считается именно из-за этого.
Насколько я понял, он вообще в C# применяется для прерывания внешних циклов и скачков по конструции switch.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)