Ошибка ли это?

Точнее, такие случаи имеют право теоретически существовать. Но чот за все годы я не встречал хорошего применения конкретно из под .Net языка.

Говоря что goto плохой стиль - имеется в виду что его использование приводит к плохому стилю, к примеру в случаях когда можно задуматься и прийти к ещё более хорошему минимуму:


К примеру возьмём C:\PABCWork.NET\Samples\!Tutorial\10_Matrices\Matr1.pas:

  // Есть ли в матрице элемент 5?
  var found5 := False;
  for var i := 1 to m do
  for var j := 1 to n do
    if matr[i,j]=5 then
    begin
      found5 := True;
      goto 1; // Ай как нехорошо! Но это лучший способ выхода из двух вложенных циклов сразу
    end;
1: 
  if found5 then 
    writeln('Элемент 5 найден')
  else writeln('Элемент 5 не найден')  

лучший способ выхода из двух вложенных циклов

// Matrix это ещё и статический массив в том примере
function Has5(matr: Matrix): boolean;
begin
  Result := true;
  for var i := 1 to m do
    for var j := 1 to n do
      if matr[i, j] = 5 then
        exit; // exit это тот же goto, но высокоуровневых и безопасный
  Result := false;
end;
  if Has5(matr) then 
    writeln('Элемент 5 найден')
  else writeln('Элемент 5 не найден')

Кроме всего прочего - выносить такой код в подпрограммы хорошая практика. В данном случае не очень важно, потому что внешний for стоял прямо в главном begin-end..
Но вообще, у поиска элемента в матрице - 3 уровня вложенности (3 отступа: for+for+if). Поэтому если писать их напрямую - они будут сильно раздувать максимальную вложенность текущей подпрограммы, убивая читабельность.

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

Ну и такая же логика работает (или должна работать) других высокоуровневых фич, заменяющих что то низкоуровневое.

4 симпатии

Да, я согласен со всеми замечаниями, но что “лучше” ученики и программисты выберут сами, в зависимости от ситуации. Если сказать честно, то мы ввод “на проверку дурака” делали с помощью goto, при помощи цикла с предусловием wile, при помощи цикла с постусловием repeat - until и даже при помощи цикла с параметром, где на десятом шаге неправильного ввода месяца следует фраза, что “Тебе мальчик нужно в больничку!!!”. Дети, используя многообразие подходов, сами выберут оптимальный и напишут даже лучше, чем преподаватели задумали!!! :slight_smile:

Спасибо! Именно для этого форум и придуман, чтобы делиться опытом

Да, это я показываю многообразие применение операторов ученикам 4-6 классов… :slight_smile:

Кстати про алтернативные варианты…

## var i: integer;
while not TryRead(i, 'Номер месяца:') or not (i in 1..12) do
  'Неправильный ввод!'.Println;
case i of
  1..2, 12: 'Зима'.Print;
  3..5: 'Весна'.Print;
  6..8: 'Лето'.Print;
  9..11: 'Осень'.Print;
  else raise new System.InvalidProgramException;
end;

В таком порядке дубль условия не страшен, потому что случаи не_совпадения этих условий это:

  1. i in 1..12 не пропускает варианты, которые добавили в case: Это должно быть заметно во время минимального тестирования изменений, которое в любом случае надо провести.
  2. В case не проработан варинт, который добавили в допустимые, к примеру i in 1..13: InvalidProgramException это исключение, которое нельзя поймать с помощью try. + тут даже текст в него передавать не надо - оно и так пишет что неправильно.

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

1 симпатия

Считаю, что если Вы только не изучаете историю развития языков программирования, давать десяти - двенадцатилетним детям оператор goto - это плохая идея. Зачем забивать голову тем, от чего уже отошли все современные языки программирования? А вдруг кому-то это покажется проще, чем подумать и написать код без goto и он примет такой стиль на вооружение? Да Вы сами потом замучитесь понимать его коды. Вот был (и есть) в языке Фортран оператор IF(арифметическое_выражение) метка1, метка2, метка3
Фактически, это три GO TO, упакованные в одну строку. Оператор есть, но использовать его не рекомендуется из-за плохой читаемости кода. Несколько таких GO TO - и Вы убьете вечер на понимание алгоритма, зашитого в код из сотни строк.

2 симпатии

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

1 симпатия

В Java есть break с меткой.

Такие случаи реально есть. Например, когда надо выйти из самого внутреннего цикла и потом сделать что-то ещё с полученными несколькими значениями. Лишнюю подпрограмму в этом случае писать неэффективно

1 симпатия

Ну почему же неэффективно? Впрочем, Вы тут поддерживаете Кнута, а я - Дейкстру, вот и вся разница.

1 симпатия

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

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

в общем то @Sun_Serega объяснил примерно то, что я и имел ввиду. пересказывать смысла не имеет. как и писать флаги/дополнительные подпрограммы, тем самым раздувая код и логику ещё сильнее(ИМХО)

1 симпатия
 Институт математики, механики и компьютерных наук ЮФУ, 2005–2021
Администрация форума: В.Н. Брагилевский, С.С. Михалкович, А.М. Пеленицын
Yandex.Metrica