Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Стереотипы: goto (https://forum.antichat.xyz/showthread.php?t=165949)

Algol 25.12.2009 00:46

Стереотипы: goto
 
Недавно один мой знакомый был повергнут в шок, увидев в моем коде оператор goto. Попытки объяснить что не все так плохо не были восприняты :)
Нынче в институтах учат, что применение goto - не кошерно, не тру и ваще отстой. Применение goto считается преступлением перед мировой общественностью.
Жаль только, что ВУЗы не учат тому, что каждому овощу - свое блюдо.
Ни в коей мере не преувеличивая важность goto, приведу все же два примера, в которых решение без goto было бы некрасиво и сложнее для восприятия:
C#
Код:

        /// <summary>
        /// Функция проверяет, что во всех матрицах есть хотя бы один нуль
        /// </summary>
        /// <param name="listOfMatrix"></param>
        /// <returns></returns>
        public bool HasZero(List<int[,]> listOfMatrix)
        {
            foreach (int[,] matrix in listOfMatrix)
            {
                for (int i = 0; i < matrix.GetLength(0); i++)
                for (int j = 0; j < matrix.GetLength(1); j++)
                    if(matrix[i, j] == 0)
                        goto nextMatrix;//<-----

                return false;
            nextMatrix: ;
            }

            return true;
        }

C#
Код:

        /// <summary>
        /// Создание tcp-сокета, с несколькими попытками подключения
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public TcpClient Connect(IPEndPoint host)
        {
            TcpClient client = new TcpClient();

            int maxTryCount = 5;
        tryAgain:
            try
            {
                maxTryCount--;
                client.Connect(host);
                return client;
            }
            catch (SocketException)
            {
                if(maxTryCount>0)
                    goto tryAgain;//<-----
                else
                    throw;
            }
        }


Retimiled 25.12.2009 00:59

Код:

          foreach (int[,] matrix in listOfMatrix)
            {
                for (int i = 0,nextMatrix=false; i < matrix.GetLength(0) && !nextMatrix; i++)
                for (int j = 0; j < matrix.GetLength(1) && !nextMatrix; j++)
                    if(matrix[i, j] == 0)
                        nextMatrix=true;//<-----
                return nextMatrix;
            }

:)

desTiny 25.12.2009 01:00

Несмотря на всю мою ненависть к яве, в ней для таких случаев предусмотрены
Код:

outer:
for(int i = 0; ....){
  for(int j = 0; ....){
      if(...) continue outer;
      if(...) break outer;
  }
}

но goto удобен, когда проще написать его, чем переконопачивать весь код

Algol 25.12.2009 01:03

Цитата:

Сообщение от Retimiled
Код:

          foreach (int[,] matrix in listOfMatrix)
            {
                for (int i = 0,nextMatrix=false; i < matrix.GetLength(0) && !nextMatrix; i++)
                for (int j = 0; j < matrix.GetLength(1) && !nextMatrix; j++)
                    if(matrix[i, j] == 0)
                        nextMatrix=true;//<-----

                return nextMatrix;

            }

:)

Эээ.... ну ваще-то этот код не эквивалентен приведенному, и вообще не рабочий. Будьте внимательней )

ЗЫ
Да и кстати даже если бы он был рабочий, он явно менее понятный чем исходный :)

Algol 25.12.2009 01:05

Цитата:

Сообщение от desTiny
Несмотря на всю мою ненависть к яве, в ней для таких случаев предусмотрены
Код:

outer:
for(int i = 0; ....){
  for(int j = 0; ....){
      if(...) continue outer;
      if(...) break outer;
  }
}

но goto удобен, когда проще написать его, чем переконопачивать весь код

Ну от того что goto назвать continue, ведь суть не меняется, не так ли?

Retimiled 25.12.2009 01:06

писал как ответ 8)) и он делает то же самое ! Написать екзешник ? :D

... по поводу смотрибельности мой меньше по кол-ву строк! И уж естественно он рабочий 8)))))))))

desTiny 25.12.2009 01:08

Цитата:

Сообщение от Algol
Ну от того что goto назвать continue, ведь суть не меняется, не так ли?

суть не меняется, просто читабельность и логичность кода - немного повышается )
Конечно же, я не спорю - goto решает! )

Algol 25.12.2009 01:15

Цитата:

Сообщение от Retimiled
писал как ответ 8)) и он делает то же самое ! Написать екзешник ? :D

Пиши :D

Цитата:

Сообщение от Retimiled
... по поводу смотрибельности мой меньше по кол-ву строк!

"Смотрибельность" не измеряется в количестве строк. Если бы это было так, то фильм "Аватар" (ок 4ГБ) был бы гораздо сложнее для восприятия чем докзательство теоремы Ферма (ок 40 КБ), что явно не так :)

Retimiled 25.12.2009 01:16

не буду .... :p я и так знаю что рабочий


... главное не это ... как то разбирая старый fig-forth заметил что goto там вытворяла НЕЧТО.... дело в том что счетчики for лежали на стеке ... и чтоб выйти по goto форту приходилось такой чисткой и анализом заниматься что КАРАУЛ!

Algol 25.12.2009 01:18

Цитата:

Сообщение от Retimiled
не буду .... :p я и так знаю что рабочий

Ну послушай, как код может быть рабочим, если у тебя внутри цикла стоит безусловный return? :D

Fata1ex 25.12.2009 01:18

по-моему, довольно очевидная вещь
было у Криса в трюках

Retimiled 25.12.2009 01:19

он стоит в цикле foreach ... как и у тебя .... присмотрись

Algol 25.12.2009 01:22

Цитата:

Сообщение от Retimiled
он стоит в цикле foreach ... как и у тебя .... присмотрись

Да нет, не как у меня, присмотрись лучше ты :D

Algol 25.12.2009 01:23

Цитата:

Сообщение от Fata1ex
по-моему, довольно очевидная вещь
было у Криса в трюках

Не очень понятное замечание.
Кто такой Крис, и какая именно вещь очевидна ?

Retimiled 25.12.2009 01:25

Код:

          foreach (int[,] matrix in listOfMatrix)
            {
                for (int i = 0,nextMatrix=false; i < matrix.GetLength(0) && !nextMatrix; i++)
                for (int j = 0; j < matrix.GetLength(1) && !nextMatrix; j++)
                    if(matrix[i, j] == 0)
                        nextMatrix=true;//<----- тут циклы заканчиваются
              printf("Этот код не выполнится в циклах for только в foreach 8-Ь");
                return nextMatrix;

            }


Algol 25.12.2009 01:26

Цитата:

Сообщение от Retimiled
... главное не это ... как то разбирая старый fig-forth заметил что goto там вытворяла НЕЧТО.... дело в том что счетчики for лежали на стеке ... и чтоб выйти по goto форту приходилось такой чисткой и анализом заниматься что КАРАУЛ!

К счастью, в C# таких проблем нет :)
В общем случае неуправляемых языков - конечно я согласен, что goto может привести к очень плохим последствиям.

Retimiled 25.12.2009 01:27

ну согласен ... но постоянно в мозгу а КАК ТАМ НА СТЕКЕ 8)))))))))))))

.... стекофобия 8)))

Algol 25.12.2009 01:28

Цитата:

Сообщение от Retimiled
Код:

....

Ты все же напиши экзешник :)
Трассировка нас рассудит :D

Retimiled 25.12.2009 01:40

кстати return - это тот же goto только в фас!

Fata1ex 25.12.2009 01:41

я имел в виду, что для большинства ясно, что иногда goto очень даже полезен
крис касперски. вспомнил его, так как пример уж больно похож :) а вообще хотелось бы побольше подобных заметок со всякими тонкостями

Algol 25.12.2009 01:46

Цитата:

Сообщение от Retimiled
кстати return - это тот же goto только в фас!

Ну не скажи. Во-первых кроме return тут большая компания: continue, break, throw... А во-вторых для этих операторов не требуется метка, точка выхода для них - более очевидна, чем для goto. Поэтому они считаются более-менее "структурными".

ЗЫ
Да и еще yield, как же ж без него, родимого, структурного нашего....

Retimiled 25.12.2009 01:48

:D да goto приближает нас к низкоуровневому программированию ... ведь никто не пытается сказать ничего против джампов в ассемблере

... и поскольку у Си С++ положение аморфное .... то GOTO живет там как засланец мышыных кодов!


давненько было помню как z0mbie в своей теории недектируемости вируса (делал попытки на Goto выстроить матрицу исполнения, которая по его мнению могла завести любую эвристику в ступор) ... делал он именно на GOTO ... :p поэтому GOTO живет и будет жить ...

НО Я ГОВОРЮ НЕ О ВЕЩАХ УПРОЩАЮЩИХ ПОНИМАНИЕ, а наоборот 8)))) , вообще вопрос риторический должен ли антивирус понимать код вируса!

nerezus 25.12.2009 02:03

Цитата:

Код:

        public TcpClient Connect(IPEndPoint host)
        {
            TcpClient client = new TcpClient();

            int maxTryCount = 5;
        tryAgain:
            try
            {
                maxTryCount--;
                client.Connect(host);
                return client;
            }
            catch (SocketException)
            {
                if(maxTryCount>0)
                    goto tryAgain;//<-----
                else
                    throw;
            }
        }


Код:

        public TcpClient Connect(IPEndPoint host)
        {
            TcpClient client = new TcpClient();
            for(int maxTryCount = 5; maxTryCount; maxTryCount--) {
                try
                {
                    client.Connect(host);
                    return client;
                }
                catch (SocketException) {}
            }
            throw;
        }


_nic 25.12.2009 02:05

Я иногда использую goto что бы неплодить ненужных вложенных циклов.

Huster 25.12.2009 02:09

Цитата:

Нынче в институтах учат, что применение goto - не кошерно, не тру и ваще отстой. Применение goto считается преступлением перед мировой общественностью.
Да, и в книгах об этом пишут, а ты не думал почему ? Может быть потому что многолетний опыт подсказывает что и правда лучше отказаться от goto ? Если бы было все так просто, то не создавали б другие циклы ( do..while, for, whlie )
Да, может быть именно в твоей ситуации goto и смотрится лучше, но в других случаях, как правило, это лишь усложняет программу, особенно если ее пишут "неопытные" программисты, которые скачут с goto по программе вдоль и поперек.
Поэтому, используй goto только тогда когда это НЕ ЗАПУТАЕТ код программы. Во :)

Retimiled 25.12.2009 02:11

циклы могут выходить стандартными средствами не делая скачков и не делая ненужных проходов.... просто обычно люди сравнение в for(....;X<Y;....) делают одно а досточно описать флаг выхода и вы выйдите из любого количества циклов без лишних проходов.... for(....,ex=0;X<Y && ex==0;....)
Код:

for(....,ex=0;X<Y && ex==0;....)
  for(....;K<L && ex==0;....)
    for(....;M<N && ex==0;....)
        ....
          for(....;F<G && ex==0;....)
            if(BLABLA==TUTU)
                ex=1;


Algol 25.12.2009 02:17

Цитата:

Сообщение от nerezus
Код:

        public TcpClient Connect(IPEndPoint host)
        {
            TcpClient client = new TcpClient();
            for(int maxTryCount = 5; maxTryCount; maxTryCount--) {
                try
                {
                    client.Connect(host);
                    return client;
                }
                catch (SocketException) {}
            }
            throw;        }


throw чего ?

Ra$cal 25.12.2009 02:38

Retimiled, вообще то глубокой вложенности нужно избегать - с помощью выделения кода в методы\функции, ибо глубоко вложенные циклы нечитабельное говно с любой стороны - что с goto, что с флагами, что с break/continue.

Retimiled 25.12.2009 02:49

2 Ra$cal
да .... если не заботишься об быстродействии и не отсчитываешь такты на PUSHA POPA , то конечно нужно оформлять в виде функций а как ты растащишь вот такой код
Код:

for(....,ex=0;X<Y && ex<10;....)
  for(....;K<L && ex<9;....)
    for(....;M<N && ex<8;....)
        ....
          for(....;F<G && ex<1;....)
            if(BLABLA==TUTU)
                ex=8; //  то есть я могу уйти в рамках цикла на люой уровень вложенности 8))


Kaimi 25.12.2009 02:50

В перле goto как будто медленнее работает, чем, например, redo.

nerezus 25.12.2009 03:08

Цитата:

throw чего ?
А хз ) Синтаксиса не помню уже ) Но там переписать не сложно без goto с меньшими затратами =)
Не дотнетчик я - импровизировал )

Algol 25.12.2009 11:27

Цитата:

Сообщение от nerezus
Но там переписать не сложно без goto с меньшими затратами =)

Ну не знаю, мне например в голову не приходит как там переписать без goto с меньшими затратами :)

Algol 25.12.2009 11:32

Цитата:

Сообщение от Ra$cal
Retimiled, вообще то глубокой вложенности нужно избегать - с помощью выделения кода в методы\функции, ибо глубоко вложенные циклы нечитабельное говно с любой стороны - что с goto, что с флагами, что с break/continue.

В целом да, так и есть. Но опять же есть специфические случаи, когда это очень геморно. В основном из-за того что нужно передавать кучу параметров в такую функцию. Да и семантика такой функции не всегда понятна (К примеру, при перемножении матриц нужно делать три вложенных цикла, если два из них вынести в функцию, то как назвать такую функцию? func1() ? :) ).

Qwazar 25.12.2009 12:39

Я бы вынес проверку одной матрицы на наличие нуля в отдельную функцию и делал бы return true если бы встретился хотя бы один ноль. А общий цикл оформил бы примерно так (псевдокод):

Код:


public boolean checkMatrix(Matrix m) {
 for(List list: m) {
  if(!checkForZeroValue(list))
    return false;
 }
 return true;
}

private boolean checkForZeroValue(List list) {
 for(Item i: list)
    if(встретился_ноль) return true;

 return false;
}

Читабельность имхо выше, чем всякие разные метки искать. Ну а в целом, я иногда использую continue; но никогда не приходилось использовать goto.

Sn@k3 25.12.2009 12:52

Цитата:

Сообщение от Algol
Недавно один мой знакомый был повергнут в шок, увидев в моем коде оператор goto. Попытки объяснить что не все так плохо не были восприняты :)
Нынче в институтах учат, что применение goto - не кошерно, не тру и ваще отстой. Применение goto считается преступлением перед мировой общественностью.
Жаль только, что ВУЗы не учат тому, что каждому овощу - свое блюдо.
Ни в коей мере не преувеличивая важность goto, приведу все же два примера, в которых решение без goto было бы некрасиво и сложнее для восприятия:
C#
Код:

        /// <summary>
        /// Функция проверяет, что во всех матрицах есть хотя бы один нуль
        /// </summary>
        /// <param name="listOfMatrix"></param>
        /// <returns></returns>
        public bool HasZero(List<int[,]> listOfMatrix)
        {
            foreach (int[,] matrix in listOfMatrix)
            {
                for (int i = 0; i < matrix.GetLength(0); i++)
                for (int j = 0; j < matrix.GetLength(1); j++)
                    if(matrix[i, j] == 0)
                        goto nextMatrix;//<-----

                return false;
            nextMatrix: ;
            }

            return true;
        }

C#
Код:

        /// <summary>
        /// Создание tcp-сокета, с несколькими попытками подключения
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public TcpClient Connect(IPEndPoint host)
        {
            TcpClient client = new TcpClient();

            int maxTryCount = 5;
        tryAgain:
            try
            {
                maxTryCount--;
                client.Connect(host);
                return client;
            }
            catch (SocketException)
            {
                if(maxTryCount>0)
                    goto tryAgain;//<-----
                else
                    throw;
            }
        }


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

Qwazar 25.12.2009 12:58

Цитата:

Сообщение от Sn@k3
помню-помню когда-то в школе использовал его) но это была только одна задача) а прошло уже много лет)
п.с. о вкусах не спорят) если тебе так удобнее почемубы и нет) в бою все средства...

В данном случае о вкусах спорят, т.к.:
1) Этот код будет разбирать не только автор
2) Возможно даже через несколько лет.

Algol 25.12.2009 14:36

Цитата:

Сообщение от Qwazar
А общий цикл оформил бы примерно так (псевдокод):

Псевдокод это конечно хоршо и кошерно, но реальные программы пишутся не на псевдокоде.
Я же привожу конкретные примеры, в котором метка - самое простое и наглядное решение.
Цитата:

Сообщение от Qwazar
Читабельность имхо выше, чем всякие разные метки искать. Ну а в целом, я иногда использую continue; но никогда не приходилось использовать goto.

Странно, у меня continue чуть ли не в каждом втором цикле.

Но в целом точка зрения ясна.

Qwazar 25.12.2009 18:03

Цитата:

Сообщение от Algol
Псевдокод это конечно хоршо и кошерно, но реальные программы пишутся не на псевдокоде.
Я же привожу конкретные примеры, в котором метка - самое простое и наглядное решение.

Моё решение более наглядно, не запутаешься во вложенных циклах, и не придётся смотреть по коду, где находится метка, на которую ты скачешь. Да и псевдокод очень даже приближен к реальности :)

.Slip 25.12.2009 18:37

Цитата:

Сообщение от Algol
Недавно один мой знакомый был повергнут в шок, увидев в моем коде оператор goto.

Увидев первый сурс я тоже был повергнут в шок :(

Algol 25.12.2009 23:06

Цитата:

Сообщение от .Slip
Увидев первый сурс я тоже был повергнут в шок :(

Ээ... Ну это понятно, а что-то по обсуждаемой теме есть :confused:


Время: 21:52