Можно ли выйти из «до» в C ++, если достигнуто конечное условие? - PullRequest
7 голосов
/ 06 января 2009

Я хочу знать, возможно ли завершить цикл for в C ++, когда проверяется конечное условие (отличное от правильного числа повторений). Например:

for (int i = 0; i < maxi; ++i)
    for (int j = 0; j < maxj; ++j)
        // But if i == 4 < maxi AND j == 3 < maxj, 
        // then jump out of the two nested loops.

Я знаю, что это возможно в Perl со следующими вызовами LABEL или последними вызовами LABEL и помеченными блоками, возможно ли это сделать в C ++ или мне следует использовать цикл while?

Спасибо.

Ответы [ 15 ]

1 голос
/ 06 января 2009

Лучший способ, который я видел , включает макросы и gotos, но на самом деле это довольно приятно (ссылка на пост начинается с разговора о Perl, но последний абзац или около того представляет макросы). *

Позволяет вам писать код вроде:

named (LOOPS) for (i=1; i<10; i++) {
    for (j=1; j<10; j++) {
        for (j=1; j<10; j++) {
            /* Process data[i][j][k] here */
            if (data[i][j][k] < threshold) break(LOOPS);
        }
    }
}
1 голос
/ 06 января 2009

Другая причина полного пересмотра конструкции for заключается в том, что ее область действия препятствует доступу к контролируемым переменным после завершения цикла. Значение (я) переменной (ей) переменной (ей) в цикле может быть полезно по ряду причин (например, чтобы отличить успех от неудачи в поиске), которые в противном случае потребовали бы дополнительных переменных для сохранения этой информации после выхода из области. Вот небольшой пример, который ищет квадратный массив с именем a для значения target (при условии, что SIZE не равен нулю, в противном случае поиск не требуется!):

int i = 0;
int j = 0;
while (i < SIZE && a[i][j] != target) { // still in array but not at target
    if (SIZE <= ++j) {                  // fallen off the end of a row
        j = 0;
        ++i;
    }
}

В следующем коде можно использовать i < SIZE, чтобы определить, было ли найдено нужное значение.

Еще одним преимуществом вышеперечисленного является гибкость. Предположим, мы теперь проинформированы о том, что значения в строках a являются восходящими, поэтому остаток строки не имеет значения, если встречается значение, большее target. Легко узнать, что именно нужно сделать, и где это сделать. Поскольку эта новая информация позволяет нам отказаться от текущей строки, затрагивается только внутреннее решение, которое становится следующим:

    if (target < a[i][j] || SIZE <= ++j) { // can't be in row or fallen off end
    ...

Я вижу больше новых языков (особенно функционально-ориентированных), отказавшихся от старой конструкции "подсчета" цикла; это, вероятно, хорошо, так как это побуждает нас думать о значении цикла, а не просто считать.

1 голос
/ 06 января 2009

Я всегда старался держаться подальше от goto заявлений (на школу всегда смотрели свысока и по какой-то причине на мою работу). Я бы использовал что-то вроде того, что предложил Daemin.

1 голос
/ 06 января 2009

У меня есть несколько предложений:

  1. throw .... поместите два цикла в "try {}" и затем "поймайте" "throw" в условии.

  2. поместите два цикла в метод и вернитесь к условию.

  3. Goto - это не зло, его используют и люди. Вы можете использовать «goto», это может быть самым понятным кодом, особенно при обработке ошибок. Я не использовал один в 20 лет.

Tony

1 голос
/ 06 января 2009

Вы можете использовать метки, что-то вроде:

Outer:
for(...)
{
    Inner:
    for(...)
    {
    if(condition)
        {
        goto End;
        }
    }
}
End:

В Java вы можете передавать метки, чтобы сломаться, я думаю?

Edit - Изменено goto на End, а не Outer, однако я не думаю, что отрицательный повтор оправдан Этот ответ дает самый простой способ сделать это.

...