1. Pascal / Говнокод #5609

    +92

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    I:=1;
        while I<=High(Sockets) do
         begin
          if FD_IsSet(Sockets[I],FDSet) then
           if Recv(Sockets[I],…)<=0 then
            begin
             // Связь разорвана, надо закрыть сокет
             // и удалить его из массива
             CloseSocket(Sockets[I]);
             for J:=I to High(Sockets)-1 do
              Sockets[J]:=Sockets[J+1];
             Dec(I);
             SetLength(Sockets,Length(Sockets)-1)
            end
           else
            begin
             // Получены данные от клиента, надо ответить
             Send(Sockets[I],…)
            end;
          Inc(I)
         end;

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

    Запостил: TarasB, 09 Февраля 2011

    Комментарии (51) RSS

    • Источник:

      http://91.210.216.1/Books/Программирование/Delphi/Использование сокетов в Delphi. Часть первая -стандартные сокеты.htm
      Ответить
      • > 91.210.216.1
        а там есть глава про DNS?
        Ответить
        • Я не знаю. Я решил к своей игрухе (стрелялка с ботами) прикрутить сетевой режим, а так как по сеть я не знаю нихрена, то решил почитать эту статью. Статья вроде нормальная, всё подробно так написано, но этот кусок кода вместе с пояснением сделал меня делать FFFFFFFFFFFFFFFUUUUUUUUUUU
          Ответить
          • ну, там есть про модель OSI, чему макак обязательно надо обучать перед допуском к сети
            Ответить
    • это типа пул?
      ну, не вижу необходимости жонглировать массивом. Тупо занулляем, а новый вставляем в свободное место. Хаха, в дельфях нет стандартной функции типа splice?
      тогда пользуйтесь такими структурами данных, как списки. Тогда удаление элемента сведется к стиранию его в порошок и забывчивости о нем соседей.
      Ответить
      • Ну со списками надо заморачиваться, массив проще.
        Просто зачем после каждого удаления сдвигать хвост массива, делая время работы квадратным? Почему нельзя удалять и одновременно сдвигать по одному?
        Ответить
        • как "по одному"?
          Ответить
          • Я имею в виду такое:
            j := 0;
            for i := 0 to Length(A) - 1 do
              if Good(a[i]) then begin
                a[j] := a[i];
                inc(j);
              end else Finalize(a[i]);
            SetLength(a, j);
            Ответить
            • вызов процедуры на одной строке с зарезервированными словами, фу
              Ответить
              • Ради одного простого оператора делать перенос на новую строку... Зачем?
                Я вообще иногда пишу
                with Engine do for i := 0 to Length(Sockets) - 1 do if Good(a[i]) then with Sockets[i] do begin...
                Ответить
                • зачем вообще пробелы жать, клавиатуру только изнашивать...
                  Ответить
                  • Нет, без пробелов код становится плохо читаем, это некрасиво.
                    Ответить
                • за with в принципе надо бить розгами, за вложенный with - сразу на кол.
                  Ответить
                  • Крестобляди ненавидят with, считая его костылём и придумывая всякие отмазки, типа он засоряет пространство имён, вырывает что-то там из контекста и так далее. А разгадка одна - крестобляди завидуют паскалистам, что у них есть такой оператор, крестобляди испытывают жопаболь от того, что они не могут так красиво создать анонимный объект и сделать с ним что угодно:
                    with TButton.Create do begin
                       Parent := Form1;
                       OnClick := smth;
                       // etc...
                    end;

                    или
                    with TBitmap.Create do begin
                      // делаем что-нибудь...
                      Free;
                    end;

                    Конечно же, крестоблядь скажет, что это говнокод или что это паскалокод, но единственная причина, по которой она это говорит - В С++ НЕТУ WITH!!!
                    Ответить
                    • with(TBitmap())
                      {
                        // делаем что-нибудь...
                      };
                      Ответить
                    • А крестобляди это кто? я 8 лет на Делфях работаю, и WITH - ГОВНО за которое я бью своих программеров.

                      А знаете почему? Код хуево читается ну да и хуй с ним, чукча не читатель.
                      Самое хуевое, что отладить такой код невозможно! Нету объекта у которого смотреть свойства
                      Ответить
                      • > WITH ГОВНО
                        1980 coding style?
                        Ответить
                        • вы так говорите, как будто это что-то плохое </trollmode>
                          Ответить
                      • Отладить такой код невозможно не потому, что with плохой, а потому, что отладчик тупой.

                        За крестоблядь извини, это ложное срабатывание детектора по ненависти к with.
                        Ответить
                        • да, извини тоже. раньше with использовали активно, но потом приняли решение в новом коде его не использовать, в основном из-за отладчика. Могли бы эмбаркадеровцы сделать в отладчике переменную с именем with
                          Ответить
                          • Поэтому все претензии к отладчику (и его авторам), а не оператору.
                            Ответить
                    • Вас не только за with ебать надо, а за то что блять .Free всегда должен быть в секции finally. Всегда!
                      with TBitmap.Create do
                      try
                      ....
                      finally
                        Free;
                      end;
                      Ответить
                      • А если исключение произойдёт в конструкторе?
                        Ответить
                        • Тогда деструктор вызовется автоматически, учите матчасть
                          Ответить
                          • Вот блин, а так хотелось про известную крестопроблему поговорить.
                            Ответить
                            • >хотелось про известную крестопроблему поговорить.
                              Ну и что-за проблема?
                              Ответить
                              • В С++ деструктор не автовызывается, если в конструкторе произошло исключениэ.
                                Ответить
                                • http://itommyalice.blogspot.com/2008/02/c.html
                                  Ответить
                                • Вообще никаких проблем с деструкторами, если сгенерировать исключение в конструкторе.
                                  Ответить
                    • Какой сочный butthurt мы наблюдаем и поныне. Чего нет в делфаях, что вы так кипите злостью? Или, может, сишник занял ваше место, и вы теперь пишете на делфаях за еду?
                      Ответить
            • ну или так
              хотя "обрезать" массив не обязательно, не надо фрагментировать память
              Ответить
              • SetLength(Goy, Length(Goy) - 1)
                Ответить
              • Ну я в играх всё важное статическими массивами делаю, храня в отдельной переменной полезную длину.
                Хотя дельфийскому менеджеру памяти можно доверять.
                Ответить
                • помнится в борланде вообще не было динамических массивов, поэтому в школьных\студенческих работах приходилось обьявлять массивы с размерностью "побольше". например, работа с матрицами. Обычно это матрицы с малой размерностью, но обьявляли с размерностью 100 на 100 - просто что бы заявить, что программа работает с матрицами до 100х100
                  Ответить
                  • Ну в ТП7 я делал примерно так: объявлял указатель на массив от 0 до 65534 div sizeof(integer);
                    И выделял ему память через GetMem(a, size) (памяти выделялось ровно столько, сколько надо, а не 64К).
                    Матрицу я задавал как динмасив динмассивов.
                    Ответить
                    • Легкий способ испортить кучу записью за границей массива в паскале\дельфи.
                      Ответить
                      • В Дельфи так делать не надо. А в Паскале действительно менеджер памяти странный: Dispose(pinteger) и Dispose(pointer) работают по разному, например.
                        Ответить
                  • Признайтесь, вы приложили руку к движку Oracle? Он тоже на старте хавает полгига-гиг оперативы просто "шоб было"
                    Ответить
        • >>Ну со списками надо заморачиваться, массив проще.

          sockList: TList;
          .....
          for i :=sockList.Count - 1 downto 0 do
            if Recv(sockList.Items[i]...)<=0 then
            begin
              CloseSocket(sockList.Items[i]);
              sockList.Delete(i);    
            end
            else
              send(sockList.Items[i]...)


          охренеть как сложно
          Ответить

    Добавить комментарий