Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО).
Интересуют прежде всего языки С++,С#.
>Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО). >Интересуют прежде всего языки С++,С#.
Когда учил с++ — да
в проектах на работе — нет... может, ещё опыта маловато ?
zzzale wrote: > Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять > этот оператор (желательно с примером и описанием ПО).
В "Этюдах" как раз недавно был пример.
Здравствуйте, zzzale, Вы писали:
Z>Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО). Z>Интересуют прежде всего языки С++,С#.
А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится
Здравствуйте, Kemsky, Вы писали:
K>А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится
А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Здравствуйте, Сергей Губанов, Вы писали:
СГ>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Выйти из двух циклов разом?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, Сергей Губанов, Вы писали:
СГ>>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Н>Выйти из двух циклов разом?
Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах break на метку). Так же можно эти циклы вынести в отдельную функцию и выходить уже из нее. Можно бросить исключение. Так что вариантов в данном случае много.
Cider wrote: > Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах > break на метку). Так же можно эти циклы вынести в отдельную функцию и > выходить уже из нее. Можно бросить исключение. Так что вариантов в > данном случае много.
Это просто аналоги goto.
Некоторые (не будем показывать пальцами) тут вообще считают, что
break/continue не нужны
Здравствуйте, Cider, Вы писали:
СГ>>>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Н>>Выйти из двух циклов разом?
C>Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах break на метку). Так же можно эти циклы вынести в отдельную функцию и выходить уже из нее. Можно бросить исключение. Так что вариантов в данном случае много.
В отдельную функцию — увы, создавать структуру с 10 переменными и копировать её туда-сюда, или передавать по ссылке их все. В С++ как назло нет ни локальных функций, ни замыканий, чтобы в этом помочь.
Исключение — это ИСКЛЮЧЕНИЕ. Не надо их использовать для обычных ситуаций.
Предлагаю поупражняться:
CString expr = m_settings.expr;
while (1)
{
if (IDOK != DataEditorDialog(expr).DoModal()) return 0;
for (size_t i = 0; i < m_settings.rules.size(); ++i)
{
if (m_settings.rules[i].active && !m_settings.rules[i].Check(expr))
{
MessageBox("Syntax error", 0, 0);
goto the_goto;
}
}
break;
the_goto:;
}
m_settings.expr = expr;
Смысл — отредактировать строку с помощью диалога-редактора, но оно должно пройти все правила. Если введено неправильная строка, диалог редактирования должен остаться. Вариантов можно придумать много, вот и давайте выберем наилучший
Здравствуйте, Cyberax, Вы писали:
C>Cider wrote: >> Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах >> break на метку). Так же можно эти циклы вынести в отдельную функцию и >> выходить уже из нее. Можно бросить исключение. Так что вариантов в >> данном случае много.
C>Это просто аналоги goto.
Тогда все операции изменения потока управления — это аналог goto
Cider wrote: >> > Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах >> > break на метку). Так же можно эти циклы вынести в отдельную функцию и >> > выходить уже из нее. Можно бросить исключение. Так что вариантов в >> > данном случае много. > C>Это просто аналоги goto. > Тогда все операции изменения потока управления — это аналог goto
Примерно так и есть.
Но вот while/for-циклы в отсутствии break/continue отличаются тем, что
имеют пост- и пред- условия.
Здравствуйте, Cyberax, Вы писали:
C>Некоторые (не будем показывать пальцами) тут вообще считают, что C>break/continue не нужны
Continue — не нужны вообще, а break не должны быть внутри WHILE-DO-END и REPEAT-UNTIL циклах по определению этих циклов (иначе эти циклы в принципе нельзя будет называть WHILE-DO-END и REPEAT-UNTIL циклами). В языке Oberon кроме WHILE-DO-END и REPEAT-UNTIL циклов есть безусловный цикл LOOP-END, вот внутри него break есть (только называется не break, а EXIT). Кстати, с помощью этого EXIT частично решается вопрос выхода из нескольких вложенных циклов.
...
...
LOOP
...
...
WHILE a DO
...
...
REPEAT
...
...
FOR i := 0 TO N DO
...
...
IF b THEN EXIT END; (* EXIT - это выход из цикла LOOP *)
...
...
IF c THEN RETURN END; (* просто выход из процедуры *)
...
...
END;
...
...
UNTIL d;
...
...
END;
...
...
END;
...
...
Здравствуйте, Кодёнок, Вы писали:
Кё>В отдельную функцию — увы, создавать структуру с 10 переменными и копировать её туда-сюда, или передавать по ссылке их все. В С++ как назло нет ни локальных функций, ни замыканий, чтобы в этом помочь.
А чем плохо передать ссылку на структуру? Ну, жираф большой, ему видней.
Кё>Исключение — это ИСКЛЮЧЕНИЕ. Не надо их использовать для обычных ситуаций.
А никто и не говорит, что ситуация обычная.
Кё>Предлагаю поупражняться:
В плюсах не силен, потому напишу на псевдо-коде (сильно пахнущем явой ).
...
do {
str = MyMegaDialog.doModal();
} while (!check(str));
...
boolean check(String str) {
// судя по имени, m_settings - это поле, поэтому передавать не нужно
for (size_t i = 0; i < m_settings.rules.size(); ++i)
{
if (m_settings.rules[i].active && !m_settings.rules[i].Check(str))
{
MessageBox("Syntax error", 0, 0);
return false;
}
}
m_settings.expr = str;
return true;
}
А еще лучше, функциональность проверки внес бы внутрь этого m_settings или выделил бы в отдельный класс.
Здравствуйте, Кодёнок, Вы писали:
Кё>Предлагаю поупражняться: Кё>
Кё> CString expr = m_settings.expr;
Кё> while (1)
Кё> {
Кё> if (IDOK != DataEditorDialog(expr).DoModal()) return 0;
Кё> for (size_t i = 0; i < m_settings.rules.size(); ++i)
Кё> {
Кё> if (m_settings.rules[i].active && !m_settings.rules[i].Check(expr))
Кё> {
Кё> MessageBox("Syntax error", 0, 0);
Кё> goto the_goto;
Кё> }
Кё> }
Кё> break;
Кё>the_goto:;
Кё> }
Кё> m_settings.expr = expr;
Кё>
Извиняюсь за иной язык и за изменение обозначений:
LOOP
IF DialogShowModal(expr) # ok THEN RETURN 0 END;
i := 0;
WHILE (i < size) & ~(rules[i].active & ~rules[i].Check(expr)) DO INC(i) END;
IF i = size THEN EXIT END; (* EXIT - это в Oberon инструкция выхода из цикла LOOP *)
ShowErrorBox("Ошибка в правиле номер i = ", i, 0, 0)
END
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Извиняюсь за иной язык и за изменение обозначений: СГ>LOOP СГ> IF DialogShowModal(expr) # ok THEN RETURN 0 END; СГ> i := 0; СГ> WHILE (i < size) & ~(rules[i].active & ~rules[i].Check(expr)) DO INC(i) END; СГ> IF i = size THEN EXIT END; (* EXIT — это в Oberon инструкция выхода из цикла LOOP *) СГ> ShowErrorBox("Ошибка в правиле номер i = ", i, 0, 0) СГ>END
Вообще интересно выкрутился, только тут ошибка, i = size неверно, надо i = numberOfActiveRules, т.е. надо завести вторую переменную для подсчета кол-ва включенных правил. Получается решение, аналогичное введению булевого флага.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, Kemsky, Вы писали:
K>>А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится
СГ>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Нет такого примера. Для избавления от goto можно также использовать дублирование кода (или помещение этого самого дублирующегося кода в отдельную функцию), continue и break с циклами (смысл которых лишь в том, чтобы не использовать goto), switch, throw. Мощь этих средств столь велика, что всегда можно обойтись и без goto, и без булевского флага.
Впрочем, если угодно, канонический пример, где я обычно использую goto:
Здравствуйте, Cider, Вы писали:
Кё>>Предлагаю поупражняться:
C> boolean check(String str) {
C>А еще лучше, функциональность проверки внес бы внутрь этого m_settings или выделил бы в отдельный класс.
Вот если бы в плюсах можно быть сделать этот check локальной функцией, это было бы хорошее решение И код бы стал читабельнее.
А так приходится на уровень выше, туда, где эта вспомогательная функция вообще никому не нужна Первая проблема, это то, что ей придётся дать конкретное осмысленное имя — в контексте функции редактирования "check" идеально подходит, в контексте интерфейса класса — конфликтует с уже имеющейся или непонятно что означает. Вторая проблема в том, что унести её в private — значит, сильно удалить от основной, в public она не нужна, а сделать private только её (как в C# — private bool check(){}) в С++ нельзя.
Здравствуйте, Кодёнок, Вы писали:
Кё>Вот если бы в плюсах можно быть сделать этот check локальной функцией, это было бы хорошее решение И код бы стал читабельнее.
Кё>А так приходится на уровень выше, туда, где эта вспомогательная функция вообще никому не нужна Первая проблема, это то, что ей придётся дать конкретное осмысленное имя — в контексте функции редактирования "check" идеально подходит, в контексте интерфейса класса — конфликтует с уже имеющейся или непонятно что означает. Вторая проблема в том, что унести её в private — значит, сильно удалить от основной, в public она не нужна, а сделать private только её (как в C# — private bool check(){}) в С++ нельзя.
Так кто мешает соорудить небольшой классец, даже внутренний, назвать его ExpressionChecker и засунуть всю эту функциональность в него?
Тогда и имена будут звучать логично, и код будет выглядеть понятно.
Здравствуйте, Кодёнок, Вы писали:
Кё>Вообще интересно выкрутился, только тут ошибка, i = size неверно, надо i = numberOfActiveRules, т.е. надо завести вторую переменную для подсчета кол-ва включенных правил. Получается решение, аналогичное введению булевого флага.
Правило считается (делается инкремент INC(i)) не зависимо о того активно оно или не активно:
i := 0;
WHILE (i < LEN(rules)) & ~(rules[i].active & ~rules[i].Check(expr)) DO INC(i) END;
IF i = LEN(rules) THEN EXIT END;
просто если оно не активно, то Check(expr) — не производится (потому что инструкция "a & b" выполняется слева направо и если её результат становится уже известным (т.е. если a = FALSE), то вычисление b не производится).