![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Кака лучше?
Fr © (2012-04-15 13:23:00)Практически везде в предоставляемых кусках кода есть такое:
for i:=0 to SL.Count-1 do ...
Почему вместоSL.Count-1не используетсяPred(SL.Count)?
В чем здесь подвох? Может одна операция действует быстрее другой? Или может возникнуть какая-нибудь проблема при использованииPred(SL.Count)?
Anatoly Podgoretsky (2012-04-17 10:11:00) [21][24] пошел в дальше, там уже использованы именованые константы диапазона, вместо 1..100
Anatoly Podgoretsky (2012-04-17 10:09:00) [22]
for Current:=Low(Rooms) to High(Rooms) do Rooms[Current]:=2;А Rooms это размерность TNumber, который является константой, а чем это станет зависит от использования, TNumber полностью совместим с Integer, поскольку является поддиапазоном последнего.
for Current:=Low(Rooms) to High(Rooms) do Rooms[Current]:=2;
Это является надежным аналогом
for Current:=1 to 100 do Rooms[Current]:=2;
Ясно же что константы и производные типы безопаснее и понятнее.
CRLF (2012-04-17 10:00:00) [23]Но ему присваивается результат от операции TNumber c Integer, что может быть некорректно. Не говоря уже о том, что "количество" в примере может быть отрицательным и это никак не проверяется.
Anatoly Podgoretsky (2012-04-17 09:50:00) [24]Там другой вариант, тоже правильно реализованый
Current: TNumber;
CRLF (2012-04-17 09:16:00) [25]
> как в [24]
как в [28] ;-)
Anatoly Podgoretsky (2012-04-17 09:03:00) [26]
> Во-вторых, смешивать TNumber и Integer потенциально опасно
> (что, видимо, пример и демонстрирует).
А не надо смешивать, например как в [24]
Anatoly Podgoretsky (2012-04-17 09:00:00) [27]
> Юрий Зотов © (16.04.12 21:21) [27]
Померещилось конечно.
Причин для выхода нет совсем, когда границами является размерность массива. В Паскале тоже самое.
Более того я ранее обычно писал так, с использование констант границ и использованием из в виде индекса и размерности.
А выражение array x[TYPE] означает array x[Low(TYPE)..High(TYPE)] сокращеная форма.
Sha (2012-04-17 08:57:00) [28]Обычно его не надо предварительно проверять*
Sha (2012-04-17 08:54:00) [29]> CRLF (17.04.12 07:43) [29]
> Не совсем понятно, что ты хотел продемонстрировать
1. То, что количество объектов (комнат, символов и т.п.) может быть получено в результате вычислений.
2. То, что 0 - это вполне корректное количество объектов (это не -1, не -2 и т.п.). Обычно его не надо предварительно ни при Copy, ни при Move и т.п., я привык не проверять. Ведь 1 я не проверяю.
3. То, что теперь мне не совсем понятно, как в моем случае должен выглядеть цикл с нулевым количеством повторений. Непонятно почему (ну, мне понятно почему) компилятору пофиг, если такой цикл начинается с любого элемента и не пофиг, если с первого.
4. Все это тем более непонятно, что обычно количество повторений цикла for компилятор вычисляет заранее.
5. То, прав Юрий Зотов: любую полезную вещь можно превратить в бесполезную (или даже вредную), доведя ее до абсурда.
CRLF (2012-04-17 07:43:00) [30]
> Sha © (17.04.12 01:23) [28]
Не совсем понятно, что ты хотел продемонстрировать, но... Во-первых, нужно проверять, что Count > 0. Во-вторых, смешивать TNumber и Integer потенциально опасно (что, видимо, пример и демонстрирует).
Sha (2012-04-17 01:23:00) [31]
type
TNumber= 1..100;
TRooms= array[TNumber] of integer;
function Volume(const Rooms: TRooms; First: TNumber; Count: integer): integer;
var
Current: TNumber;
begin;
Result:=0;
for Current:=First to First+Count-1 do Result:=Result+Rooms[Current];
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Rooms: TRooms;
Current: TNumber;
begin;
for Current:=Low(Rooms) to High(Rooms) do Rooms[Current]:=2;
Volume(Rooms,2,2);
Volume(Rooms,2,0);
Volume(Rooms,1,1);
Volume(Rooms,1,0);
end;
Юрий Зотов (2012-04-16 21:21:00) [32]Проверил (D7) - ошибка действительно не возникает. Сорри.
Но возникает вопрос - откуда же я это взял, не из головы же придумал? Точно помню, что эти ошибки были.
Видимо, это было еще в Паскале, а на Delphi перенес по привычке.
Юрий Зотов (2012-04-16 17:35:00) [33]
> CRLF (16.04.12 17:30) [25]
> RWolf © (16.04.12 17:23) [24]
Приду домой - проверю, сейчас Delphi нет под рукой.
CRLF (2012-04-16 17:30:00) [34]
> Юрий Зотов © (16.04.12 17:19) [23]
Специально проверял, range check error не возникает. Delphi XE2.
RWolf (2012-04-16 17:23:00) [35]вот прямо сейчас запустил код на Д7:
procedure TForm1.Button1Click(Sender: TObject);
const
IndexMin = 11;
IndexMax = 322;
type
TIndex = IndexMin..IndexMax;
TArray = array [TIndex] of byte;
var
j: TIndex;
a: TArray;
begin
for j := IndexMin to IndexMax do
caption:=caption+IntToStr(a[j]);
end;
Range checking включен, процедура работает без ошибок.
Юрий Зотов (2012-04-16 17:19:00) [36]
> CRLF (16.04.12 17:06) [21]
> вряд ли это можно считать проблемой.
Если контроль выхода за диапазон выключен, то да, не проблема. А у меня, например, есть привычка держать его включенным и отключать только при билде релиза. И если в коде есть подобные конструкции, то выскакивающие из-за них окошки исключений очень сильно мешают.
RWolf (2012-04-16 17:16:00) [37]
> Юрий Зотов © (16.04.12 16:07) [17]
> for j := IndeхMin to IndexMax do ...; // Выход за диапазон
> Действительно, выход за пределы диапазона есть
какой такой выход?
вы меня пугаете.
CRLF (2012-04-16 17:06:00) [38]Действительно, выход за пределы диапазона есть, в том числе и при использовании Low, High.
Но так как параметр цикла вне цикла имеет неопределённое значение и компилятор об этом предупреждает, вряд ли это можно считать проблемой.
Юрий Зотов (2012-04-16 16:57:00) [39]
> CRLF (16.04.12 16:48) [19]
После последнего витка цикла его счетчик еще раз инкрементируется и выходит за диапазон.
CRLF (2012-04-16 16:48:00) [40]
> for j := IndeхMin to IndexMax do ...; // Выход за диапазон
Поясни, о каком выходе идёт речь.