Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Вниз

Ошибка в delphi 7   Найти похожие ветки 

 
Sicilla   (2004-11-17 18:34) [0]

Привет всем. Постваил себе delphi 7 взамен delphi 5. delphi 5 не удалял. И теперь ошибка: при отладке F7 например в переменной i значение 2, а кажет, что там 10 или -5. Хотя считает правильно в целом.


 
begin...end ©   (2004-11-17 18:49) [1]


>  Sicilla   (17.11.04 18:34)

i - это не счётчик цикла случайно?


 
Sicilla   (2004-11-17 19:07) [2]

Да, в основном этот глюк в цикле. И еще не реагирует в циклах на команду Continue. Сволочь:((


 
begin...end ©   (2004-11-17 19:11) [3]


> [2] Sicilla   (17.11.04 19:07)

> Да, в основном этот глюк в цикле.

В случае цикла это нормальное поведение.

> И еще не реагирует в циклах на команду Continue.

Приведи код.


 
Sicilla   (2004-11-17 20:01) [4]

function Tform1.change_record(num: byte): integer;
var
  x,i,j: Integer;
  last, now_1: byte;
begin
    for x := 1 to prov do
        begin
             way_old[x] := prov_info.way[x];
             prov_info.way[x] := 0;
        end;
    for i := 1 to num do
        for x := 1 to prov do
            begin
                 if prov_info.P[x,1] = lstEntries.Items.Strings[i-1] then
                 prov_info.way[i] := x;
            end;
    j := num - ini.kol_prov;
    for x := 1 to num do
        begin
             if (prov_info.way[x] = 0) and (abs(j) > 0) then
                begin
                     prov_info.way[x] := abs(j) + ini.kol_prov;
                     if j > 0 then dec(j);
                     if j < 0 then inc(j);
                     if i = 0 then break;
                end;
        end;
    j := num - ini.kol_prov; // отсюда глюки
    if j > 0 then
       begin
            for i := num downto 1 do
                for x := prov downto 1 do
                    if (way_old[x] = prov_info.way[i]) and (prov_info.way[i] <> 0) and (way_old[x] <> 0) then
                       begin
                            last := way_old[x];
                            now_1 := i;
                            form1.Change(num,last,now_1);
                       end;
       end;
    if j < 0 then
       begin
            for i := 1 to num do
                for x := 1 to prov do
                    if (way_old[x] = prov_info.way[i]) and (prov_info.way[i] <> 0) and (way_old[x] <> 0) then
                       begin
                            last := way_old[x];
                            now_1 := i;
                            form1.Change(num,last,now_1);
                       end;
       end;
    EXE.P[last] := prov_info.p[now_1];
    //
    for i := 1 to prov do
        Prov_info.P[i,1] := "";
    for i := 1 to lstEntries.Items.Count do
        begin
             Prov_info.P[i,1] := lstEntries.Items.Strings[i-1];
             prov_info.way[i] := i
        end;
    ini.kol_prov := lstEntries.Items.Count;
    change_prov(col);
end;

первые пару циклов нормальон кажет, потом начинается фигня.
type
   PRI = record
       P : array[1..prov,1..20] of string[50];
       way: array[1..prov] of byte;
end;
  Prov_info, Exe: PRI;
const prov = 9



 
Anatoly Podgoretsky ©   (2004-11-17 20:09) [5]

Continue в коде не обнаружилось


 
begin...end ©   (2004-11-17 20:12) [6]


> Continue в коде не обнаружилось

Так что глюк уже не в Delphi.


 
Defunct ©   (2004-11-17 21:41) [7]

а зачем Continue вообще нужен?
также как и Goto и Exit его место на помойке IMHO.


 
Gero ©   (2004-11-17 21:46) [8]


> Defunct ©   (17.11.04 21:41)

Тогда уж и Break в придачу.
А можно и циклы вобще выкинуть. Нафиг они нужны?

Имхо


 
Defunct ©   (2004-11-17 22:01) [9]

> Тогда уж и Break в придачу.

Абсолютно точно, и break туда же.
IMHO те кто пользуется
Goto, Break, Continue, Exit
просто не могут нормально реализовать логику программы.

> А можно и циклы вобще выкинуть. Нафиг они нужны?

не извращайте идею.

C помощью 7-ми операторов можно реализовать любую логику:
1. пустой оператор - ;
2. оператор присваивания :=
3. Условный оператор if <> then <оператор> else <оператор>
4. Оператор цикла с пердусловием while <условие> do <оператор>
5. Оператор цикла с постусловием repeat <оператор> until <условие>
6. Оператор цикла с границами for <от> to <до> do <оператор>
7. Составной оператор begin <оператор>.. end.

два доп. оператора case и with можно применять для красоты и наглядности программы.

Continue, Break, Goto, Exit лишь запутывают логику программы и делают программу трудно читаемой.


 
Defunct ©   (2004-11-17 22:02) [10]

[9]
4. LOL суперопечатка.


 
Defunct ©   (2004-11-17 22:14) [11]

2 Gero,

[2] кстати демонстрирует то о чем я говорю.
Код трудночитаем.

и по всей видимости вообще неправильно работает и на D5 и на D7:
for i := 1 to lstEntries.Items.Count do


 
jack128 ©   (2004-11-17 22:28) [12]

Defunct ©   (17.11.04 22:01) [9]
А зачем целых 3(!!!) вида цикла?? Вполне достаточно одного while.


 
jack128 ©   (2004-11-17 22:29) [13]

Defunct ©   (17.11.04 22:14) [11]
Код трудночитаем.

Код трудночитаем из-за нестандартных отступов, ИМХО.


 
Defunct ©   (2004-11-17 22:35) [14]

for x := 1 to num do
       begin
            if (prov_info.way[x] = 0) and (abs(j) > 0) then
               begin
                    prov_info.way[x] := abs(j) + ini.kol_prov;
                    if j > 0 then dec(j);
                    if j < 0 then inc(j);
                    if i = 0 then break;
               end;
       end;

что мешает этот цикл записать так:

   if i<>0 then
   for x := 1 to num do
   if (prov_info.way[x] = 0) and (abs(j) > 0) then
   begin
      prov_info.way[x] := abs(j) + ini.kol_prov;
      if j > 0 then dec(j) else inc(j)
   end;

и не надо никаких Break"ов, и кода меньше.

Хотя возможно автор допустил ошибку именно в строке с Break (вероятно там не if i = 0, а должно было быть if j=0)

но и в этом случае, можно обойтись без Break:

 x := 1;
 Repeat
   if (prov_info.way[x] = 0) and (abs(j) > 0) then
   begin
      prov_info.way[x] := abs(j) + ini.kol_prov;
      if j > 0 then dec(j) else inc(j)
   end;
   inc(x);
 Until (x>=num) or (j=0);

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


 
Palladin ©   (2004-11-17 23:13) [15]


> [14] Defunct ©   (17.11.04 22:35)

Зачем break и continue? Ну уж от вас таких заявлений не ожидал.

Цикл While. Обработка чего угодно, множество условий выхода из цикла. Множество условий для возврата исполнения на начало тела цикла. Выход один. While True Do и использование Break и Continue.


 
Defunct ©   (2004-11-17 23:19) [16]

> А зачем целых 3(!!!) вида цикла??

На все случаи жизни ;>
Вопрос в другом, зачем имея аж 3 оператора цикла применять какие-то Continue, break и т.п?


 
Gero ©   (2004-11-17 23:35) [17]


> IMHO те кто пользуется
> Goto, Break, Continue, Exit
> просто не могут нормально реализовать логику программы.

Неужели в борланде работают именно такие?

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

Простейший пример:

for i := 0 to High(Arr) do
 begin
   if IsError(Arr[i]) then Break;
   <Код>
 end;

Реализуйте это красивее без Break.


 
Gero ©   (2004-11-17 23:37) [18]


> IMHO те кто пользуется
> Goto, Break, Continue, Exit
> просто не могут нормально реализовать логику программы.

Да, кстати, с таким же успехом можно утверждать, что нормально реализовать логику программы не могут те, кто не использует Goto, Break, Continue и Exit.
Если язык позволяет - то почему бы не использовать?


 
Defunct ©   (2004-11-17 23:38) [19]

Palladin ©   (17.11.04 23:13) [15]

Я все же придерживаюсь позиции, что break и cont. абсолютно излишние операторы.

Ведь никто не мешает построить тело цикла так:

procedure Cycle;
var Done : boolean;
begin
 Done := not <множество условий запуска>;
 while not Done do
 begin
   ...
   Done := <множество условий выхода>
 end;
end;

...
Cycle;


что же касается
> While True Do
то настал мой черед удивляться, т.к. IMHO такое вообще нельзя писать.


 
Gero ©   (2004-11-17 23:41) [20]


> Я все же придерживаюсь позиции, что break и cont. абсолютно
> излишние операторы.

Любой оператор цикла не есть необходимостью.
Все можно сделать через if"ы.


 
jack128 ©   (2004-11-17 23:51) [21]

Gero ©   (17.11.04 23:41) [20]
При отсутствии Goto - это необходимость.  как выполнить <оператор> N раз подряд??(N - переменная)


 
Palladin ©   (2004-11-17 23:53) [22]

Можно, еще как можно. Тоже IMHO.

Конструкция с Done не прокатывает в случае с "многозадачным" циклом. Не в том смысле что потоковым или нитевым, а в том что в цикле выполняется задача разбитая на подзадачи. Простейший пример.

A)

DeviceConnect;
Try
While True Do
Begin
 If Not IsDeviceConnected Then Break;
 If Not ReadCommand Then Break;
 ProceedCommand;
 If Not DeviceConnected Then Break;
 If Not WriteCommand Then Break;
End;
Finally
TryDisconnectDevice;
End;

B)
Var
isDone:Boolean;
Begin
DeviceConnect;
Try
While Not isDone Do
Begin
 isDone:=IsDeviceConnected;
 If isDone Then isDone:=ReadCommand;
 If Not isDone Then  ProceedCommand;
 If Not isDone Then isDone:=DeviceConnected;
 If Not isDone Then isDone:=WriteCommand;
End;
Finally
TryDisconnectDevice;
End;

Для моего восприятия A) понятней чем B), да и надежней если придется добавлять код, разбиратся в толпе условий зависящих от установленной ранее булевой переменной. А между прочим это простейший пример, в сложных алгоритмах простой цепочкой условий не обойтись. Так же break сэкономит время выполнения... просто выйдя за цыкл, не проходя толпу условий..


 
Defunct ©   (2004-11-17 23:55) [23]

> for i := 0 to High(Arr) do
> begin
>   if IsError(Arr[i]) then Break;
>   <Код>
> end;

> Реализуйте это красивее без Break.

while NoError(Arr[i]) and (i<High(Arr)) do
Begin
 <Код>
end;

> Если язык позволяет - то почему бы не использовать?
Если так рассуждать, то почему бы не использовать Label? Язык ведь позволяет. Почему бы не использовать Inline? Почему бы всю программу не написать на Asm? Почему бы не писать все операторы  в одну строку? Язык ведь и это все позволяет. Точнее не язык, а компилятор.

Я отвечу на все эти вопросы так:
Потому что НЕ используя все это, программа будет выглядеть куда более удобочиемой, и более доступной для понимания. Углядеть логику (алгоритм) программы будет намного проще, соответственно найти возможную ошибку в коде будет намного проще.


 
Palladin ©   (2004-11-17 23:55) [24]

Упс.. ошибочка... из толпы условий Not нужно поубирать... и из условия While тоже...


 
Defunct ©   (2004-11-18 00:13) [25]

Palladin ©   (17.11.04 23:53) [22]
> Для моего восприятия A) понятней чем B),

Честно сказать я соглашусь с этим (в вашей реализации B действительно оказался менее наглядным чем A), но я ниже предлагаю вариант C), который IMHO не менее прозрачен чем A), и для моего восприятия более понятен.

C)
DeviceConnect;
NoError := True;
Try
 while NoError and DeviceConnected do
 begin
   if ReadCommand then ProceedCommand;
   if Not WriteCommand then NoError := False
 end;  
Finally
 TryDisconnectDevice;
End;


 
Gero ©   (2004-11-18 00:16) [26]


> while NoError(Arr[i]) and (i<High(Arr)) do
> Begin
>  <Код>
> end;

Этот код совсем не соответствует моему.

> Если так рассуждать, то почему бы не использовать Label?
> Язык ведь позволяет. Почему бы не использовать Inline?

Потому что нет необходимости.
Лично у меня нет принципов, будет мне удобнее с Label - сделаю с Label, будет удобнее с Inline - сделаю Inline, так же и Continue, Break, и пр.
Невозможно продумать ведь все ньюансы алгоритма наперед, кроме того, возможно его придется править.
И чтобы не переписывать всю логику работы, порой достаточно просто поставить в нужном месте Break...


 
Palladin ©   (2004-11-18 00:17) [27]

К сожалению если команда не прочиталась нужно немедленно выйти...


 
Defunct ©   (2004-11-18 00:28) [28]

Gero ©   (18.11.04 00:16) [26]
> Потому что нет необходимости.
Я принимаю ваш аргумент.

Тоже самое ("нет необходимости") имеем и в случае с break и continue.

> Невозможно продумать ведь все ньюансы алгоритма наперед, кроме того, возможно его придется править.
А я вам гарантирую, что без Break, Continue, Goto, Exit, Inline и прочее упомянутое можно запросто обойтись, причем всегда. (написано в любой книге по паскалю в разделе операторы).

Palladin ©   (18.11.04 00:17) [27]
Ок, с учетом немедленного выхода:

C)
DeviceConnect;
NoError := True;
Try
while NoError and DeviceConnected do
begin
  if Not ReadCommand then  NoError := False else
  if Not WriteCommand then NoError := False else
  ProceedCommand
end;  
Finally
TryDisconnectDevice;
End;


 
Palladin ©   (2004-11-18 00:34) [29]

Нет, чтение команды, исполнение, запись команды.


 
Игорь Шевченко ©   (2004-11-18 00:40) [30]


> А я вам гарантирую, что без Break, Continue, Goto, Exit,
> Inline и прочее упомянутое можно запросто обойтись, причем
> всегда. (написано в любой книге по паскалю в разделе операторы).


Выкинь книгу на помойку. Искренний совет.
Главное в коде - его удобочитаемость, а с введением дополнительных переменных типа Done она ухудшается.


 
Palladin ©   (2004-11-18 00:42) [31]

Причем сильно, ибо при чтении приходится прослеживать за ее изменением в теле цикла. Иногда это становится сущим адом.


 
Defunct ©   (2004-11-18 00:47) [32]

Palladin ©   (18.11.04 00:34) [29]

Соблюдаю последовательность действий:
D)

DeviceConnect;
NoError := True;
Try
 while NoError and DeviceConnected do
   NoError := ReadCommand and ProceedCommand and WriteCommand
Finally
 TryDisconnectDevice;
End;


Игорь Шевченко ©   (18.11.04 00:40) [30]
> Главное в коде - его удобочитаемость
Об этом и речь.
Done - образный пример.
Неужели пример D) менее нагляден чем A) [22]

> Выкинь книгу на помойку. Искренний совет.
Только за то, что там указывается "полнота" языка паскаль?


 
Palladin ©   (2004-11-18 00:49) [33]


> [32] Defunct ©   (18.11.04 00:47)

:) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.


 
Defunct ©   (2004-11-18 00:52) [34]

> :) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.

;)
Это не проблема:

function ProceedCommand:boolean;
begin
 <код процедуры>;
 Result := True
end;


 
Игорь Шевченко ©   (2004-11-18 00:55) [35]

Defunct ©   (18.11.04 00:47) [32]

Код в D отличается от кода А по логике. То есть, гарантировано работает не так, как оригинал. Хотя и более удобочитаем.


> Только за то, что там указывается "полнота" языка паскаль?


Это не "полнота". Такие советы давались на заре программирования или в эпоху структурного программирования. После этого пришли к выводу, что введение операторов управления (Break, Continue, Exit) улучшает удобочитаемость кода.


 
Игорь Шевченко ©   (2004-11-18 01:02) [36]

Я бы код организовал следующим образом


 ConnectDevice;
 try
   try
     while true do begin
       ReadCommand;
       ProceedCommand;
       WriteCommand;
     end;
   except
     on E: EDeviceNotConnected do
       ....
 finally
   DisconnectDevice;
 end;


А внутри ReadCommand и WriteCommand написал бы
 
 if not DeviceConnected then
   raise EDeviceNotConnected.Create(...);
 .....
 


 
Palladin ©   (2004-11-18 01:04) [37]

Ну конечно это не проблема. Если ProceedCommand процедура. Но если это все таки функция, которая возвращает результат выполнения команды? Но не булевский, а, скажем Integer, который потом нужно еще и анализировать и который влияет на выход из тела цикла при определенных условиях...

Кстати, в A) была допущена ошибка. Устройство ведь нужно проверить на готовность перед записью... но в принципе это ерунда, в and это увязывается. Еще момент: вы уверены, что команды выполнятся именно в том порядке в котором они записаны? Я почему то нет... Кто его знает, этот оптимизатор... Ну это тоже черт с ним... Правда ошибку искать потом неудобно будет...

Повторюсь, это ведь простейший пример. На его, так сказать, "оптимизацию" к нестабильной не гибкой форме, у вас ушло времени гораздо больше чем у меня на вариант A)... Как вы думаете... Это хорошо?


 
Palladin ©   (2004-11-18 01:11) [38]


> [36] Игорь Шевченко ©   (18.11.04 01:02)

Ну что же Вы так... Мечом то сразу по узлу... :)


 
Defunct ©   (2004-11-18 01:15) [39]

Игорь Шевченко ©   (18.11.04 00:55) [35]
> гарантировано работает не так, как оригинал.

Я не знаю как работает оригинал, потому что не знаю сколько там устройств на самом деле. Начало DeiveConnect и секция finally дает понять, что устройство одно, но почему-то присутствует две функции IsDeviceConnected и DeviceConnected. Спрашивается зачем две функции когда устройство одно? Если уж полностью соблюсти логику примера A) получим:

while NoError do
   NoError :=
      IsDeviceConnected and
      ReadCommand and
      ProceedCommand and
      DeviceConnected and
      WriteCommand


И Break по сути не нужен.

> Такие советы давались на заре программирования или в эпоху структурного программирования.

Возможно.

> что введение операторов управления улучшает удобочитаемость кода.

IMHO для кого как.
Вот хоть я в основном и пищу на асм (а там сами понимаете сплошные "goto"), но когда дело касается паскаля стараюсь соблюдать рекомендации прошлого (пишу без использования Break, Cont., goto, exit). И код получается вполне удобочитаемым и главное по коду сразу видно алгоритм, за это мне и нравится паскаль.


 
Palladin ©   (2004-11-18 01:19) [40]

IsDeviceConnected и DeviceConnected - аналогичны... просто во второй раз Is забыл написать...


 
Игорь Шевченко ©   (2004-11-18 01:20) [41]

Palladin ©   (18.11.04 01:11) [38]

Извиняюсь :) Для меня, начиная с какого-то момента, самым главным критерием кода стала его удобочитаемость, до такой степени, чтобы глядя на чужой код, я мог быстро понять, что он делает. Это относится к названиям методов и свойств объектов, к именам переменных и классов, к оформлению кода (отступы, единый стиль) и т.д.
Поскольку обычно на код смотреть приходится, когда он либо работает не так, как задумывалось, либо его приходится изменять под изменившиеся требования окружающей среды, читаемость кода является основным критерием :)


 
Игорь Шевченко ©   (2004-11-18 01:23) [42]


> Если уж полностью соблюсти логику примера A)


> И Break по сути не нужен.


Да нет, на мой взгляд, ты ухудшил код, введя совершенно ненужную конструкцию - сделав из процедуры ProceedCommand функцию, возвращающую всегда одно значение.


 
Defunct ©   (2004-11-18 01:29) [43]

> Но если это все таки функция, которая возвращает результат выполнения команды?

Тогда пришлось бы построить тело цикла подругому.
Скажем, ввести что-то типа ErrorCount.

> вы уверены, что команды выполнятся именно в том порядке в котором они записаны?

Да, можете попробовать с отладчиком. После первого результата False запуск функций прекращается.

> Кто его знает, этот оптимизатор...
Не влияет. И от версии делфи не зависит.

> у вас ушло времени гораздо больше чем у меня на вариант A)... Как вы думаете... Это хорошо?

Нет, думаю, что плохо понял алгоритм A) поэтому долго провозился. Насторожило меня там IsDeviceConnected и DeviceConnected. Ну и про обязательный порядок функций я тоже не знал...

Игорь Шевченко ©   (18.11.04 01:02) [36]
А я бы написал все же
while NoError do ...

Ошибка же может быть не только из-за того что девайс не подключен. Может быть, что код команды в ProceedCommand левый попал.


 
Игорь Шевченко ©   (2004-11-18 01:30) [44]


> Ошибка же может быть не только из-за того что девайс не
> подключен. Может быть, что код команды в ProceedCommand
> левый попал.


Дык, тоже Exception. Ты же сам произнес слово "ошибка".


 
Palladin ©   (2004-11-18 01:33) [45]


> [41] Игорь Шевченко ©   (18.11.04 01:20)

Ну да. Когда в ранней молодости я понаписал пару-тройку продуктов способом кодовой пластмассы, ко мне тоже вскоре откровение пришло... :)

Цикл принципально так и реальзиван как и Ваше решение... Но он - это первое, что пришло мне в голову для примера оправданного использования Break... :)


 
Palladin ©   (2004-11-18 01:36) [46]


> Скажем, ввести что-то типа ErrorCount

А зачем? При добавлении единицы задачи вводить каждый раз новую переменную, которая будет что то значить? И что бы потом мудрить с комбинациями этих переменных? И народить такую лапшу, которой даже Goto позавидует?


 
Ihor Osov'yak ©   (2004-11-18 01:38) [47]

2 [39] Defunct ©   (18.11.04 01:15)

>while NoError do
  NoError :=
     IsDeviceConnected and
     ReadCommand and
     ProceedCommand and
     DeviceConnected and
     WriteCommand
> И Break по сути не нужен.

хм... а как относительно опции "Complete boolean eval"?

зы. код в 22А и 36 намного прозрачнее.


 
Defunct ©   (2004-11-18 01:43) [48]

> Дык, тоже Exception. Ты же сам произнес слово "ошибка".

Черт его знает.
IMHO уровень ошибки не столь высок чтобы в Exception превратиться ;>

> Palladin ©   (18.11.04 01:33) [45]
> Цикл принципально так и реальзиван
> Но он - это первое, что пришло мне в голову для примера оправданного использования Break... :)

Вот видите, зачем же предлагать Break, если сами его не используете. :)


 
Palladin ©   (2004-11-18 01:48) [49]

Я его использую... и очень часто...

Function FindS(Const S:String):Integer;
Var
i:Integer;
Begin
Result:=-1;
For i:=0 to high(a) do
 If a[i]=S Then
  Begin
   Result:=i;
   Break;
  End;
End;

a:array of string;


 
Ihor Osov'yak ©   (2004-11-18 01:49) [50]

относительно break и continue..
Всегда предпочитаю их использовать вместо сложных if в цыклах с ветвлениями. И даже довольно часто вместо многослолойных if (либо вместо генерации исключения с целью прерывания последовательности кода) делаю псевдоцыклы c break, примерно так:

repeat // psewdoloop
  ..
  if что-то1
  then
    break;  
  ...
  if что-то2
  then
    break;  
  ...
 
  Break;
until false;

 
в старом-добролм паскале до появления break в аналогичных ситуациях соотв. псевдоцыклы оформлял как процедуры с exit в соотв. местах.
Впрочем, иногда сейчас также использую аналогичную технику.

Конечно, с точки зрения читабельности желательно делать примерно так -

try
  ..
  if что-то1
  then
    Abort;  
  ...
  if что-то2
  then
    Abort;  
  ...
except
  ..
end;

Но учитывая что обработка исключения немного ресурсоемкая операция, то все же даю предпочтение двум упомянутым выше способам.


 
Defunct ©   (2004-11-18 01:50) [51]

> Palladin ©   (18.11.04 01:36) [46]

Это были мысли в слух. А вы тут уже атомную войну заметили ;)

> Ihor Osov"yak ©   (18.11.04 01:38) [47]
> зы. код в 22А и 36 намного прозрачнее.

А смысл? Разве здесь состязание по красоте кода?
Скажите лучше по сути 22A или 36, что нагляднее?
Imho 36.


 
Ihor Osov'yak ©   (2004-11-18 01:54) [52]

2 [51] Defunct ©   (18.11.04 01:50)

> А смысл? Разве здесь состязание по красоте кода?

Надежный код - всегда красивый.

>Скажите лучше по сути 22A или 36, что нагляднее?

надежнее 36. Но новичку он может быть неочевидным. Я все же дал-бы предпочнетие 36. Тем более, он написан по всем классическим канонам.


 
Defunct ©   (2004-11-18 02:07) [53]

> относительно break и continue..
> Всегда предпочитаю их использовать вместо сложных if в цыклах с ветвлениями.

Кому как, меня, например, от асм"a уже подташнивает, потому и не люблю пользоваться ни break ни exit ни goto.

> Palladin ©   (18.11.04 01:48) [49]
Для таких случаев у меня всегда используется while

a:array of string;

Function FindS(Const S:String):Integer;
Var
 i:Integer;
Begin
 i := 0;
 while (A[i]<>S) and (i<Length(A)) do inc(i);
 if i<Length(A) then Result := i
                else Result := -1
End;


Ihor Osov"yak ©   (18.11.04 01:54) [52]
> Надежный код - всегда красивый.
Золотые слова.


 
Palladin ©   (2004-11-18 02:10) [54]

У меня на одно сравнение меньше :)

И мне понятней. Но это уже ИМХО.


 
Anatoly Podgoretsky ©   (2004-11-18 09:51) [55]

Palladin ©   (18.11.04 00:42) [31]
Равносильно глобальным переменным


 
Sicilla   (2004-11-18 14:39) [56]

Короче мужики! Кто нибудь скажет в чем проблема??? См. вопрос.


 
Amoeba ©   (2004-11-18 15:03) [57]

Странно всё это. Ошибок в коде не видно. Есть, правда, пара шероховатостей.

j := num - ini.kol_prov; // отсюда глюки
Эта строка лишняя, т.к. в предыдущем цикле значения num и ini.kol_prov не изменяются.

...
end;
   if j < 0 then
      begin
....
Это лучше переписать так:
...
end
else if j < 0 then
begin
...

Что же касается существа дела, то просто мистика какая-то.


 
Sicilla   (2004-11-18 15:16) [58]

Вот и я так думаю. Но все-таки видно это глюк в delphi 7. Delphi 5 мне больше нравился. Но от прогресса не уйдешь. А что касается строки j := num - ini.kol_prov, то мне надо было просто узнать знак разности, т.е. что из них больше. А читать всех интересно. Надо бы это все куда-нибудь опубликовать:))) Большое всем спасибо!!!


 
Sicilla   (2004-11-18 15:18) [59]

Спасибо!


 
Amoeba ©   (2004-11-18 15:24) [60]


> что касается строки j := num - ini.kol_prov, то мне надо
> было просто узнать знак разности

А зачем его узнавать еще раз? Ведь и j у тебя не изменялся в предыдущем цикле.

P.S.
от прогресса не уйдешь
Я, например, до сих пор сижу на D5 и не вижу для себя достаточно веских причин переходить на более новые версии.


 
KSergey ©   (2004-11-18 16:08) [61]

2 Defunct

Товарищи втянули вас в обсуждение более сложного случая. Однако вы не ответили на замечание по простейшему коду, приведенному Gero. Позволю себе напомнить:

> [26] Gero ©   (18.11.04 00:16)
>
> > while NoError(Arr[i]) and (i<High(Arr)) do
> > Begin
> >  <Код>
> > end;
>
> Этот код совсем не соответствует моему.

И ведь действительно не соответсвует! Так что делать тут будем? В этом, простейшем случае? Доп. проверку условия вводить? Переставлят местами проверку?


 
begin...end ©   (2004-11-18 16:21) [62]


> [61] KSergey ©   (18.11.04 16:08)

К тому же уважаемый Defunct забыл добавить туда инициализацию и увеличение счётчика (а это влияет на читаемость), т.е.:

i := 0;
while NoError(Arr[i]) and (i<High(Arr)) do
begin
 Inc(i);
 <Код>
end.

Впрочем, этот код (как и оригинальный из [23]) будет, конечно, некорректно работать как в случае {$B-}, так и в случае {$B+}. (Оригинальный код из [23], разумеется, работать вообще не будет.) Кстати сказать, в случае for про подобные директивы можно и вовсе не помнить.

Ну а насчёт удобочитаемости - для меня лично действительно легче понять, что делает такой код:

for i := 0 to High(Arr) do
begin
 if IsError(Arr[i]) then Break;
 <Код>
end;

чем код, приведённый выше.


 
Defunct ©   (2004-11-18 16:41) [63]

Sicilla   (18.11.04 14:39) [56]

Перечитайте [11] и [14] там указаны возможные ошибки в вашем коде.
Особенно обратите внимание на [14], там IMHO возможная причина неверной работы 3-го цикла.



KSergey ©   (18.11.04 16:08) [61]

Это Gero так считает. Я же считаю, что все там соответствует, за исключением условия < должно быть <=. ну и еще инвертирована функция NoError = not IsError. Но это IMHO мелочи. При проектировании программы, я бы строил соответствующие функции.

> Так что делать тут будем?
А что бы вы хотели делать?
Я придерживаюсь позиции без break можно обойтись всегда. Без break логика программы выглядит более читабельно. Хотя бы потому что выход из цикла всегда в одном и том же месте.

Вот пример с exit, это сродни break:

procedure DoSomthing( SomeObject : TSomeClass);
begin
 if SomeObject = nil then Exit;

 with SomeObject do
 begin
   <Код>
 end
end;

procedure DoSomething( SomeObject: TSomeClass);
begin
 if SomeObject <> nil then
 with SomeObject do
 begin
   <Код>
 end
end;


Что, на ваш взгляд, проще для отладки и выглядит логичнее?
Обратите внимание, что если все без исключения процедуры и функции оформлены без операторов управления, это значительно повышает "гибкочитаемость" программы и такую программу проще отлаживать, т.к. всегда известно где "вход", а где "выход" (даже не нужно читать код). Там где много "входов" и много "выходов" там обычно и проблемы.


 
Defunct ©   (2004-11-18 16:48) [64]

begin...end ©   (18.11.04 16:21) [62]

Набирайте высоту коллега. Негоже искать истину в inc.
Лучше поищите истину здесь:
if IsError(Arr[i]) then Break;

на кой черт проверять какую-то ошибку.
смотрите 36.

for i := 0 to High(Arr) do
try
  <Код>
except
  <обработка искл.>  
end;


 
begin...end ©   (2004-11-18 16:58) [65]


> [64] Defunct ©   (18.11.04 16:48)


> Набирайте высоту коллега.

Я Вам не коллега.

> Негоже искать истину в inc.

Что-то я Вас не пойму. В [63] Вы утверждаете, что Ваш код соответствует коду Gero. Я же говорю Вам, что Ваш код не только не соответствует коду Gero, а даже и не работает вовсе (последнее - даже если добавить инициализацию и увеличение счётчика). И он не будет работать даже в том случае, если заменить условие "<" на "<=".

> на кой черт проверять какую-то ошибку.

О какой ошибке Вы говорите? Уж не сделали ли Вы окончательное заключение о деятельности функции IsError по её названию? В таком случае, можно это название изменить.

P.S. Интересна Ваша манера отвечать на чьи-либо сообщения, при этом переворачивая всё с ног на голову.


 
begin...end ©   (2004-11-18 17:20) [66]

> Defunct

Небольшая поправка к [65].

Если считать всякие Inc"и само собой разумеющимися, то Ваш код из [23] работает, но некорректно. А после внесения исправлений, указанных Вами же в [63], т.е. замены "<" на "<=", Ваш код перестаёт работать! Чудеса, не правда ли?


 
Defunct ©   (2004-11-18 17:29) [67]

> Я Вам не коллега.
LOL
"тамбовский волк тебе товарищь" (C)
похвально!

> Я же говорю Вам, что Ваш код не только не соответствует коду Gero, а даже и не работает вовсе

Код Gero тоже не работает, это был абстрактный пример если до вас до сих пор не дошло.

> И он не будет работать даже в том случае, если заменить условие "<" на "<=".

Мне все равно, что вы считаете. Я и так знаю, что абстрактный код не будет работать на практике.

> О какой ошибке Вы говорите? Уж не сделали ли Вы окончательное заключение о деятельности функции IsError по её названию? В таком случае, можно это название изменить.

Измените, если вам полегчает. Тогда и смысл будет другим, тогда на кой черт break?

> P.S. Интересна Ваша манера отвечать на чьи-либо сообщения, при этом переворачивая всё с ног на голову.

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

Мне интересна ваша манера изучения отходов ракетного топлива после того как ракета уже улетела.
PS: А конференция-то была по динамике полета.


 
begin...end ©   (2004-11-18 17:39) [68]


> [67] Defunct ©   (18.11.04 17:29)


> Мне все равно, что вы считаете. Я и так знаю, что абстрактный
> код не будет работать на практике.

Что-то долго до Вас доходит. Видите ли: если сделать на основе Вашего "абстрактного" кода "неабстрактный", то он тоже не будет работать.

Вот пример:

function NoError(Element: Integer): Boolean;
begin
 Result := Element > 0;
end;

var
 I: Byte;
 Arr: array [0..1] of Integer;
begin
 Arr[0] := 1;
 Arr[1] := 5;
 I := 0;
 while NoError(Arr[i]) and (I <= High(Arr)) do
 begin
   Inc(I)
 end
end.

И здесь применение Вашего кода вызывает ошибку. У Вас есть предположения, почему это так происходит, или Вам нужно пояснить?


 
Defunct ©   (2004-11-18 18:05) [69]

begin...end ©   (18.11.04 17:39) [68]
> Ваш код перестаёт работать! Чудеса, не правда ли?

Неужели Вы не понимаете, мне этот код вообще не нужен. И мне даже не интересно работает он или нет. То что я хотел показать (без break можно обойтись всегда), я показал.
Я ни разу в программах на Паскале и Delphi, за последние ~10 лет, не использовал ни break, ни goto, ни exit, а continue считал и считаю верхом алогизма (особенно если крутится вложенный цикл). А тут приходит begin..end и пытается мне открыть какую-то истину, что с break код выглядит лучше. Да как хотите, юзайте ваш break, юзайте inline, юзайте continue, пишите все операторы в одну строку. Все равно мы с вами, как вы намекнули, вместе не работаем и мне не придется лицезреть и править ваш код.

> Что-то долго до Вас доходит.
До меня "дошло" вот что.
1. Вам нечем заняться.
2. Вы хотите порадоваться тем, что приперли меня к стенке знаком равенства.
3. Вы не желаете вникнуть в суть дискуссии, вам ведь всего-то для полного счастья надо найти ошибку в абстрактном примере.


 
Defunct ©   (2004-11-18 18:15) [70]

> begin...end ©
> Видите ли: если сделать на основе Вашего "абстрактного" кода "неабстрактный", то он тоже не будет работать.

Я вас огорчу, вот абстрактный код[23]:

while NoError(Arr[i]) and (i<High(Arr)) do
Begin
<Код>
end;


а вот здесь я из него делаю не абстрактный код [53]:

a:array of string;

Function FindS(Const S:String):Integer;
Var
i:Integer;
Begin
i := 0;
while (A[i]<>S) and (i<Length(A)) do inc(i);
if i<Length(A) then Result := i
               else Result := -1
End;


2 begin...end
Обратите внимание, что неабстрактным и рабочим, я его сделал еще до того как вы сегодня проснулись.


 
Gero ©   (2004-11-18 18:35) [71]


> begin...end ©

> Defunct ©

Да ладно вам по пустякам кашу заваривать.

> Defunct ©   (18.11.04 18:05)

Понимаете, что для того, чтобы сделать код рабочим, понадобилась куча исправлений.
И одну ошибку в коде вы даже не заметили.
Конечно, каждый мог не заметиь, дело не в вас.
Но, после этого всего, дайте ответ на вопрос: где легче допусить ошибку в моём коде или в вашем?


 
begin...end ©   (2004-11-18 18:35) [72]


> [69] Defunct ©   (18.11.04 18:05)


> Неужели Вы не понимаете, мне этот код вообще не нужен.

Я понимаю, что он Вам не нужен. Но я думал, что Вы отвечаете за свои слова. И если Вы приводите пример кода, который НЕ РАБОТАЕТ при условии, что его переделали из "абстрактного" в "неабстрактный", то после выяснения этого печального обстоятельства Вы поймёте свою ошибку и признаете её. Хотя справедливости ради надо сказать, моя надежда на это была весьма слабой.

А теперь я позволю себе показать, как изменяются переменные в коде из [68], сделанном на базе Вашего.

До прохода цикла: I = 0. При вычислении первой части условия повторения цикла происходит обращение к СУЩЕСТВУЮЩЕМУ элементу массива Arr, а именно Arr[0]. Второе условие, т.е. I <= High(Arr), истинно, т.к. 0 <= 1.

После первого прохода цикла: I = 1. См. предыдущий абзац, с заменой числа 0 на число 1.

После второго прохода цикла: I = 2. Происходит обращение к НЕСУЩЕСТВУЮЩЕМУ элементу массива Arr, а именно Arr[2]. Как говорится, комментарии излишни. Истинность или ложность второго условия продолжения цикла уже никого не интересует.

А теперь, - и что самое интересное! - такая ошибка возникла, скорее всего, именно потому, что for был заменён на while.

На всякий случай поясню, как избежать этой ситуации - надо просто поменять местами NoError(Arr[i]) и (I <= High(Arr)), и не забыть отключить опцию Complete Boolean Eval.

И после этого Вы утверждаете, что while лучше, чем for. Может быть, и лучше, но только не для Вас.


 
begin...end ©   (2004-11-18 18:38) [73]


> [70] Defunct ©   (18.11.04 18:15)


> while (A[i]<>S) and (i<Length(A)) do inc(i);

Я прошу прощения - Вы притворяетесь, или действительно не понимаете?

Сделайте доброе дело: опубликуйте где-нибудь список Ваших программ, написанных, вероятно, в том же духе, для того, чтобы ими кто-нибудь случайно не воспользовался. А то - мало ли что, знаете ли.


 
Defunct ©   (2004-11-18 18:51) [74]

> Но, после этого всего, дайте ответ на вопрос: где легче допусить ошибку в моём коде или в вашем?

Ошибку одинаково легко допустить и там и там.
А вот заметить ошибку, IMHO проще там где нет break.

> Да ладно вам по пустякам кашу заваривать.

А разве я завариваю кашу, объективно оцените ситуацию, посмотрите на посты begin...end [72],[73]. Кстати, Gero, это подтверждает первую часть ответа, если даже begin...end замечает ошибки в моем примере, то их действительно просто заметить.


 
begin...end ©   (2004-11-18 18:58) [75]


> [69] Defunct ©   (18.11.04 18:05)


> А тут приходит begin..end и пытается мне открыть какую-то
> истину, что с break код выглядит лучше.

1. Куча программистов использует Break в своей практике. А тут приходит Defunct и пытается открыть какую-то истину, что без Break код выглядит лучше. Не забывая при этом допустить элементарнейшую ошибку.
2. Человек учится работать с CompareMem и пытается сравнить две строки с помощью этой функции. Посетители форума дают ему советы, что сравнить можно и с помощью CompareMem, но только немножко не так. А тут приходит Defunct и говорит: строки можно сравнивать с помощью операции "=".
http://delphimaster.net/view/1-1100710585/
3. Человек спрашивает: "Как удалить файл в корзину?". Посетители форума советуют ему воспользоваться функцией SHFileOperation. А тут приходит Defunct и говорит, что, дескать, Корзина - это приблуда для дураков, а Вам нужно просто удалить файл с помощью DeleteFile. И термин "удалить в Корзину" - он, видите ли, некорректен. (Ветка, к сожалению, уже ушла в архив.)
4. Приходит Defunct и делает утверждение. Посетитель форума указывает ему, что оно неверно. Defunct отвечает, что Вы, дескать, человек твердолобый, и вот не поняли, что утверждение моё обобщать на явления дальше носа Defunct"а, оказывается, нельзя. (Ветка, к сожалению, уже ушла в архив.)


 
Gero ©   (2004-11-18 18:59) [76]


> если даже begin...end замечает ошибки в моем примере, то
> их действительно просто заметить

Их просто заметить потому что код элементарен.
При более сложном коде это будет намного сложнее.

Иногда удобнее while, иногда for, иногда удобнее с Break, иногда без него.
Зачем вбивать себе в голову какие-либо ограничения?


 
Gero ©   (2004-11-18 19:01) [77]


> begin...end ©

Алексей, зачем провоцируешь?
Може хватит?


 
begin...end ©   (2004-11-18 19:05) [78]


> [77] Gero ©   (18.11.04 19:01)

Да вот - видишь ли, надоело уже терпеть.
Неприятно, знаешь ли, когда дураком выставляют.
Особенно, если невнимателен (мягко сказано) на самом деле - не я.
Странно, правда?


 
begin...end ©   (2004-11-18 19:20) [79]


> [74] Defunct ©   (18.11.04 18:51)


> если даже begin...end замечает ошибки в моем примере, то
> их действительно просто заметить

LOL. Их так просто заметить, что их не замечаете даже Вы - автор кода.

Указываешь Вам на ошибки, указываешь... а Вы всё о своём талдычите. ПривОдите свой же "неабстрактный код" в [73] с той же самой "легко замечаемой" ошибкой...

Можете продолжать поливать меня грязью. Но лучше не надо - не позорьтесь.

Засим дискуссию с Вами заканчиваю. Finish.


 
Defunct ©   (2004-11-18 19:30) [80]

begin...end ©   (18.11.04 18:58) [75]
"плохой вечер хорошего дня"

> Неприятно, знаешь ли,
IMHO вы сами себя выставляете.

> Можете продолжать поливать меня грязью. Но лучше не надо - не позорьтесь.

Я вас ничем не поливал, помоему как раз наоборот.

PS: я на вас не обижаюсь. несдержанность это недуг.


Gero ©   (18.11.04 18:59) [76]
> Зачем вбивать себе в голову какие-либо ограничения?
Ограничения - сродни стандарту.
А все стандартное легко запоминается и работа со стандартным сводится к механической работе.

Например, не используя exit, мы вольны для отладки поставить точку останова на предпоследнюю строку процедуры и посмотреть значения переменных перед выходом из процедуры. Если же будет применен exit, то такой вариант отладки уже не пройдет.
Придется отлаживать нестандартно - ставить несколько точек останова на каждый exit.

В общем речь о том, чем меньше ветвлений, прыжков и т.п. тем прозрачнее алгоритм. Goto, Break, Exit, Cont., вносят дополнительные ветвления. А нужны ли нам эти ветвления если без них можно обойтись? Вот собсно об этом я и говорю.


 
Defunct ©   (2004-11-18 19:35) [81]

begin...end ©
> Их так просто заметить, что их не замечаете даже Вы - автор кода.

Ваша цель была найти ошибки, вы их нашли с чем вас и поздравляю.

Моя цель была показать, что break не нужен, и что без break ошибки лучше видны. С чем я тоже успешно справился.


 
Gero ©   (2004-11-18 19:42) [82]


> А все стандартное легко запоминается и работа со стандартным
> сводится к механической работе.

Согласен. Break, Continue и пр. - вполне стандартные операторы.


 
Defunct ©   (2004-11-18 19:49) [83]

Gero ©   (18.11.04 19:42) [82]

Как говорится, остались при своем imho.


 
Defunct ©   (2004-11-18 21:47) [84]

begin...end ©   (18.11.04 18:58) [75]

Могу вам подыграть ;>
А еще я один раз написал в форуме:

(Sender.Handle as TControl).Left := ...

или что-то в этом духе.
Можете добавить в свой аресенал.


 
KSergey ©   (2004-11-19 08:24) [85]

Все же позволю себе написать. Хотя, понятно, вс еостанутся при своих имхах.

[63] Defunct ©   (18.11.04 16:41)
KSergey ©   (18.11.04 16:08) [61]
Это Gero так считает.


Нет, не он один. Я тоже так считаю.

[69] Defunct ©   (18.11.04 18:05)
2. Вы хотите порадоваться тем, что приперли меня к стенке знаком равенства.


Да при чем тут, блин, знак равенства?!! Неужели вы и вправду не видите проблем в своем коде и принципиальное отличие от приведенного с for? НЕ ВЕРЮ!

[70] Defunct ©   (18.11.04 18:15)
> begin...end ©
> Видите ли: если сделать на основе Вашего "абстрактного" кода "неабстрактный", то он тоже не будет работать.

Я вас огорчу, вот абстрактный код[23]:

while NoError(Arr[i]) and (i<High(Arr)) do
Begin
<Код>
end;


Сколько можно повторять, что он НЕ СООТВЕТСВУЕТ коду из [26]. Неужели ткнуть надо в чем именно? Да плевать на Inc и тонкости в операторе сравнения, это понятно что сделаете правильно. В вашем коде - ПРИНЦИПИАЛЬНая ошибка! Вернее не ошибка, а отличие. Ну посмотрите же внимательно, мне бы не хотелось тыкать... Впрочем, begin...end на нее уже указал, хотя я бы начал с другого варианта, ну да не важно. При этом, даже перестановка местами проверок - накладывает на разработчика заботу следить на опцией BoolEval. Зачем??

[28] Defunct ©   (18.11.04 00:28)
А я вам гарантирую, что без Break, Continue, Goto, Exit, Inline и прочее упомянутое можно запросто обойтись, причем всегда.


Да разве же кто-то спорит?

[69] Defunct ©   (18.11.04 18:05)
То что я хотел показать (без break можно обойтись всегда), я показал.


Безусловно, хотя тут вы уже лукавите.

> [69] Defunct ©   (18.11.04 18:05)
> Я ни разу в программах на Паскале и Delphi, за последние
> ~10 лет, не использовал ни break, ни goto, ни exit, а continue
> считал и считаю верхом алогизма (особенно если крутится
> вложенный цикл).

Во, вот тут наконец-то мы слышим правду. Безусловно, это личное дело каждого, но моя позиция противополжна. Хотя, конечно, это религия, тут спорить смысла нет.

И еще по поводу Exit.

Стандартный кусок:

if Проверка_1 then  Выход;
Действия_1;
if Проверка_2 then  Выход;
Действия_2;
if Проверка_3 then  Выход;
Основные действия;


Ну Выход я написал условно, чтобы показать алгоритм. Смысл в том, что в случае выполнения проверок (на ошибки) дальше делать тут нечего. Да, можно вложить кучу if"ов. Но на мой взгляд - это ужас! Можно воспользоваться исключениями, как писали мастера выше. Но зачем изличне расходовать ресурсы?? Ведь очевидно, что Exit - легче, чем обработка исключений.


 
Fay ©   (2004-11-19 09:33) [86]

Все мётлы и веники - на помойку! Туда им дорога!!
Ах, как клёво подметать ломами да лопатами!!!


 
Defunct ©   (2004-11-19 15:35) [87]

> Да при чем тут, блин, знак равенства?!! Неужели вы и вправду не видите проблем в своем коде и принципиальное отличие от приведенного с for?

Я не вижу к чему вы прицепились в той одной строчке, абстрактного примера. см [81]

Зато проблему в for я вижу отчетливо - чтобы прервать цикл надо использоватать, с моей точки зрения левый, оператор break.

> Да разве же кто-то спорит?

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


 
begin...end ©   (2004-11-22 10:59) [88]


> [85] KSergey ©   (19.11.04 08:24)


Сергей, оцените ситуацию объективно.

1. Defunct утверждает (см. [81]), что он успешно доказал: "без break ошибки лучше видны". Как мы видели, в процессе этого доказательства правильный код Gero (с Break, см. [17]) был превращён в неправильный код Defunct (без Break, см. [23]). В [23] НА 3 СТРОЧКИ КОДА ПРИХОДИТСЯ 2 ОШИБКИ. Правда, потом пропорция изменилась: теперь НА 3 СТРОЧКИ КОДА ПРИХОДИТСЯ 1 ОШИБКА. Всё равно - многовато. Таким образом, мы получили, по крайней мере, единичное опровержение утверждения "без break ошибки лучше видны".

2. В [70] Defunct приводит код, и характеризует его: "неабстрактным и рабочим, я его сделал еще до того как вы сегодня проснулись". В то же время очевидно, что ЭТОТ КОД ТОЖЕ НЕ РАБОТАЕТ. А Defunct, видимо, даже не потрудился выполнить его с включённой опцией Range Checking.

А вот теперь скажите, Сергей - стоит ли разговаривать серьёзно с человеком, упорно называющим свой неработающий код "рабочим"? И утверждающим, что он что-то "доказал", когда на самом деле он доказал обратное?


 
KSergey ©   (2004-11-22 13:48) [89]

> Defunct ©   (19.11.04 15:35) [87]
> > Да при чем тут, блин, знак равенства?!! Неужели вы и вправду
> не видите проблем в своем коде и принципиальное отличие
> от приведенного с for?
> Я не вижу к чему вы прицепились в той одной строчке, абстрактного примера. см [81]

Плохо.
Либо см. [72], либо вот еще более простая ситуация: массив имеет нулевую длину. Законно? А тогда как быть с кодом из [70]?? При том, что цикл с for будет работать корректно.
Заметьте, я ни в коей мере покусаюсь на "абстрактность".

> > Да разве же кто-то спорит?
> Тогда будьте добры, укажите вашу цель этого разговора.

Хотелось бы увидеть или аналогичное по празрачности решение без for, либо... ну вы поняли ;)
А то, что в принципе без break обойтись можно - это безусловно, но цель-то наша, как мне видится, не в искуственных ограничениях религиозного толку, а в познании шаблонов прозрачного. лаконичного кода.

PS
а личто я использую goto! ;) один раз правда, но посоветовавшись с одним мужичком услышал от него верную, на мой взгляд, фразу: "если тебе удобнее и код здесь будет более прозрачен - так зачем себя насиловать и городить неестественные решения?"


 
Defunct ©   (2004-11-23 06:00) [90]

KSergey ©   (22.11.04 13:48) [89]
> Либо см. [72], либо вот еще более простая ситуация: массив имеет нулевую длину. Законно?

Понимаете, моей целью не было написать рабочий пример. Моей целью было написать абстрактный пример, который покажет суть того, как именно избавиться от break. Следовательно, меня абсолютно не волнуют ни опции компилятора, ни ситуации когда этот код не будет работать. Потому что я могу привести сколько угодно ситуаций, когда код Gero тоже не будет работать. Например:
Arr : Array[50..67] of TForm;

Вот теперь скажите, законно ли набрасываться на какой-то абстрактный кусочек кода, который просто показывает КАК можно избежать использования break?

> Хотелось бы увидеть или аналогичное по празрачности решение без for, либо...

for i := 0 to High(A) do
begin
 if <ошибка> then break;
 <код>
 if <что-то> then break
end;


Аналогичное по прозрачности:

i := 0;
while (i<High(A)) and (not NeedToBreak) do
if <ошибка> then NeedToBreak := True else
begin
 <код>
 Inc(i);
 if <что-то> then NeedToBreak := True
end;

 

Может вам с первого взгляда покажется, что кода написано больше. Зато логика цикла остается ровной. Условие выхода из цикла записано только в одном месте, и вы не будете гадать почему цикл был покинут или почему при отладке не попали на нужную вам строку.
Теперь попробую с Repeat, здесь помоему еще прозрачнее:

I := 0;
if not <ошибка> then
Repeat
 <Код>
 inc(i);
Until <что-то> and (i<High(A));


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

так что, например у меня, никогда бы не складывалась ситуация описанная Gero. Поскольку я никогда не использовал break, вообще не вижу ситуации когда бы последний был бы востребован.

вот сегодня написал, вполне рабочий код, и без всяких break.
хотя судя по возгласам некоторых, break в таких случаях применять просто необходимо:

 while not ProgressForm.BreakStatus do
 begin
   StepForward;
   <код>
   <BreakStatus зависит от того нажмет ли пользователь на кнопу стоп, либо время в StepForward будет больше заданного>
 end;


И вполне прозрачная логика, не находите?


> а личто я использую goto! ;) один раз правда
Goto - это инструмент других языков (Basic, Asm, fortran). Если вам довелось разок его применить, значит писали либо что-то низкоуровневое (имеется в виду системный уровень), либо наоборот - переходили с одного языка на другой.

begin...end ©   (22.11.04 10:59) [88]
> А вот теперь скажите, Сергей - стоит ли разговаривать серьёзно с человеком, упорно называющим свой неработающий код "рабочим"?

А вы умеете серьезно разговаривать?
Что-то не заметил.


 
KSergey ©   (2004-11-23 08:36) [91]

> Defunct ©   (23.11.04 06:00) [90]
> Вот теперь скажите, законно ли набрасываться на какой-то
> абстрактный кусочек кода, который просто показывает КАК
> можно избежать использования break?

Да, т.к. повторю еще раз: он отличается функционально от оригинала. Не отличающийся я в вашем исполнении так и не увидел, увы... Задача же - показать функционально инедтичный код, а не код, примерно равный по функциональности, но работающий верно в других условиях. Это можно понять, наконец? При этом эти доп. условия по определению дожны быть указаны, т.к. являются неотъемлемой частью шаблона. Пусть и абстрактного.

> Аналогичное по прозрачности:

Нууу.... Я бы так не сказал, хотя решить сие без голосования - наверное не выйдет ;) Впрочем, доверюсь вам.
Хотя, а что же делать в немколько более сложном случае:

for i := Low(A) to High(A) do
begin
if <проблема_1> then break;
<код>
if <проблема_2> then break;
<код>
if <что-то> then break
end;


Обрастать else if"ами? Нет уж, увольте. Хотя это, конечно же, опять дело вкуса, спорить тут, видимо, смысла нет.

> И вполне прозрачная логика, не находите?

Нахожу, только это не в тему совсем.

> Теперь попробую с Repeat, здесь помоему еще прозрачнее:

А постоянно приводить функционально совершенно не идентичный код - это нормально по-вашему???!!


 
begin...end ©   (2004-11-23 09:16) [92]


> [91] KSergey ©   (23.11.04 08:36)


> > Теперь попробую с Repeat, здесь помоему еще прозрачнее:
>
> А постоянно приводить функционально совершенно не идентичный
> код - это нормально по-вашему???!!

Вот-вот... И, к тому же - опять неработающий...

> I := 0;
> if not <ошибка> then
> Repeat
>  <Код>
>  inc(i);
> Until <что-то> and (i<High(A));

Мда... Куда уж прозрачней...


 
KSergey ©   (2004-11-23 09:44) [93]

> [92] begin...end ©   (23.11.04 09:16)
> Вот-вот... И, к тому же - опять неработающий...
> Until <что-то> and (i<High(A));

То, что вы выделили - мелочь, по-моему. Код по структуре принципиально отличается. Пока не буду писать чем.


 
Verg ©   (2004-11-23 09:50) [94]


> [90] Defunct ©   (23.11.04 06:00)
> KSergey ©   (22.11.04 13:48) [89]
> > Либо см. [72], либо вот еще более простая ситуация: массив
> имеет нулевую длину. Законно?
>
> Понимаете, моей целью не было написать рабочий пример. Моей
> целью было написать абстрактный пример, который покажет
> суть того, как именно избавиться от break. Следовательно,
> меня абсолютно не волнуют ни опции компилятора, ни ситуации
> когда этот код не будет работать.


Это что, типа прозрачность в ущерб работоспособности?

А зачем тогда if not <ошибка> then?
Без этого if-а было бы еще прозрачнее.
Давайте прозрачный нерабочий код писать и сидеть наслаждаться "крысотой"!

Да уж Open Source отдыхает...


 
begin...end ©   (2004-11-23 15:39) [95]


> [93] KSergey ©   (23.11.04 09:44)


> То, что вы выделили - мелочь, по-моему. Код по структуре
> принципиально отличается. Пока не буду писать чем.


> I := 0;
> if not <ошибка> then
> Repeat
>  <Код>
>  inc(i);
> Until <что-то> and (i<High(A));

1. Если массив пуст, то проверяется выполнение условия <ошибка> для несуществующего элемента.

Прочие недостатки относятся к случаю <ошибка> = False:

2. Если массив состоит из одного элемента, то после первого прохода i > High(A), и цикл никогда не закончится (если, конечно, не учитывать его вылет из-за ошибки).

3. Независимо от количества элементов массива: если окажется, что <что-то> = False при любом i, то цикл никогда не закончится.

Кто больше?

> [94] Verg ©   (23.11.04 09:50)

> Да уж Open Source отдыхает...

Да, на всеобщее обозрение такой код лучше не выставлять, - слишком прозрачный.


 
KSergey ©   (2004-11-23 15:52) [96]

> [95] begin...end ©   (23.11.04 15:39)

Да нет, я все же не о том.
Под "принципиально отличается" по структуре я имел в виду то, что if вынесен за пределы цикла! Т.е. в нем уже не может идти речь о проверке каких-либо элементов, тем более на каждой итерации. Изначальный же код выполнял if на каждой итерации. Налицо то, что код <ошибка> уже не применим, т.е. предлагаемый код не соответствует исходному по сути. Либо надо было оговаривать изменения в "абстракциях" (кусочках между <..>).
Про то, что для одного элемента выполнится цикл в любом случае - это как-то Defunct вообще игнорирует упорно до сих пор ;)


 
Defunct ©   (2004-11-23 18:48) [97]

> Да, т.к. повторю еще раз: он отличается функционально от оригинала. Не отличающийся я в вашем исполнении так и не увидел, увы... Задача же - показать функционально инедтичный код, а не код, примерно равный по функциональности, но работающий верно в других условиях. Это можно понять, наконец? При этом эти доп. условия по определению дожны быть указаны, т.к. являются неотъемлемой частью шаблона. Пусть и абстрактного.

Я вашу точку зрения понял. А вы мою?

> Хотя, а что же делать в немколько более сложном случае:

> for i := Low(A) to High(A) do
> begin
>   if <проблема_1> then break;
>   <код>
>   if <проблема_2> then break;
>   <код>
>    if <что-то> then break
> end;

Помоему я уже написал, как быть в общем случае. Только вы приняли это решение, за не относящееся к теме:

while not BreakStatus do
begin
 <код>;
 <Процедура в которой рассматриваются все проблемы и условия пребывания>
end;


> А постоянно приводить функционально совершенно не идентичный код - это нормально по-вашему???!!

А упорно не хотеть понять мою точку зрения это нормально?
Читать сообщения не полностью тоже нормально?

> Про то, что для одного элемента выполнится цикл в любом случае - это как-то Defunct вообще игнорирует упорно до сих пор ;)

А if перед стартом цикла? Вы его конечно проигнорировали.

> Until <что-то> and (i<High(A));
здесь была опечатка
если вы посмотрите на время когда я постил примеры (5:00) утра, думаю можно быть более снисходительным.

Verg ©   (23.11.04 09:50) [94]
не уподобляйтейсь begin...end.


 
begin...end ©   (2004-11-23 19:31) [98]


> [97] Defunct ©   (23.11.04 18:48)

Defunct, дело в том, что мне просто не нравятся голословные утверждения.

Вот Вы говорите в [81]:

> Моя цель была показать, что break не нужен, и что без break
> ошибки лучше видны. С чем я тоже успешно справился.

Надеюсь, это действительно Ваши слова, и я ничего не переврал?

Так вот - пожалуйста, покажите, ГДЕ в этой ветке Вы показали, что без Break ошибки лучше видны?

Ведь Вы ДО СИХ ПОР не привели кода, функционально соответствующего коду Gero [17]. Вместо этого Вы один за одним приводите варианты кода, в которых - ошибка на ошибке. На мой взгляд, это является прямым опровержением Вашего мнения. По крайней мере, для тех случаев, которые описываются в этой ветке.


> > Until <что-то> and (i<High(A));
> здесь была опечатка

А Вы можете наконец привести код, не содержащий опечаток?

И ещё - посмотрите, сколько человек согласно / не согласно (как я понял) с Вашим мнением о том, что "без break ошибки лучше видны".

Не согласны с этим утверждением (в алфавитном порядке):

1. Anatoly Podgoretsky (Мастер) [55]
2. begin...end [62]
3. Gero [8]
4. Ihor Osov"yak (Мастер) [50]
5. KSergey [85]
6. Palladin (Мастер) [31]
7. Verg (Мастер) [94]
8. Игорь Шевченко (Мастер) [30]

Согласны с этим утверждением:

1. Defunct

Вас это ни на какие мысли не наводит?


 
Verg ©   (2004-11-23 20:21) [99]


> [97] Defunct ©   (23.11.04 18:48)


> Verg ©   (23.11.04 09:50) [94]
> не уподобляйтейсь begin...end.


Не бредонось. Чес-слово, иногда такое несешь, что аж стыдно за наше поколение.....

"Следи за собой, будь осторожен" (С) Кино.


 
Defunct ©   (2004-11-23 20:30) [100]

> И ещё - посмотрите, сколько человек согласно / не согласно (как я понял) с Вашим мнением о том, что "без break ошибки лучше видны".

Ключевая фраза здесь - (как я понял).
Я и не смневался, что вы можете сказать, что все в этой ветке против моего мнения.
Для того чтобы разбить вашу теорию, достаточно посмотреть на первый пост, приведенный вами в качестве аргумента - AP [55]. Там нет ни слова о том согласен уважаемый AP или не согласен с моим мнением. Следовательно, дальше рассматривать приведенный Вами список даже нет смысла.

Мне очень интересно, какова цель ваших "атак"? Причем не только в этой ветке. Вас раздражает мой nick-name?


 
Verg ©   (2004-11-23 20:32) [101]


> 100] Defunct ©   (23.11.04 20:30)


Советую спать ночами, а не насиловать организм....


 
begin...end ©   (2004-11-23 20:41) [102]


> [100] Defunct ©   (23.11.04 20:30)


> Для того чтобы разбить вашу теорию, достаточно посмотреть
> на первый пост, приведенный вами в качестве аргумента -
> AP [55]. Там нет ни слова о том согласен уважаемый AP или
> не согласен с моим мнением.

Там есть выражение согласия с постом [31], поэтому прочитайте [31] внимательнее.

Но если Вы не считаете это очевидным, то пожалуйста - всё равно будет 7 против 1.


> Вас раздражает мой nick-name?

А вот здесь Вы глубоко заблуждаетесь. Меня раздражают голословные утверждения, и об этом я уже сказал в [98]. А уж кто эти самые голословные утверждения делает, а уж тем более, какой nick-name у того, кто их делает - мне абсолютно всё равно. Может быть, просто так получается, что Вы их делаете чаще, чем другие?

А Вы всё же, пожалуйста, ответьте на вопрос, заданный в [98]: "ГДЕ в этой ветке Вы показали, что без Break ошибки лучше видны?". Если можете ответить, конечно.


 
Defunct ©   (2004-11-23 20:44) [103]

Verg ©   (23.11.04 20:21) [99]

Именно это я и подумал, прочитав [94].
без обид.

поясню:
В [94] вы критиковали предложение:
>> Понимаете, моей целью не было написать рабочий пример.

> Это что, типа прозрачность в ущерб работоспособности?

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

> А зачем тогда if not <ошибка> then?
> Без этого if-а было бы еще прозрачнее.

Потому что мне, как автору поста, захотелось его там написать. Точно также как и Gero захотелось написать if IsError(Arr) then break.

> Давайте прозрачный нерабочий код писать и сидеть наслаждаться "крысотой"!

Давайте не будем искажать и переворачивать все вверх дном.
Используете break, хорошо, на то ваше право. Я не использую break, на то есть мое право. begin...end в мягкой форме говорит, что я пишу все программы по-ламерски раз не использую break, на то есть его право.

> Да уж Open Source отдыхает...

А это вообще не понятно к чему. Я не насколько дальновиден, чтобы увидеть связь OpenSource с оператором break и/или как-то связать с темой о циклах.


 
Verg ©   (2004-11-23 20:51) [104]


>  [103] Defunct ©   (23.11.04 20:44)


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


 
Defunct ©   (2004-11-23 21:07) [105]

Verg ©   (23.11.04 20:51) [104]

Очень интересная манера донести свое мнение.

PS: А на тебя-то что нашло? (я про [94])


 
Verg ©   (2004-11-23 21:11) [106]


> А на тебя-то что нашло? (я про [94])


Да "гонево" от тебя уже пошло тако-ое!. На самом деле непонятно стало - то ли ты издеваешься, то ли у тебя что-то с головой случилось....


 
Defunct ©   (2004-11-23 21:15) [107]

Verg ©   (23.11.04 21:11) [106]

Дык, просто надоело выслушивать поучения от некоторых.

> Да "гонево" от тебя уже пошло тако-ое!.
В общем да...


 
begin...end ©   (2004-11-24 09:30) [108]


> [107] Defunct ©   (23.11.04 21:15)

Правильно ли я понял - ответа на вопрос, повторенный в конце [102], и приведения кода (например, с циклом repeat) без опечаток, функционально соответствующего [17], - от Вас ожидать не следует?


 
KSergey ©   (2004-11-24 10:22) [109]

>  [97] Defunct ©   (23.11.04 18:48)
> Помоему я уже написал, как быть в общем случае. Только вы
> приняли это решение, за не относящееся к теме:
>
> while not BreakStatus do
> begin
>  <код>;
>  <Процедура в которой рассматриваются все проблемы и условия
> пребывания>
> end;

Издеваетесь? ;)
Нельзя ли уточнить вот это:

<Процедура в которой рассматриваются все проблемы и условия пребывания>

Я прекрасно понял вашу точку зрения.
Но вы упорно делаете вот что: приводите "абстрактный код" в котором кучу проверок, которые я рисую в своем "абстрактном коде" сводите в лаконичную фразу по-русски "Процедура в которой...".
А если эту фразу написать на дельфи, а? Будет ли она столь лаконичной?

Вы упорно приводите другие абстрактрые коды.
Я же считаю, что если код с for не выкидывая из него обязательные (предположим, для некоего алгоритма) куски (ну нельзя без них!) переложить на вариант без break - то выйдет куда более пространный код. Можно спорить о его прозрачности, но он будет существенно более многословным!

Вот потому я и бьюсь уже который день, пытаясь вытянуть не расплывчатую фразу "вот тут все проверки", а конкретный код, без упрощений!
Неужели нельзя его написать, наконец??! Чтобы можно было все же предметно разговаривать и голосовать, а??

> А if перед стартом цикла? Вы его конечно проигнорировали.

Да нет же! Я все внимательно читал. Но согласитесь, если if вставлен внутрь цикла - то наверное не от дури, а лишь потому, что за цикл его вынести нельзя (работает с конкретным элементом массива, например). Если это было не очевидно - прошу прощения, что не уточнил.

Так свет увидит наконец функционально полностью идентичный код тому, что приведен в [17] и [91]???

ЗЫ
С одним бодался-бодался (ровно о том же) - так он жаловаться ушел... Уж извините.


 
KSergey ©   (2004-11-25 11:10) [110]

Ну что, все, не увидим мы ответов тов. Defunct?


 
ASoft   (2004-11-25 12:03) [111]

Привет, Sicilla!
У меня на D7 такая хрень была, но в целом, программа работала.    Именно при проверке Step"ом переменная в цикле (for) показывала черти-что. До D7, никакой Дельфией не пользовался.
Что касается, выбирать из Break-Continue, я пользуюсь ими по мере надобности, когда считаю, что мне нужны данные операторы.
Ну и кашу заварил...:)


 
KSergey ©   (2004-11-25 12:15) [112]

>  [111] ASoft   (25.11.04 12:03)

Это не черти что, это работа оптимизатора. Автор же рассказывает не совсем понятно о чем...


 
begin...end ©   (2004-11-28 14:07) [113]

> [110] KSergey ©   (25.11.04 11:10)

"Жаль, что нам так и не удалось послушать начальника транспортного цеха" (© Жванецкий).


 
KSergey ©   (2004-11-28 14:11) [114]

> begin...end ©   (28.11.04 14:07) [113]

"...услышать..", если не ошибаюсь, было в оригинале ;)
Впрочем, не суть важно ;)


 
KSergey ©   (2004-11-29 07:46) [115]

Пишу от имени и по поручению Defunct. Текст авторский, без изменений.

KSergey ©   (24.11.04 10:22) [109]
> Так свет увидит наконец функционально полностью идентичный код тому,
что приведен в [17] и [91]???


> Gero ©   (17.11.04 23:35) [17]

> for i := 0 to High(Arr) do
>  begin
>   if IsError(Arr[i]) then Break;
>   <Код>
> end;


Для цикла while я инвертирую функцию IsError -> NoError;

i := 0;
CanGo := NoError(Arr[0]);
while CanGo do
begin
 <Код>
 inc(i);
 if i<High(Arr) then CanGo := NoError(Arr[i])
                else CanGo := False
end;


Для repeat отсавлю оригинальную IsError.

i := 0
if i<High(Arr) then
Repeat
 if not IsError(Arr[i]) then
 begin
   <Код>
 end;
 inc(i);
Until (i>=High(Arr)) or IsError(Arr[i-1]);


PS
Вот объяснения от Defunct:
меня кажется забанили из-за тов. Soft"a....
У нас с ним один IP (работаем через NAT).
Так что извините с задержкой ответа.
Можете его запостить в той ветке:


 
KSergey ©   (2004-11-29 07:50) [116]

Ну а теперь наш ответ чемберлену ;)

Ну то, что код стал более многословным - стоило ожидать. На мой взгляд - он менее прозрачен, ну да тут спорить наверное смысла нет, это уже религия. Соответственно, при усложнении сей код будет еще усложняться и все более запутываться. Хотя это опять мое мнение.

Единственный прокол, который я вижу - в цикле Repeat ф-ция IsError будет вызываться дважды для каждого элемента массива (кроме последнего). Хорошо ли это??


 
kostan ©   (2004-11-29 09:12) [117]

может не совсем в тему....
ВНИМАНИЕ!  Ошибка компилятора Delphi !
Обнаружена была давно (на сайте Borland есть ссылка)
реально НЕЛЬЗЯ использовать напрямую переменную цикла
в вычислениях!
пример:
for i:=1 to 1000 do
begin
  gg=i*i*20;
end;
выдаст не верный результат

НАДО так !! (через переменную)
for i:=1 to 1000 do
begin
  b=i
  gg=b*b*20;
end;


 
TButton ©   (2004-11-29 09:21) [118]


> а зачем Continue вообще нужен?
> также как и Goto и Exit его место на помойке IMHO.

+

> > Тогда уж и Break в придачу.
>
> Абсолютно точно, и break туда же.
> IMHO те кто пользуется
> Goto, Break, Continue, Exit
> просто не могут нормально реализовать логику программы.
>
> > А можно и циклы вобще выкинуть. Нафиг они нужны?
>
> не извращайте идею.
>
> C помощью 7-ми операторов можно реализовать любую логику:
> 1. пустой оператор - ;
> 2. оператор присваивания :=
> 3. Условный оператор if <> then <оператор> else <оператор>
> 4. Оператор цикла с пердусловием while <условие> do <оператор>
> 5. Оператор цикла с постусловием repeat <оператор> until
> <условие>
> 6. Оператор цикла с границами for <от> to <до> do <оператор>
> 7. Составной оператор begin <оператор>.. end.
>
> два доп. оператора case и with можно применять для красоты
> и наглядности программы.
>
> Continue, Break, Goto, Exit лишь запутывают логику программы
> и делают программу трудно читаемой.


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

ведь можно обойтиси всего двумя предметами
1. глиняная миска
2. китайские палочки.


 
ЮЮ ©   (2004-11-29 09:23) [119]

>выдаст не верный результат

И кто здесь чего выдаёт? если gg используется только для профанации, то, возможно, и будет "подсчитана неправильно", да только об этом никто не узнает.


 
KSergey ©   (2004-11-29 09:23) [120]

> [117] kostan ©   (29.11.04 09:12)

Может когда и было... Проверять лень, но сомнение меня разбирает...


 
kostan ©   (2004-11-29 09:37) [121]

<ЮЮ ©   (29.11.04 09:23) [119]
 код конечно -профонация (так для примера)

<KSergey ©   (29.11.04 09:23)

 чесное слово ...  :0) [Borland предупреждает  ;)]
 сам ловился (хватило одного раза , просидел в отладчике
 несколько часов - пока "умный" парень не помог)
 причем счет сбивается всегда с разных значений i
 (а бывает что выполняется успешно )


 
KSergey ©   (2004-11-29 09:44) [122]

> [121] kostan ©   (29.11.04 09:37)
>  чесное слово ...  :0) [Borland предупреждает  ;)]

О какой конкрентно версии речь?


 
kostan ©   (2004-11-29 09:49) [123]

ошибка была в Delphi5
щас специально "погонял" в Delphi7
че-то не вылазит (ошибка) - так что простите, наверно
убрали ее
[но все равно интересно:) ]


 
ЮЮ ©   (2004-11-29 09:55) [124]

>щас специально "погонял" в Delphi7
Включи оптимизацию и она вернется. Только не ошибка это. А вот вычислять незнамо что и незнамо зачем и анализировать это в отладчике - это ошибка :)


 
kostan ©   (2004-11-29 10:17) [125]

вот что "гонял" (это чтоб оптимизатор не с оптимизировал:)
 Memo1.clear;
 for dd:=10 to 1000 do
 begin
  rr:=dd*100;
  ff:=dd*rr;
  memo1.lines.add(floattostr(ff));
 end;

(это не ошибка компилятора - а глюк мат.сопроцессора-
был описан еще в книжке по DOS паскалю)


 
begin...end ©   (2004-11-29 13:17) [126]

> Defunct {[115] KSergey ©   (29.11.04 07:46)}

Расставим точки над "i".

1. Код Gero с for + Break:

> for i := 0 to High(Arr) do
>  begin
>   if IsError(Arr[i]) then Break;
>   <Код>
> end;

Производится проверка IsError для всех элементов массива, если массив вообще заполнен. При обнаружении элемента, для которого IsError = True, цикл заканчивается. Ошибок я тут не вижу. По крайней мере, для случая, когда Arr - это динамический массив, или это статический массив с нулевой нижней границей.

2. Ваш код с while:

> i := 0;
> CanGo := NoError(Arr[0]);

Введение дополнительной переменной. Это хорошо?

А в случае, если массив Arr пуст, эта строка вызовет ошибку. Добавьте соответствующую проверку, - и код станет ещё более многословным. Заметьте, в коде [17] эта проверка не нужна: если массив пуст, то цикл просто не выполнится ни разу.

> while CanGo do
> begin
>   <Код>
>   inc(i);
>   if i<High(Arr) then CanGo := NoError(Arr[i])
>                else CanGo := False
> end

Почему функцией NoError не проверяется последний элемент массива?

3. Ваш код с repeat:

> i := 0
> if i<High(Arr) then

Случай, когда массив Arr состоит из одного элемента, Вы игнорируете?

> Repeat
>   if not IsError(Arr[i]) then
>   begin
>     <Код>
>   end;
>   inc(i);
> Until (i>=High(Arr)) or IsError(Arr[i-1]);

Цикл дошёл до i = High(Arr). Тогда выделенное условие равно True. Следовательно, последний элемент массива не будет проверен. А ведь если этот непроверенный элемент массива дал бы IsError = False, то нужно было выполнить ещё и <Код>.

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


 
KSergey ©   (2004-11-29 14:00) [127]

> [126] begin...end ©   (29.11.04 13:17)
> А в случае, если массив Arr пуст, эта строка вызовет ошибку.

Позор мне!
Я действительно проглядел самое главное... Из-за чего я так долго "давил" (прошу прощения за термин) Defunc"а... Но так и "не выдавил", увы...

Ну да ладно ;)


 
Gero ©   (2004-11-29 17:06) [128]

i := 0;
if Length(Arr) > 0 then
 while (i <= High(Arr)) and not IsError(Arr[i]) do
   begin
     <Код>
     Inc(i);
   end;


При условии {$B-}.
Это наиболее простой код, который смог написать я для данного случая.
Вроде как без ошибок, при условии что
Здесь 7 строк.
В коде [15] их 5.
Нам приходится инициализировать переменную i и еще к тому же проверять, содержит ли массив элементы.

И неужели после этого товарищ Defunct будет утверждать, что без Break проще?


 
Gero ©   (2004-11-29 17:07) [129]


> Вроде как без ошибок, при условии что

Эта строка лишняя.


 
begin...end ©   (2004-11-29 17:28) [130]

> [128] Gero ©   (29.11.04 17:06)

> if Length(Arr) > 0 then

Раз уж {$B-}, то эту строку в Вашем случае всё же можно убрать, т.к. для пустого массива High(Arr) = -1.

Однако, разумеется, необходимость слежения за {$B-}/{$B+} уже сама по себе является существенным недостатком.


 
Gero ©   (2004-11-29 17:53) [131]


> begin...end ©   (29.11.04 17:28)

Да, ты прав, она лишняя.


 
Gero ©   (2004-11-29 17:59) [132]

Итак,

i := 0;
while (i <= High(Arr)) and not IsError(Arr[i]) do
 begin
   <Код>
   Inc(i);
 end;

Непонятно только, зачем Defunct городил невесть что.

Хотя даже этот код хуже примера с for.
Как уже было сказано, необходимость слежения за {$B} + необходимость инициализации i + вычисление индекса последнего элемента массива в каждой итерации цикла.


 
Defunct ©   (2004-11-30 07:01) [133]

Gero ©   (29.11.04 17:59) [132]
> Непонятно только, зачем Defunct городил невесть что.
Что этой фразой вы хотели сказать?
Втянули меня в дурацкий спор, и теперь еще спрашиваете что я городил. Надо было сразу написать лично вам этот код, потому как вам было виднее, что делает ваш код с циклом for.

> Хотя даже этот код хуже примера с for.
Он лучше хотя бы тем, что не используется break.

> + необходимость инициализации
Плюс возможность изменения индекса в произвольном порядке и с произвольным шагом. Как по мне это плюс.

{B-} всегда установлен по-умолчанию.

> + вычисление индекса последнего элемента массива в каждой итерации цикла.
не городите чепухи. посмотрите asm код этого цикла.

для цикла вашего цикла for:

 for i:=0 to High(Arr) do
 begin
   if IsError(Arr[i]) then break;
 end;


mov eax,[ebp-$04]
call @DynArrayHigh
mov  esi, eax
test esi, esi
jl   +$16
inc  esi
xor  ebx, ebx
mov  eax,[ebp-$4]
mov  eax,[eax+ebx*4]
call IsError
test al,al
jnz  +$4    <<--- вот он ваш break
inc  ebx
dec  esi
jnz  -$13
-->> выход из цикла (14 команд)



теперь сравним с циклом while (без break который)
 i := 0;
 while (i <= High(Arr)) and not IsError(Arr[i]) do
 begin
    Inc(i);
 end;


xor  ebx, ebx   <-- i:=0
jmp  +1
inc  ebx              <-- inc(i)
mov  eax, [ebp,-$4]
call @DynArrayHigh
cmp  ebx, eax
jnle +$F
mov  eax,[ebp-$4]
mov  eax,[eax+ebx*4]
call IsError
test al,al
jz   -$1c

--->> выход из цикла (12 команд)


Думаю теперь нет смысла спорить дальше.


 
Defunct ©   (2004-11-30 07:14) [134]

Defunct ©   (30.11.04 07:01) [133]

Подведу итог.
Каждый break добавляет дополнительный условный jmp, а как вы знаете число конвееров в процессоре ограничено. Если сильно много условныз ветвлений, то блок предсказания ветвлений неминуемо ошибается, что приводит к сбросу конвеера и замедлению выполнения цикла.


 
Verg ©   (2004-11-30 09:17) [135]


> для цикла вашего цикла for:
>
>  for i:=0 to High(Arr) do
>  begin
>    if IsError(Arr[i]) then break;
>  end;
>
> mov eax,[ebp-$04]
> call @DynArrayHigh
> mov  esi, eax
> test esi, esi
> jl   +$16
> inc  esi
> xor  ebx, ebx

> mov  eax,[ebp-$4]
> mov  eax,[eax+ebx*4]
> call IsError
> test al,al
> jnz  +$4    <<--- вот он ваш break
> inc  ebx
> dec  esi
> jnz  -$13

> -->> выход из цикла (14 команд)


Вот все тело цикла (жирным). Состоит оно из восьми команд. Содержит ровно столько же "ветвлений" условных. Но не содержит вызова call @DynArrayHigh (ветвление безусловное) на каждой итерации цикла. Оптимизатор выкинул из тела цикла инварантный код High(Arr).

Какой из циклов будет выполнен быстрее?


 
begin...end ©   (2004-11-30 09:41) [136]

> [133] Defunct ©   (30.11.04 07:01)

> > Хотя даже этот код хуже примера с for.
> Он лучше хотя бы тем, что не используется break.

Очень веский аргумент.

> > + необходимость инициализации
> Плюс возможность изменения индекса в произвольном порядке
> и с произвольным шагом.

Произвольный порядок - downto к Вашим услугам. Насчёт произвольного шага - согласен, но для данного случая, когда проверяется каждый элемент массива, шаг как раз должен быть равен 1.

> > + вычисление индекса последнего элемента массива в каждой
> итерации цикла.
> не городите чепухи. посмотрите asm код этого цикла.

И что - этот asm код показывает, что для while НЕ происходит вычисление High(Arr) для каждой итерации?

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

А насчёт производительности - вот, пожалуйста:

function IsError(Item: Integer): Boolean;
begin
 Result := Item < 0
end;

var
 I, J, K: Integer;
 T1, T2: Cardinal;
 Arr: array of Integer;
begin
 
 // Заполнение массива
 SetLength(Arr, 1000000);
 Randomize;
 for I := 0 to High(Arr) - 1 do
   Arr[I] := Random(100);
 Arr[High(Arr)] := -1;

 // Подсчёт времени выполнения for с Break
 T1 := GetTickCount;
 for J := 0 to High(Arr) do
 begin
   if IsError(Arr[J]) then Break;
 end;
 T1 := GetTickCount - T1;

 // Подсчёт времени выполнения while без Break
 T2 := GetTickCount;
 K := 0;
 while (K <= High(Arr)) and not IsError(Arr[K]) do
 begin
   Inc(K);
 end;
 T2 := GetTickCount - T2;

 // Результаты
 ShowMessage(Format("For с Break: %d; while без Break: %d", [T1, T2]))

end.


Выполните этот код, можете запостить сюда результат.
У меня получилось вот что: "For с Break: 30; while без Break: 60".

> Думаю теперь нет смысла спорить дальше.

Вот и последуйте своему же совету.


 
begin...end ©   (2004-11-30 09:44) [137]

Дополнение к [136]:

Результат "For с Break: 30; while без Break: 60" - это при включённом Range Checking. Если Range Checking выключить, то у меня получается: "For с Break: 40; while без Break: 50". Т.е. всё равно код с while проигрывает.


 
Gero ©   (2004-11-30 13:19) [138]


> не городите чепухи. посмотрите asm код этого цикла

Простите, а вы сами-то его смотрели?
В [135] все сказано, повторяться не буду.



Страницы: 1 2 3 4 вся ветка

Форум: "Основная";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.98 MB
Время: 0.05 c
14-1100851367
truster
2004-11-19 11:02
2004.12.12
Распаковка ZIPа в Far-e


3-1100237129
Margel
2004-11-12 08:25
2004.12.12
Как заставить DBMemo отдавать в буфер обмена кирилицу?


4-1098867565
GuestTM
2004-10-27 12:59
2004.12.12
Как отловить ACCESS VIOLATION...


6-1096864298
Sasha aka Slon
2004-10-04 08:31
2004.12.12
локалка


3-1100516912
Алекс
2004-11-15 14:08
2004.12.12
DATAPUMP пример конвертации или статью





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский