Приходилось ли вам использовать goto?
От: zzzale  
Дата: 31.03.06 08:07
Оценка:
Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО).
Интересуют прежде всего языки С++,С#.
Re: Приходилось ли вам использовать goto?
От: Вумудщзук Беларусь  
Дата: 31.03.06 09:13
Оценка:
>Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО).
>Интересуют прежде всего языки С++,С#.
Когда учил с++ — да

в проектах на работе — нет... может, ещё опыта маловато ?
Homo sum et nihil humani a me alienum puto...
Re: Приходилось ли вам использовать goto?
От: Cyberax Марс  
Дата: 31.03.06 09:40
Оценка:
zzzale wrote:
> Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять
> этот оператор (желательно с примером и описанием ПО).
В "Этюдах" как раз недавно был пример.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re: Приходилось ли вам использовать goto?
От: Kemsky  
Дата: 31.03.06 09:56
Оценка:
Здравствуйте, zzzale, Вы писали:

Z>Я имею в виду случаи когда ДЕЙСТВИТЕЛЬНО была необходимость применять этот оператор (желательно с примером и описанием ПО).

Z>Интересуют прежде всего языки С++,С#.

А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится
Re[2]: Приходилось ли вам использовать goto?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 31.03.06 10:01
Оценка:
Здравствуйте, Kemsky, Вы писали:

K>А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится


А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).
Re[3]: Приходилось ли вам использовать goto?
От: Нахлобуч Великобритания https://hglabhq.com
Дата: 31.03.06 10:05
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).


Выйти из двух циклов разом?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Re[4]: Приходилось ли вам использовать goto?
От: Cider Россия  
Дата: 31.03.06 10:33
Оценка: -1
Здравствуйте, Нахлобуч, Вы писали:

Н>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).


Н>Выйти из двух циклов разом?


Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах break на метку). Так же можно эти циклы вынести в отдельную функцию и выходить уже из нее. Можно бросить исключение. Так что вариантов в данном случае много.
Cider
Re[5]: Приходилось ли вам использовать goto?
От: Cyberax Марс  
Дата: 31.03.06 10:37
Оценка:
Cider wrote:
> Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах
> break на метку). Так же можно эти циклы вынести в отдельную функцию и
> выходить уже из нее. Можно бросить исключение. Так что вариантов в
> данном случае много.
Это просто аналоги goto.

Некоторые (не будем показывать пальцами) тут вообще считают, что
break/continue не нужны
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[5]: Приходилось ли вам использовать goto?
От: Кодёнок  
Дата: 31.03.06 10:47
Оценка: +1
Здравствуйте, 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;


Смысл — отредактировать строку с помощью диалога-редактора, но оно должно пройти все правила. Если введено неправильная строка, диалог редактирования должен остаться. Вариантов можно придумать много, вот и давайте выберем наилучший
Re[6]: Приходилось ли вам использовать goto?
От: Cider Россия  
Дата: 31.03.06 10:51
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Cider wrote:

>> Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах
>> break на метку). Так же можно эти циклы вынести в отдельную функцию и
>> выходить уже из нее. Можно бросить исключение. Так что вариантов в
>> данном случае много.

C>Это просто аналоги goto.


Тогда все операции изменения потока управления — это аналог goto
Cider
Re[7]: Приходилось ли вам использовать goto?
От: Cyberax Марс  
Дата: 31.03.06 10:56
Оценка:
Cider wrote:
>> > Неизбежности нет. Например, оператор break (не помню, есть ли в плюсах
>> > break на метку). Так же можно эти циклы вынести в отдельную функцию и
>> > выходить уже из нее. Можно бросить исключение. Так что вариантов в
>> > данном случае много.
> C>Это просто аналоги goto.
> Тогда все операции изменения потока управления — это аналог goto
Примерно так и есть.

Но вот while/for-циклы в отсутствии break/continue отличаются тем, что
имеют пост- и пред- условия.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[6]: Приходилось ли вам использовать goto?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 31.03.06 11:01
Оценка: -2
Здравствуйте, 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;
...
...
Re[6]: Приходилось ли вам использовать goto?
От: Cider Россия  
Дата: 31.03.06 11:05
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>В отдельную функцию — увы, создавать структуру с 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 или выделил бы в отдельный класс.
Cider
Re[6]: Приходилось ли вам использовать goto?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 31.03.06 11:20
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Предлагаю поупражняться:

Кё>
Кё>        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
Re[7]: Приходилось ли вам использовать goto?
От: Кодёнок  
Дата: 31.03.06 11:57
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Извиняюсь за иной язык и за изменение обозначений:

СГ>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, т.е. надо завести вторую переменную для подсчета кол-ва включенных правил. Получается решение, аналогичное введению булевого флага.
Re[3]: Приходилось ли вам использовать goto?
От: Kemsky  
Дата: 31.03.06 12:07
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Kemsky, Вы писали:


K>>А что значит "ДЕЙСТВИТЕЛЬНО"? Я goto применяю довольно часто. Однако если исходить из того, что добавление к коду лишней bool переменной и её проверка — меньшее зло, чем goto, то примера, собственно, привести и не получится


СГ>А Вы, пожалуйста, приведите какой-нибудь (канонический) пример в котором устранение goto с неизбежностью повлечёт введение лишнего булевского флага(ов).


Нет такого примера. Для избавления от goto можно также использовать дублирование кода (или помещение этого самого дублирующегося кода в отдельную функцию), continue и break с циклами (смысл которых лишь в том, чтобы не использовать goto), switch, throw. Мощь этих средств столь велика, что всегда можно обойтись и без goto, и без булевского флага.
Впрочем, если угодно, канонический пример, где я обычно использую goto:

{
if( <усл1> )
<действ1>
else if( <усл2> )
<действ2>
else goto exit;
<действ3>
exit:;
}
Re[7]: Приходилось ли вам использовать goto?
От: Кодёнок  
Дата: 31.03.06 12:07
Оценка:
Здравствуйте, Cider, Вы писали:

Кё>>Предлагаю поупражняться:


C> boolean check(String str) {


C>А еще лучше, функциональность проверки внес бы внутрь этого m_settings или выделил бы в отдельный класс.


Вот если бы в плюсах можно быть сделать этот check локальной функцией, это было бы хорошее решение И код бы стал читабельнее.

А так приходится на уровень выше, туда, где эта вспомогательная функция вообще никому не нужна Первая проблема, это то, что ей придётся дать конкретное осмысленное имя — в контексте функции редактирования "check" идеально подходит, в контексте интерфейса класса — конфликтует с уже имеющейся или непонятно что означает. Вторая проблема в том, что унести её в private — значит, сильно удалить от основной, в public она не нужна, а сделать private только её (как в C# — private bool check(){}) в С++ нельзя.
Re[8]: Приходилось ли вам использовать goto?
От: Cider Россия  
Дата: 31.03.06 12:11
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Вот если бы в плюсах можно быть сделать этот check локальной функцией, это было бы хорошее решение И код бы стал читабельнее.


Кё>А так приходится на уровень выше, туда, где эта вспомогательная функция вообще никому не нужна Первая проблема, это то, что ей придётся дать конкретное осмысленное имя — в контексте функции редактирования "check" идеально подходит, в контексте интерфейса класса — конфликтует с уже имеющейся или непонятно что означает. Вторая проблема в том, что унести её в private — значит, сильно удалить от основной, в public она не нужна, а сделать private только её (как в C# — private bool check(){}) в С++ нельзя.


Так кто мешает соорудить небольшой классец, даже внутренний, назвать его ExpressionChecker и засунуть всю эту функциональность в него?
Тогда и имена будут звучать логично, и код будет выглядеть понятно.
Cider
Re[8]: Приходилось ли вам использовать goto?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 31.03.06 12:24
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Вообще интересно выкрутился, только тут ошибка, 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 не производится).

Короче, мне кажется, что ошибки нет...
Re[6]: Приходилось ли вам использовать goto?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 31.03.06 12:26
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Предлагаю поупражняться:

Кё>
Кё>        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;
Кё>


namespace {

struct ExpressionCheckerAndSetter {
  SomeSettings & m_setting;
  ExpressionChecker( SomeSettings & setting ) : m_setting( setting ) {}

  bool operator()( const CString & expr )
  {
    for( size_t i = 0, i_max = m_settings.rules.size(); i != i_max; ++i )
      if( m_settings.rules[ i ].active && !m_settings.rules[ i ].Check( expr ) )
      {
        MessageBox( "Syntax error", 0, 0 );
        return false;
      }
    m_settings.expr = expr;
    return true;
  }
};

}

...
ExpressionCheckerAndSetter checker( m_setting );
CString expr = m_settings;
do {
  if (IDOK != DataEditorDialog(expr).DoModal()) return 0;
} while( !checker( expr ) );


Кстати, если не ошибаюсь, ExpressionCheckerAndSetter можно объявить и внутри самой функции.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.