![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Можно ли избавиться от goto в этом коде ? [D7]
Гоу ту © (2005-03-14 01:15:00)Зачем ? Просто из спортивного интереса.
for i := 0 to High(BoxA) do
if BoxA[i].obj = nil then begin
Result := i;
{ some code here }
goto End1;
end;
Result := Length(BoxA);
SetLength(BoxA, Result +1);
End1:
Defunct (2005-03-14 06:14:00) [1]И самое печальное то, что если пацан считает, что хранение дыр в массиве (без сдвига массива при удалении элемента) ускоряет работу, так он сильно ошибается, потому что что сдвиг части массивапри удалении элемента, что поиск дыр при добавлении по скорости одниковые операции .
Разница только в том, что в первом случае (со сдвигом части массива при удалении элемента) число возможных багов снизится т.к. всегда известно, что ВСЕэлементы массива СУЩЕСТВУЮТ(ну и как побочный эффект никакой надобности в goto или в break не возникнет).
Defunct (2005-03-14 06:02:00) [2][22] продолжу
вот пример:
procedure TABox.AddItem(AObject: TObject);
begin
Inc( fCount );
SetLength( fItems, fCount);
Items[fCount - 1] := AObject;
end;
Разве может быть процедура добавления более простой? И скажите в какое место здесь можно вставить Goto?
Defunct (2005-03-14 05:55:00) [3]> default ©
Тривиальная задача. Пацану захотелось оставлять дыры в массиве. Ну так это его проблема, которая породила новую проблему - использование Goto.
Я бы постарался избежать этих дыр, например двухсвязным списком или еще как-то ибо дырявый (с элементами nil) BoxA это потенциальный ходячий баг.
default (2005-03-14 05:42:00) [4]хотя нет - 2 и 3 не аналоги 1 в [19](по принципу)
а с goto как не крути лучше всего
default (2005-03-14 05:28:00) [5]Defunct © (14.03.05 04:47) [19]
1 вариант по логике аналог [16]
а 2 и 3 аналог 1
Defunct (2005-03-14 04:47:00) [6]> Гоу ту
Вариант 1. (такой же длины как и оригинал)
Result := Length(BoxA);
for i := 0 to High(BoxA) do
if BoxA[i].obj = nil then
begin
Result := i;
{ some code here }
Break;
end;
if Result = Length(BoxA) then
SetLength(BoxA, Result +1);
Вариант 2 (логика изменена):
Result := Length(BoxA);
i := Result - 1;
while i >= 0 do
begin
if BoxA[i].Obj = nil then
begin
{ some code here }
Break;
end;
Dec(i);
end;
if i < 0 then
SetLength(BoxA, Result +1)
else
Result := i;
Вариант 3 (логика изменена):
Result := Length(BoxA);
i := Result - 1;
while (i >= 0) and (BoxA[i].Obj <> nil) do Dec(i);
if i < 0 then
SetLength(BoxA, Result +1)
else
begin
Result := i;
{ some code here }
end;
default (2005-03-14 02:38:00) [7]Гоу ту (14.03.05 02:34) [17]
задумайся
результат сравнения есть логическая константа: True или False
численное же значение констант: Byte(True)=1, Byte(False)=0
последний вариант хорош, вот только логика не так проста
Гоу ту (2005-03-14 02:34:00) [8]
> default © (14.03.05 02:17) [16]
> Byte(Result=Length(BoxA)
> идеалогически правильно следовать [12] или оставить первый
> вариант
Первый вариант. Ибо, вот какой результат даст эта строка +Byte(Result=Length(BoxA)) ? Надо задуматься.
Так, что да-здравствует гоу ту, и правильная логика. Если не нашли объект, то добавляем новый. Как словами говорим, так программу и пишем, безо всяких извращений.
default (2005-03-14 02:17:00) [9]
Result := Length(BoxA);
for i := 0 to High(BoxA) do
if BoxA[i].obj = nil then begin
Result := i;
{ some code here }
Break
end;
SetLength(BoxA, Length(BoxA) + Byte(Result=Length(BoxA));
вообщем, как видишь, воображение может создавать всё новые и новые модификации:)
идеалогически правильно следовать [12] или оставить первый вариант
Гоу ту (2005-03-14 02:14:00) [10]
> > Но стало длиннее. А значит хуже.
> > И непонятнее.
> Хм. длиннее - значит хуже и непонятнее? Длина и понятность
> как-то коррелируются?
В вашем предложении да, а в моём нет. Нефиг переделывать чужие предолжения.
> default © (14.03.05 01:55) [13]
> строку Result := Length(BoxA); можно безболезненно вынести
> в начало кода
Два вызова функции SetLength вместо одного. Ла и логика извращённая. Сначала одну длину устанавливаем, потом другую. Уж лучше гоу ту, чем так.
GuAV (2005-03-14 02:03:00) [11]Exit + finally
abort + except
default (2005-03-14 01:55:00) [12]строку Result := Length(BoxA); можно безболезненно вынести в начало кода
отмена Goto по-любому потребует внесения дополнительного кода
можно ещё так
Result := Length(BoxA);
SetLength(BoxA, Result +1);
for i := 0 to High(BoxA)-1 do
if BoxA[i].obj = nil then begin
Result := i;
{ some code here }
SetLength(BoxA, High(BoxA));
Break
end;
Просто Джо (2005-03-14 01:50:00) [13]Ну, так разбей это дело на 2 функции, примерно так:
function X(var BoxA: TArr): Integer;
// возвращает номер пустого эл-та
// или -1, если пустых нет
function GetNilElementIndex: Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to High(BoxA) do
if BoxA[I].obj = nil then
begin
Result := I;
Break
end;
end;
begin
Result := GetNilElementIndex;
if Result = -1 then
begin
Result := Length(BoxA);
SetLength(BoxA, Result +1);
end;
end;
> Но стало длиннее. А значит хуже.
> И непонятнее.
Хм. длиннее - значит хуже и непонятнее? Длина и понятность как-то коррелируются? Это новость.
Гоу ту (2005-03-14 01:46:00) [14]
> Просто Джо © (14.03.05 01:32) [6]
> Тогда достаточно заменить Goto на Exit.
Нельзя. Там дальше ещё код идёт.
default (2005-03-14 01:42:00) [15]Гоу ту (14.03.05 01:38) [9]
если у тебя после End1: ничего не должно выполняться, то делай Exit как тебе сказали в [6]
Гоу ту (2005-03-14 01:38:00) [16]
> default © (14.03.05 01:28) [3]
> например, так
Но стало длиннее. А значит хуже.
И непонятнее.
default (2005-03-14 01:34:00) [17]Result намекает об этом, но всё же не факт
default (2005-03-14 01:34:00) [18]Просто Джо © (14.03.05 01:32) [6]
тут не очерчены рамки подпрограммы да и вообще что это подпрограмма
Просто Джо (2005-03-14 01:32:00) [19]Если я правильно интерпретировал ваши намерения, то в случае, если не один из элементов массива не равен nil, то результат функции должен быть равен старой длине массива, а новая длина массива должна быть увеличена на 1? Если же хоть один элемент массива равен nil, то функция возвращает индекс первого такого элемента? Так? Тогда достаточно заменить
GotoнаExit. А вообще, переписать нафик.
default (2005-03-14 01:31:00) [20]блин
Result := 0;
for i := 0 to High(BoxA) do
if BoxA[i].obj = nil then begin
Result := i;
{ some code here }
Break
end;
if BoxA[Result].obj <> nil then begin
Result := Length(BoxA);
SetLength(BoxA, Result +1);
end;