Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как выскочить из блока... Подскажите оператор... 
:(
    Опции темы
np9mi7
  Дата 27.7.2004, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Добрый день...

Такой вопросик:

Для вылета из цикла нужен оператор:
Цитата
break;


Для вылета из функции:
Цитата
return;


А кокой оператор нужен для вылета из блока???
Цитата

{
SomeOperator;
}


ЗАранее благодарен за ответ...


Это сообщение отредактировал(а) arajan - 27.7.2004, 19:16


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
_hunter
Дата 27.7.2004, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



goto smile.gif


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
cardinal
Дата 27.7.2004, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



Код
{
goto label;
}
label:

Ничего другого для такой нужды в голову не приходит (в смысле оператора по типу break и return помоему нет).
Добавлено @ 19:25
_hunter, был на минуту быстрее... adv/133.gif


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
AndyY
Дата 28.7.2004, 00:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 316
Регистрация: 8.5.2004
Где: СПб

Репутация: 2
Всего: 4



можно блок оформить так:

Код

do
{
  somefunc();
  ...
  break;

}while( 0 );


типа цикл который один раз выполняется.
изврат, конечно. я за гоуту.


--------------------
PM MAIL WWW   Вверх
chipset
Дата 28.7.2004, 02:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



А нельзя что нить с исключениями намудрить?
Хотя я за goto..


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Олег М
Дата 28.7.2004, 05:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



Цитата
А кокой оператор нужен для вылета из блока???

Такого оператора нет.
goto вообще никогда не пользуйся!

Для подобных целей я делал цикл типа AndyY, только for(;;)

А вообще пользуйся исключительными ситуациями.

А что за задачу ты решаешь?

PM MAIL ICQ   Вверх
gray_k
Дата 28.7.2004, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1015
Регистрация: 9.1.2003
Где: Москва

Репутация: нет
Всего: 22



Цитата
Такого оператора нет.
goto вообще никогда не пользуйся!

Шаблон мышления. В данном случае GOTO - лучший вариант.


--------------------
С уважением.
Gray.
PM MAIL   Вверх
srd
Дата 28.7.2004, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Как будто
do {
...
break;
...
} while(0);
и
{
...
goto label;
...
}
label:
это не одно и тоже. Лучше подумать надо кодом, может получится избавиться от безусловного перехода, а не придумывать такую забавную маскировку.


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Олег М
Дата 28.7.2004, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



Цитата
Шаблон мышления. В данном случае GOTO - лучший вариант.

Да нет, не шаблон. И вариант тоже далеко не лучший, скорее худший. Я лично ни разу им не пользовался. Разве что в детстве, в бейсике.
Ты уверен, что деструкторы будут вызваны, если выйти из блока по goto?
PM MAIL ICQ   Вверх
chipset
Дата 28.7.2004, 09:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Код

               try { //Измученный блок из которого надо выйти
 
                      if(что нибудь...) throw 1; //Если "что-то" выходим...


}
catch(...)
{
 cout<<endl<<"Наконец то вышли!"<<endl;
 
}

hmmm.gif

Это сообщение отредактировал(а) chipset - 28.7.2004, 09:21


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Hroft
Дата 28.7.2004, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 20.10.2003
Где: Москва

Репутация: нет
Всего: 3



Ну да, это действительно лучший вариант, наверное...
Я вот делаю блоки, когда не хочу, чтобы переменые временные долго жили.
Как раз под решение исключениями вопрос.
PM MAIL ICQ   Вверх
gray_k
Дата 28.7.2004, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1015
Регистрация: 9.1.2003
Где: Москва

Репутация: нет
Всего: 22



Олег М
Вы видимо опытный программист, и поэтому должны знать, что нет абсолютно стандартных и готовых решений, подходящих для всего. Тем более нельзя давать советы начинающим типа "Никогда не исполоьзуй goto". Да, его использование в БОЛЬШИНСТВЕ случаев нежелательно. Но бываю случаи, когда применение GOTO может существенно упростить код и ЧИТАБЕЛЬНОСТЬ программы.
В качастве аргумента приведу статью:


Вадим Сабашный
"Оператор GOTO и преобразование потока управления"

Использованы материалы статей:

E. Dijkstra "Go to statement considered harmful", Communications of the ACM, 1968.
D. Knuth "Structured Programming with Go to statement", 1974
B. Baker "An Algorithm for Structuring Flowgraphs", Journal of the ACM, 1977. Crw
Цитата
Вопрос об использовании или не использовании оператора GOTO обсуждается уже на протяжении многих лет. Этот оператор имеет и своих ярых сторонников, которые говорят, что без него не обойтись, и противников, которые утверждают, что GOTO пережиток прошлого, еще тех времен, когда при программировании активно использовались языки низкого (точнее, более низкого чем сейчас) уровня, и в настоящее время этот оператор не должен использоваться. На мой взгляд, нельзя однозначно решить стоит использовать оператор GOTO или нет в общем случае, но в каждом конкретном случае можно оценить все выгоды, которые дает использование данного оператора и сложности, которыми придется за это заплатить. И только потом решить стоит ли писать "GOTO LABEL".
Почему следует избегать употребления оператора GOTO

При изучении первого языка программирования многие учащиеся начинают пользоваться операторами безусловного перехода, даже если они пишут на языках, в которых можно прекрасно обойтись и без GOTO, например, Pascal. В дальнейшем учащиеся используют оператор GOTO все меньше и меньше, возможно, это происходит под давлением опытного преподавателя или после возникновения сложностей при отладке или модернизации кода.

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

Введем некоторую систему координат на процессе исполнения программы. Представим что наша программа это просто последовательность операторов, тогда наиболее удобно, и в тоже время полно, процесс исполнения адресуется одной осью, в которой каждая метка это просто ссылка на кусок текста программы. После введения процедур этой координатной системы уже недостаточно, требуется еще знать место откуда процедура была вызвана, т.е. стек вызовов. Полученная система координат все еще достаточно проста для понимания, но и полностью адресует уже достаточно мощный язык. Теоретически, в "наш" язык циклы можно было бы и не вводить, т.к. их можно выразить с помощью рекурсии, но мы введем циклы, т.к. они очень часто используются и просты в понимании. В координатной системе в дополнение к стеку возьмем счетчик цикла. При введении в язык оператора GOTO сложно выдумать какую-либо подходящую систему координат, конечно, можно взять за систему - номер оператора, который выполнился с начала запуска программы, но вряд ли такая координатная система будет полезна при отладке или анализе структуры программы.

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

Хотя оператор GOTO сложно вписать в разумную и удобную систему координат, многие программисты продолжают его активно использовать.

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

i:=1;
while i<=m and A[i]<>x do
  i:=i+1;
if i>m then
  m:=i;
  A[i]:=x;
  B[i]:=0;
fi
B[i]:=B[i]+1;



    for i:=1 step 1 until m do
      if A[i]=x then goto found;
    not_found:
    i:=m+1;
    A[i]:=x;
    B[i]:=0;
    found:
    B[i]:=B[i]+1;

Правый пример, на мой взгляд, более точно соответствует человеческим действиям - "повторяем, находим то, что нам нужно, прекращаем повторять", конечно, левый пример делает то же самое, но по записи это не так очевидно. Возможно, именно из-за подобных эффектов ученики и употребляют go to - как оператор наиболее близкий к действиям, описанным человеческим языком. Дональд Кнут провел опыт, который подтверждает эту близость, он случайным образом взял алгоритм, описанный в одной из его книг, и обнаружил, что в текстовой записи алгоритма GOTO встречался пять раз.

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

A[m+1]:=x;
i:=1;
while A[i]<>x do
  i:=i+1;
if i>m then
  m:=i;
  B[i]:=1;
else
  B[i]:=B[i]+1;
fi;



  A[m+1]:=x;
  i:=1;
  go to test;
  loop:
  i:=i+2;
  test:
  if A[i]=x then goto found fi;
  if A[i+1]<>x then go to loop fi;
  i:=i+1;
  found:
  if i>m then
    m:=i;
    B[i]:=1;
  else B[i]:=B[i]+1;
  fi;

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

A[m+1] := x;
I := 1;
while A[I] != x do
  if A[I+1] != x then I := I + 2;
  else I := I + 1;
  fi;
if I > m then
  m := I;
  B[I] := 1;
  B[I] := B[I] + 1;
fi;

...а иногда и нужно!

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

Рассмотри цикл "n + 1/2":

A: S;
  if B then go to Z fi;
  T; go to A;
Z:

Если S пустое, то этот цикл выражается через while, если T пустое - через repeat. В случае непустоты S и T, выразить этот цикл через while или repeat без каких-либо дополнительных ухищрений или дупликации кода нельзя:

repeat S;
  if not B then T fi;
until B;

В этом примере получилось дублирование проверки условия B, что достаточно плохо, если проверка условия большая по размерам или времени исполнения, и очень плохо, если проверка изменяет окружение.

При формальном доказательстве корректности работы программ или анализе алгоритмов при помощи машин Тьюринга или RAM-машин без оператора GOTO не обойтись, так как сами эти машины основаны на использовании этого оператора. В других наиболее часто используемых инструментах анализа алгоритмов - нормальных алгоритмах с оперативной буквой и нормальных алгоритмах Маркова используется понятие очень близкое (если не эквивалентное) оператору безусловного перехода. Вероятно, факт использования GOTO в теоретических исследованиях влечет удобство его применения в программах, использующих алгоритмы, основанные на автоматах, машинах Тьюринга, нормальных алгоритмах или других инструментах теоретических исследований.

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

Как и любой вопрос, обсуждение которого идет уже несколько десятилетий, вопрос об использовании GOTO породил некое компромиссное решение. Замечено, что в большинстве случаев оператор GOTO используется при работе с циклами, поэтому появились такие узконаправленные заменители GOTO, как break, exit, jump out, continue. Эти заменители были приняты как противниками, так и сторонниками оператора GOTO и прочно вошли в современные языки программирования.

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

Оператор GOTO не плох сам по себе, а плох в неподходящем месте. Если использовать GOTO в пределах одного модуля то, возможно, его использование является лучшим выходом, например, при реализации цикла "n + 1/2". Ошибочно считать, что программа станет хорошо читаемой, если все операторы GOTO заменить какими-то другими конструкциями. Программа первоначально должна была создаваться с таким расчетом, что GOTO в ней не понадобится, и код будет удовлетворять требованиям структурного программирования.

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

В статье B. Baker предложен алгоритм, который анализирует поток управления программы и эквивалентным образом приводит его к более хорошо читаемому виду, при этом не производится копирование кода, ввод дополнительных переменных или выделения последовательности действий в процедуру. Данный подход рассмотрен на примере преобразования программ, написанных на языке Fortran, но с небольшими изменениями может быть адаптирован для работы с программами практически на любом языке.

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

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

user posted image

Граф потока управления

При анализе потока управления для каждого узла (оператор исходной программы) в графе потока управления строится множество HEAD и FOLLOW, первый несет в себе смысл заголовка объемлющего оператора, например, параметры цикла, а второй - оператор, следующий на этом же уровне вложенности, например, две последовательные записи в файл.

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

Несводимые программы так и остаются несводимыми, но основной объем кода преобразуется к структурированному виду, что значительно повышает читаемоcть программы.

Кроме упомянутого алгоритма существуют алгоритмы, которые позволяют полностью избавится от использования оператора GOTO, но это достигается за счет копирования кода, введения дополнительных переменных, выделения отдельных кусков кода в процедуры. Но, как уже написано выше, читаемость и хорошая структурируемость программы зависит не только от использования или не использования оператора безусловного перехода, так что по полезности рассмотренный алгоритм, вероятно, не уступает более продвинутым аналогам, а свою цель — улучшение читаемости программ, он выполняет.




--------------------
С уважением.
Gray.
PM MAIL   Вверх
AndyY
Дата 28.7.2004, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 316
Регистрация: 8.5.2004
Где: СПб

Репутация: 2
Всего: 4



chipset
exception, в отличии от goto, далеко не бесплатны.

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

for(;;) крутится бесконечно, а do{}while(0) исполняется один раз - и соответственно больше похож на тот оператор, что просит arajan.



--------------------
PM MAIL WWW   Вверх
Олег М
Дата 28.7.2004, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



AndyY и gray_k, вы наверное правы, просто мне однажды, ещё в институте, посоветовали им не пользоваться, обоснованно посоветовали, я и не пользуюсь, хотя почему - не помню.

А деструкторы, оказывается, всё-таки вызываются - на метке, где бы она ни стояла. Вот так. Я не знал. Кстати это может внести конкретную путаницу в программу.


PM MAIL ICQ   Вверх
Hroft
Дата 28.7.2004, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 20.10.2003
Где: Москва

Репутация: нет
Всего: 3



Любопытная статья. Подводит черту. Насчет обработчика в конце процедуры: есть такая штука как Sentry - просто класс, конструктор которого выполняет инициализацию, а деструктор освобождает че надо. Пишем первой строчкой функции
Sentry guard;
, и все.
AndyY
Цитата

exception, в отличии от goto, далеко не бесплатны.

Не бесплатны. Но, если честно, не сильно дороги. А делать большие блоки редко требуется, по крайней мере мне вообще не требовалось больше 10-20 строк не сильно мудреного кода, и всего несколько раз.

PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0743 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.