Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[98.81.24.230] |
|
Страницы: (12) [1] 2 3 ... 11 12 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Всем прива!
Некоторое время назад эта тема затрагивалась вскользь. ЕМНИП в связи с обсуждением оператора goto. Хотелось бы обсудить, и, скажем так, поставить все точки над ï ... Пусть есть код непростой обработки: for (size_t i1 = 0; i1< IMAX; ++i1) { for (size_t i2 = 0; i2< IMAX; ++i2) { for (size_t i3 = 0; i3< IMAX; ++i3) { for (size_t i4 = 0; i4< IMAX; ++i4) { for (size_t i5 = 0; i5< IMAX; ++i5) { // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда for (size_t i87 = 0; i87< IMAX; ++i87) { // ... } } } } } } Какие варианты, кроме как использовать метки и оператор goto, могут быть для решения данного вопроса? |
Сообщ.
#2
,
|
|
|
А если каждый цикл представить функцией?
Т.е. будет функция NextStep, которая будет в себе заключать счетчики первых 5 циклов. И функция SubFor, которая будет реализовывать цикл i87. Тогда для каждого шага циклов можно будет вызывать функцию NextStep, а после выполнения каких-либо действий запускать SubFor. |
Сообщ.
#3
,
|
|
|
Цитата macomics @ А если каждый цикл представить функцией? Мне кажется, как в той аксиоме "От перемены мест слагаемых - легче не становится". Нужно что-то другое, менее "линейное", как мне представляется. Другой подход к выстраиванию обработки. Но это только на уровне "идеи". Что и как - пока не знаю и не понимаю. Добавлено Цитата macomics @ Т.е. будет функция NextStep, Попробуй выразить кодом. Обсудим. |
Сообщ.
#4
,
|
|
|
см. пост выше.
|
Сообщ.
#5
,
|
|
|
Цитата macomics @ см. пост выше. Пока не вижу "сохранения" и "восстановления". Напиши, плс, какой-то синтетический пример этого. |
Сообщ.
#6
,
|
|
|
Вот же
void SubFor(size_t MAXI, ptrdiff_t ind[]) { for (ptrdiff_t i87 = 0; i87 < MAXI; ++i87) { // ... } } bool NextStep(size_t MAXI, ptrdiff_t i[]) { if (++i[5] >= MAXI) { // for (size_t i5 = 0; i5 < MAXI; ++i5) i[5] = 0; if (++i[4] >= MAXI) { // for (size_t i4 = 0; i4 < MAXI; ++i4) i[4] = 0; if (++i[3] >= MAXI) { // for (size_t i3 = 0; i3 < MAXI; ++i3) i[3] = 0; if (++i[2] >= MAXI) { // for (size_t i2 = 0; i2 < MAXI; ++i2) i[2] = 0; if (++i[1] >= MAXI) // for (size_t i1 = 0; i1 < MAXI; ++i1) return false; } } } } return true; } int main() { ptrdiff_t ind[6]; // счетчики for (ptrdiff_t i = 0; i < 6; ++i) ind[i] = 0; // инициализация первого шага do { // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда SubFor(10, ind); // внутренний цикл } while (NextStep(10, ind)); // следующий шаг 5 внешних циклов } |
Сообщ.
#7
,
|
|
|
Наверное я туплю ... В случае с использованием goto, для восстановления обработки в месте прерывания - мы читаем сохраненные i1,i2,i3,i4,i5 и прыгаем в точку обработки (восстанавливая эти i*). А у тебя как?
|
Сообщ.
#8
,
|
|
|
А у меня они изначально хранятся в массиве из N элементов. NextStep приращивает старший счетчик в массиве и если он превысил MAXI, тогда его обнуляет, увеличивает и проверяет следующий счетчик и т.д. до первого. Как только i1 превысит или станет равным MAXI функция возвращает false и цикл обработки заканчивается. В функцию же SubFor передается этот массив счетчиков для проведения обработки.
При этом все это может быть встроено в любой линейный алгоритм через равное/произвольное число операций, а в конце может стоять цикл do как у меня в примере. Можно обойтись только NextStep если SubFor должен всегда выполняться перед этой функцией. bool NextStep(size_t MAXI, ptrdiff_t i[]) { if (i[0] == 0) for (ptrdiff_t i87 = 0; i87 < MAXI; ++i87) { // ... } if (++i[5] >= MAXI) { // for (size_t i5 = 0; i5 < MAXI; ++i5) i[5] = 0; if (++i[4] >= MAXI) { // for (size_t i4 = 0; i4 < MAXI; ++i4) i[4] = 0; if (++i[3] >= MAXI) { // for (size_t i3 = 0; i3 < MAXI; ++i3) i[3] = 0; if (++i[2] >= MAXI) { // for (size_t i2 = 0; i2 < MAXI; ++i2) i[2] = 0; if (++i[1] >= MAXI) // for (size_t i1 = 0; i1 < MAXI; ++i1) i[0] = 1; } } } } return i[0] == 0; } int main() { ptrdiff_t ind[6]; // счетчики for (ptrdiff_t i = 0; i < 6; ++i) ind[i] = 0; // инициализация первого шага // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда NextStep(10, ind); // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда NextStep(10, ind); // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда NextStep(10, ind); // ─────► нам нужно остановиться тут, запомнить состояние, а потом вернуться сюда while (NextStep(10, ind)); // следующий шаг } |
Сообщ.
#9
,
|
|
|
Честно говоря - я пока не андестенд, сказывается принятый алкоголь.
Завтра попробуем на практических примерах. |
Сообщ.
#10
,
|
|
|
Цитата Majestio @ Какие варианты, кроме как использовать метки и оператор goto, могут быть для решения данного вопроса? Если такое потребовалось, то вероятно где-то проблемы.. Кроме того, вот прямо если так, то 5 циклов не нужно. Достаточно одного с границей в 5*IMAX. Если это просто задача, можно и так: const size_t IMAX=10; int state=0; size_t i1=0,i2=0,i3=0,i4=0,i5=0; for(int eoj=0;eoj==0;) { switch(state) { case 0: // это состояние исключительно с демонстрационными целями. i1=i2=i3=i4=i5=0; state=1; break; case 1: if(++i5 == IMAX) { i5=0; if(++i4 == IMAX) { i4=0; if(++i3 == IMAX) { i3=0; if(++i2 == IMAX) { i2=0; if(++i1 == IMAX) { i1=0; state=2; break; } } } } } { // что-то делаем for (size_t i87 = 0; i87< IMAX; ++i87) { // ещё что-то делаем } } break; case 2: // возможно, если нужно : // eoj=1; // закончили работу. Выход. break; } // делаем что-то совсем другое. Другой автомат состояний. } |
Сообщ.
#11
,
|
|
|
Цитата Majestio @ Мне кажется, как в той аксиоме "От перемены мест слагаемых - легче не становится". Нужно что-то другое, менее "линейное", как мне представляется. Запихни всё, что требуется делать внутри цикла, где "нам надо остановиться тут", в отдельную функцию. А все 5 внешнийх циклов преврати в один, сразу по пяти индексам, хоть так, как выше показано. И всё, сначала ты эти пять индексов проинициализируешь нулями, а после восстановления, собственно, восстановленными. |
Сообщ.
#12
,
|
|
|
Цитата ЫукпШ @ Если это просто задача, можно и так: Ну я ему изначально предложил именно это. Только вместо switch .. case использовал функцию, которая как раз содержит одну из веток этого case. |
Сообщ.
#13
,
|
|
|
Цитата ЫукпШ @ if(++i5 == IMAX) { i5=0; if(++i4 == IMAX) { i4=0; if(++i3 == IMAX) { i3=0; if(++i2 == IMAX) { i2=0; if(++i1 == IMAX) Ещё один, в циклы не умеющий Тут же while очевидный, который и понятнее, и пишется быстрее. Как принцип - сойдёт, в реальности же это эталон, достойный govnokod.ru |
Сообщ.
#14
,
|
|
|
А тут и не должно быть циклов. Эта функция должна сделать один инкремент для этих 5 циклов.
|
Сообщ.
#15
,
|
|
|
Цитата Majestio @ Пусть есть код непростой обработки: Можно еще нахеровертить 87 вложенных циклов и написать "Пусть есть код непростой обработки:... И как тут обойтись без goto"... Да очень просто - если есть вот такая шняга, значит ты ничего кроме циклов и goto не умеешь. Приведи реальный пример когда надо именно 5-6 вложенных циклов и без этого никуда? Это наверное из области теоретической физики или че это? Или для реализации сверхмощной нейронной сети? И то я слабо верю что там ну никак не разбить эти циклы. В описываемом тобой случае с вероятностью 99.9999% - неверный подход к решению задачи. |