Действительно ли возможно выйти для перед временем в C++, если конечное условие достигнуто?

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

select sales_person,sum(today_sales),month_to_date
from
(SELECT a.sales_person,sum(a.sales_total) as today_sales,(select sum(sales_total)
                                         from sales b
                                         where year(b.sales_date)=year(a.sales_date) and month(b.sales_date)=month(a.sales_date)) as month_to_date
from sales as a
where a.sales_date=date(now())) c
group by sales_person,month_to_date
order by sales_person
7
задан tunnuz 6 January 2009 в 13:16
поделиться

15 ответов

Можно использовать return ключевое слово: переместите вложенный цикл в подпрограмму, вызовите подпрограмму для выполнения вложенных циклов и 'возврата' из подпрограммы для выхода из [всех] циклов.

51
ответ дан 6 December 2019 в 04:44
поделиться

Другая причина пересмотра for конструкция полностью - то, что ее обзор предотвращает доступ к управляемым переменным после того, как цикл завершился. Значение (значения) переменной (переменных), видоизменяемой в цикле, может полезный для ряда причин (например, отличать успех от отказа в поиске), который иначе потребовал бы, чтобы дополнительные переменные сохранили ту информацию после выхода объема. Вот небольшой пример, который ищет названную квадратную антенную решетку a для 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
ответ дан 6 December 2019 в 04:44
поделиться

Лучшим способом я видел, включает макросы и 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
ответ дан 6 December 2019 в 04:44
поделиться

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

1
ответ дан 6 December 2019 в 04:44
поделиться

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

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

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

Редактирование - Измененный goto для Окончания, а не Внешний однако я не думаю, что отрицательный представитель выравнивается по ширине. Этот ответ уступает самому простому дорогу, чтобы сделать это.

1
ответ дан 6 December 2019 в 04:44
поделиться

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

  1. бросьте.... помещает эти два цикла в "попытке {}" и затем "ловят" "бросок" на условии.

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

  3. Goto не является злым, это - люди использования, помещает его также.... Можно использовать "goto", это может быть самый четкий код, особенно когда ошибки из-за неправильного обращения. Я не использовал один за 20 лет.

Tony

1
ответ дан 6 December 2019 в 04:44
поделиться

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

Ваша другая опция состоит в том, чтобы сделать что-то вроде этого

int i;
int j = 0;
for (i = 0; i < maxi && !(i==4 && j==3); ++i)
    for (j = 0; j < maxj && !(i==4 && j==3); ++j)
4
ответ дан 6 December 2019 в 04:44
поделиться

Чтение кода не должно быть похожим на чтение детективной книги (который всегда должен вычисляться)...

пример:

Java:

iterate_rows:
for (int i = 0; i < maxi; ++i)
{       
    for (int j = 0; j < maxj; ++j)
    {
        if (i == 4 < maxi && j == 3 < maxj) 
            break iterate_rows;
        else
            continue iterate_rows;
    }   
}

Вы не должны выяснять, какое повреждение iterate_rows делают, Вы просто читаете его.

C++:

//iterate_rows:
for (int i = 0; i < maxi; ++i)
{
    for (int j = 0; j < maxj; ++j)
    {
        if (i == 4 < maxi && j == 3 < maxj) 
            goto break_iterate_rows;
        else
            goto continue_iterate_rows;
    }

continue_iterate_rows:;
}
break_iterate_rows:;

goto break_iterate_rows является просто видимой версией повреждения iterate_rows

При ограничении использования goto и маркировок на этом виде кода только Вы не будете выяснять намерение. Ограничение Вашего использования goto и маркировок на этом виде кода сделает Вас просто прочитать код, не анализируя или понимая это. Вы не будете обвиняться в том, что он злой программист.

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

P.S.

Соедините те маркировки с комментариями (перед циклом), к тому времени, когда Вы читаете мимо тех строк с оператором перехода, Вы уже знаете намерение тех gotos

2
ответ дан 6 December 2019 в 04:44
поделиться

Вы не можете выскочить как это в C/C++:

for (...)
{
  for (...)
  {
    // from here...
  }
}
// ...to here

без использования goto. Вам нужна конструкция как:

for (...)
{
  bool
    exit = false;

  for (...)
  {
    if (do_exit)
    {
      exit = true; // or set outer loop counter to end value
      break;
    }
  }
  if (exit)
  {
    break;
  }
}

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

Очевидный способ должен сделать внутренний цикл функцией:

bool F ()
{
  if inner loop terminates, return false else return true
}

void G ()
{
  for (...)
  {
    if (!F ())
    {
      break;
    }
  }
}
6
ответ дан 6 December 2019 в 04:44
поделиться
bool done = false;

for (int i = 0; i < maxi && !done; ++i)
    for (int j = 0; j < maxj && !done; ++j)
        if (i == 4 && i < maxi && j == 3 && j < maxj )
             done = true;
        else {
        }

Или Вы могли просто goto. Или нет :-)

6
ответ дан 6 December 2019 в 04:44
поделиться

Вы не можете выпрыгнуть из двух циклов с инструкцией по одиночному разрыву, но Вы могли использовать goto для спрыгивания с внутреннего цикла прямо снаружи.

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

8
ответ дан 6 December 2019 в 04:44
поделиться

Позвольте мне сказать это так решительно (но вежливо ;-) как я могу: for конструкция в подобном языку C не о подсчете.

Проверяемое выражение, которое определяет, продолжить ли, может быть чем-либо, что относится к цели цикла; выражение обновления не должно быть то, " добавьте тот к счетчику".

for (int i = 0, j = 0; i < maxi && j < maxj && i != 4 && j != 3;) {
    if (j < maxj) {
        ++j;
    } else {
        j = 0;
        ++i;
    }
}

был бы один (довольно произвольный) способ переписать.

Дело в том, что при установлении некоторого условия точка взаимодействия, обычно возможно записать цикл (использующий также while или for) способом это указывает продолжать/завершать условие более явно.

(Если Вы могли бы отправить описание того, что на самом деле происходит, оно было бы, вероятно, для записи чего-то, что не выглядит столь же произвольным как вышеупомянутое.)

13
ответ дан 6 December 2019 в 04:44
поделиться

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

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

bool exit_loops = false;
for (int a = 0; a < A && !exit_loops; ++a)
{
    for (int b = 0; b < B && !exit_loops; ++b)
    {
        if (some_condition) exit_loops = true;
    }
}

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

Наконец не бойтесь использования goto при этом обстоятельстве, обычно goto's плохо не структурирован, программируя, но в некоторых случаях (как это) они очень полезны.

8
ответ дан 6 December 2019 в 04:44
поделиться

Несмотря на"goto рассмотренные вредные" аргументы, это походит на идеальное место для goto. Это по существу, что Вы делаете в Perl. Серьезно... рассмотрите альтернативы:

Дополнительные переменные состояния


for (int i=0; i<maxi; ++i) {
    bool leaveLoop = false;
    for (int j=0; j<maxj; ++j) {
        if (i == 4 && j == 3) {
            leaveLoop = true;
            break; // leave the inner loop
        }
    }
    if (leaveLoop) {
        break; // leave the outside loop
    }
}

Отпуск исключением


try {
    for (int i=0; i<maxi; ++i) {
        for (int j=0; j<maxj; ++j) {
            if (i == 4 && j == 3) {
                throw leave_loop();
            }
        }
    }
} catch (leave_loop const&) {
}

Сложная логика


int j = 0;
for (int i=0; i<maxi && !(i==4 && j==3); ++i) {
    for (j=0; j<maxj && !(i==4 && j==3); ++j) {
        // inner loop
    }
}

goto


for (int i=0; i<maxi; ++i) {
    for (int j=0; j<maxj; ++j) {
        if (i==4 && j==3) {
            goto leave_loop;
        }
    }
}
leave_loop:

Действительно ли последний менее ясен? Я не полагаю, что это. Это больше хрупко? По моему скромному мнению, другие довольно подвержены ошибкам и хрупки по сравнению с goto версия. Извините, что стоял на мыльнице здесь, но это - что-то, что побеспокоило меня некоторое время ;)

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

47
ответ дан 6 December 2019 в 04:44
поделиться
for (int i = 0; i < maxi; ++i)
{
    int j = 0;
    for (j = 0; j < maxj; ++j)
    {
         if (i == 4 && j == 3) // i < maxi and j < maxj otherwise we would not be here
             break; // exit inner loop
    }
    if (i == 4 && j == 3) // i < maxi and j < maxj otherwise we would not be here
        break; // exit outer loop
}
4
ответ дан 6 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: