Текущий архив: 2006.04.09;
Скачать: CL | DM;
Вниздобавить элемент в динамический массив в начало и в конец Найти похожие ветки
← →
Delphi5.01 © (2006-03-20 02:46) [0]Доброе время суток,
Есть ли способ который позволил бы добавить элемент в динамический массив в начало и в конец, не повреждая все остальные элементы, типа имеемvar
myArray: array of byte;
begin
SetLength(myArray, 3);
myArray[0] := 1;
myArray[1] := 2;
myArray[2] := 3;
//на данный момент массив содержит элементы [1, 2, 3]
end;
что надо сделать что бы массив стал содержать 4 элемента и новый элемент добавился или в начало или в конец соответственно
[new, 1, 2, 3] и [1, 2, 3, new]
как сделать в РНР или в Java я знаю а вот как с дельфи проблемы
Заранее благодарен за помощь
п.с. Прошу банальные варианты с увеличением размера массива и циклом перемещение всех элементов на одну позицию не предлагать
← →
Джо © (2006-03-20 02:51) [1]> п.с. Прошу банальные варианты с увеличением размера массива
> и циклом перемещение всех элементов на одну позицию не предлагать
Не обязательно циклом. Можно при помощиMove.
← →
Джо © (2006-03-20 02:56) [2]Для помещения в конец никакого Move и цикла, разумеется, не нужно. "Банальный" SetLength и запись в последний элемент. Учти, что вызов SetLength в любом случае повлечет за собой реаллокацию памяти под массив.
← →
Delphi5.01 © (2006-03-20 05:48) [3]Для помещения в конец никакого Move и цикла, разумеется, не нужно. "Банальный" SetLength и запись в последний элемент. Учти, что вызов SetLength в любом случае повлечет за собой реаллокацию памяти под массив.
Что значит именно "реаллокацию", по идее оно должно повлечь потерю содержимого массива, так? если да то SetLength не поможет, я об этом подумал правда пока не про экспериментировал :-)
Что касается move вот это уже интересно, а насколько он быстрей банального цикла, если он на уровне памяти и поинтеров работает то все ок если нет то не вижу смысла.
Большое вам спасибо за уделенное время
И вообще как массив устроен в Delphi? вот уже больше 5 лет под него программирую а вопрос только сейчас возник (был и раньше но не так обращал внимание).
Заранее благодарен.
← →
Yanis © (2006-03-20 09:22) [4]
> Что значит именно "реаллокацию", по идее оно должно повлечь
> потерю содержимого массива, так?
Нет. Что мешает проверить?
> И вообще как массив устроен в Delphi?
В интернете про это есть статьи. Вот что в справке (!) к стати написано:Dynamic array types
A dynamic-array variable occupies four bytes of memory which contain a pointer to the dynamically allocated array. When the variable is empty (uninitialized) or holds a zero-length array, the pointer is nil and no dynamic memory is associated with the variable. For a nonempty array, the variable points to a dynamically allocated block of memory that contains the array in addition to a 32-bit length indicator and a 32-bit reference count. The table below shows the layout of a dynamic-array memory block.
Dynamic array memory layout
Offset Contents
-8 32-bit reference-count
-4 32-bit length indicator (number of elements)
0..Length * (size of element) - 1 array elements
← →
Delphi5.01 © (2006-03-20 14:21) [5]Спасибо за помощь
п.с. И хотелось увидеть того придурка админа который данный топик из общего перенес в начинающим :-) Там же в вопросе было написно не предлогать банальные решения а что мне в рзаделе для начинающих могут посоветовать, как лудше цикл устроить? Ну вы блин даете если новички задают вопросы про динамические массивы и работу с ними на уровне адресов то что можно ожидать в разделе общие вопросы или даже WinAPI. Дело просто в том что вместо тупой сортировки иногда вместо Ж подумайте и головой!!! больше 4 лет с этим форумом и такого пока еще ни когда не происходило, наверно новых придурков наняли для сортировки тем
← →
GuAV © (2006-03-20 14:39) [6]Доб в начало:
Если массив не содердит типы с управляемым временем жизни (т.е. анси строки, другие дин массивы, варианты, интерфейсы), то SetLength + Move + доб в начало.
Если содержит, то код немного усложняется - нужно явно финализировать последний элемент до замещения, и обнулить без финализации первый.
Доб в конец тривиально.
> Учти, что вызов SetLength в любом случае повлечет за
> собой реаллокацию памяти под массив.
Может полечь а может и не повлечь. Но таки в любом случае.
← →
Delphi5.01 © (2006-03-20 17:16) [7]Bolshoe spasibo za pmosh GuAV, teper budu eksperementirovat.
← →
Delphi5.01 © (2006-03-20 17:17) [8]Da zabil dobavit chto massiv budet record tipa. Dumau eto ne doljno povlech problem
← →
DelphiCity (2006-03-20 18:59) [9]
> Delphi5.01 © (20.03.06 14:21) [5]
Данному топику место как раз в «начинающим»
> И вообще как массив устроен в Delphi? вот уже больше 5 лет
> под него программирую а вопрос только сейчас возник
ну и чем можно было 5 лет заниматься, не зная элементарных вещей, тот же move который еще в школе проходят(серьезно), и не уметь пользоваться справкой?
← →
Delphi5.01 © (2006-03-20 21:57) [10]DelphiCity
начнем с того что топик оценивается вопросом а не ответами в нем! Во вторых перед тем как на кого-то наезжать сначала узнай кто он и что он из себя представляет в программировании. Если ты думаешь что кидая кнопки на форму ты программируем то ты глубоко заблужаещся, ты сначала для примера разбери KOL (key object library) и создай в нем компонент, потом можно графику подучить с DirectX-ом, немного сетевых программ напиши, под конец разберись в API функциях (самых распространенных) и вот потом я к твоему совету прислушаюсь.
А то что я не знал о команде move еще ни о чем не говорит :-) В Джаве к примру все сложные структуры и так на уровне пойнтеров в дельфи надо через спец символ обрушаться и у каждого языка свой стиль, так что назубок только не нормальный параноик может учить. Что касается доки то там как всегда не описываться те нюансы о которых могут сказать люди кто с этим уже давно работал, и я подозреваю что к таким людям ты не относишься
Так как флудить в теме кроме самоуверенного любителя ни кто не будет!!!
п.с. Параллельно не буду затрагивать тему создания много потокового режима в PHP в котором такое вообще не реально и должно делаться на уровне операционной системы.
← →
SergP. (2006-03-21 02:42) [11]
> Delphi5.01 © (20.03.06 14:21) [5]
> п.с. И хотелось увидеть того ... который данный
> топик из общего перенес в начинающим :-) Там же в вопросе
> было написно не предлогать банальные решения а что мне в
> рзаделе для начинающих могут посоветовать, как лудше цикл
> устроить? Ну вы блин даете если новички задают вопросы про
> динамические массивы и работу с ними на уровне адресов то
> что можно ожидать в разделе общие вопросы или даже WinAPI.
> Дело просто в том что вместо тупой сортировки иногда вместо
> Ж подумайте и головой!!! больше 4 лет с этим форумом и такого
> пока еще ни когда не происходило, наверно новых ...
> наняли для сортировки тем
ИМХО как раз дело в том что не новых наняли, а продолжают это делать старые. А у них соответствующие критерии с течением времени меняются...
Но не стоит так все воспринимать, особенно не стоит это воспринимать как оскорбление. Лично мне было бы пофик куда что перенесли. главное чтобы ответили...
Да и часто бывает что топики которые содержат "нормальные" вопросы переносяться в "Новичкам", а топики которые следовало бы туда перенести остаются в основном. Но это мое мнение. Мнение же другого человека (например того же модератора) может быть иное.
← →
Джо © (2006-03-21 02:50) [12]... но после прямых оскорблений, я думаю, мнение модератора, если и изменится, то только не в лучшую сторону. И это есть правильно.
← →
Германн © (2006-03-21 02:58) [13]
> как сделать в РНР или в Java я знаю а вот как с дельфи проблемы
Ну вот лично для меня, вышеуказанная строка - является несомненной причиной переноса в "Начинающие"! Т.е. ты сам иницировал сей перенос своими высказываниями.
Ещё одна причина является в виде Пост-Фактум. Тебе всё-таки помогли, несмотря на перенос (а может и благодаря ему?).
← →
Delphi5.01 © (2006-03-21 04:40) [14]Ок одинм словом многие высказывания в постах 11, 12, 13 принимаю, возможно зря я вообше завелся переносом ветки, но всеже мое ИМХО тему не надо было переносить, я вообше хотел вопрос в API задать так как знал что для этого возможно придеться воспользоваться некой API функцией.
п.с. Я как подумал мне больше не понравился пост который приравнивал меня с начинающим ламаком :-) Млин я же не говорю что я вундеркинд но давно не делетант :-)
← →
SergP. (2006-03-21 05:18) [15]
> я вообше хотел вопрос в API задать так как знал что для
> этого возможно придеться воспользоваться некой API функцией.
>
Но ведь Move - не является API-функцией
Вот ее код: (из system.pas)
procedure Move( const Source; var Dest; count : Integer );
{$IFDEF PUREPASCAL}
var
S, D: PChar;
I: Integer;
begin
S := PChar(@Source);
D := PChar(@Dest);
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
Кстати ИМХО сделано не лучшим способом...
← →
Delphi5.01 © (2006-03-21 08:58) [16]SergP
Согласен что сделано как я понимаю банально циклом, вот только думаю что у этого метода преимущества с банальным перемещением никакого :-( если я точно понимаю что есть структура PChar (это стоковой параметр с нулевым символом в конце).
Полюбому надо что-то на уровне указателей. Вот что мне пришло в голову пока я данный топик создал. Если каждый элемент массива как структура LinkList то можно довольно легко добавлять новый элемент в начало и конец массива указав элементу массива что следующий элемент находиться по такому адресу. Но для этого надо понять как устроен массив и есть ли у меня возможность вмешиваться на такой низкий уровень ...
Есть ли у кого идеи?
← →
Delphi5.01 © (2006-03-21 09:09) [17]п.с. Как я понимаю здесь на форуме раздел "Начинающим" зашифрован, вот только что видел топик с названием "Динамическая память" ну как можно такой топик отнести к начинающим? Что тогда надо писать в "Основная". Скоро в разделе "Начинающим" появиться вопросы, как можно реализовать Х проблему используя Turbo Assembler :-)
← →
Amoeba © (2006-03-21 11:47) [18]
> SergP. (21.03.06 05:18) [15]
>
> > я вообше хотел вопрос в API задать так как знал что для
>
> > этого возможно придеться воспользоваться некой API функцией.
>
> >
>
>
> Но ведь Move - не является API-функцией
>
> Вот ее код: (из system.pas)
>
> procedure Move( const Source; var Dest; count : Integer
> );
> {$IFDEF PUREPASCAL}
> var
> S, D: PChar;
> I: Integer;
> begin
> S := PChar(@Source);
> D := PChar(@Dest);
> if S = D then Exit;
> if Cardinal(D) > Cardinal(S) then
> for I := count-1 downto 0 do
> D[I] := S[I]
> else
> for I := 0 to count-1 do
> D[I] := S[I];
> end;
>
> Кстати ИМХО сделано не лучшим способом...
Ну и что? На самом деле все несколько не так. Если хорошенько посмотреть в исходники, то есть и реализация на ассемблере, которая и используется на самом деле. PUREPASCAL по умолчанию не активно, так что на самом деле приведенного тобой кода в откомпилированном SYSTEM нет.
P.S. В D4, например, нет ни PUREPASCAL, ни приведенного тобой кода, и вся процедура целикос на ассемблере.
← →
Sapersky (2006-03-21 13:18) [19]Чтобы меньше двигать массив при добавлении в начало, можно выделить сначала некоторый объём и добавлять элементы начиная со середины, отслеживая начальный и конечный индексы; если не влезает - перевыделять память блоками, на несколько элементов сразу.
Можно и списком.
← →
Delphi5.01 © (2006-03-21 20:18) [20]Amoeba
Как я думаю единственный выход это протестировать функцию практически и стравнить с стандартным переносом циклом.
Sapersky
Идея очень понравилась на счет большого массива, можно взять в 3 раза больше и как только массив дойдет до начала или конца, типа больше двагать нельзя, вот потом можно массив перенести в середину и сново все повторить, теоретитески у меня движения в обои стороны массива рандомом, так что вероятность что он постоянно будет двигаться в одно напровление очень мала, типа теоретически думаю это самым оптимальным решением для моей конкретной задачи и перенос массива как уже предлагали делать процедурой move
п.с.
Сечас только что с работы пришел, проверю по позже, если у кого еще мысли появяться то выкладывайте не стесняйтесь ;-)
← →
SergP. (2006-03-22 00:36) [21]
> Amoeba © (21.03.06 11:47) [18]
ну а зачем тогда в system.pas существует [15] ?
Я вобще-то подозревал что Borland не опустится до [15], но нормального кода пока не нашел. Подскажите плиз где он...
← →
Джо © (2006-03-22 01:26) [22]> [21] SergP. (22.03.06 00:36)
> ну а зачем тогда в system.pas существует [15] ?
> Я вобще-то подозревал что Borland не опустится до [15],
> но нормального кода пока не нашел. Подскажите плиз где он...
Ассемблерный код там же, в {$ELSE} для IFDEF"а.
procedure Move( const Source; var Dest; count : Integer );
{$IFDEF PUREPASCAL}
var
S, D: PChar;
I: Integer;
begin
S := PChar(@Source);
D := PChar(@Dest);
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
{$ELSE}
asm
{ ->EAX Pointer to source }
{ EDX Pointer to destination }
{ ECX Count }
PUSH ESI
PUSH EDI
MOV ESI,EAX
MOV EDI,EDX
MOV EAX,ECX
CMP EDI,ESI
JA @@down
JE @@exit
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
REP MOVSD
MOV ECX,EAX
AND ECX,03H
REP MOVSB { copy count MOD 4 bytes }
JMP @@exit
@@down:
LEA ESI,[ESI+ECX-4] { point ESI to last dword of source }
LEA EDI,[EDI+ECX-4] { point EDI to last dword of dest }
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
STD
REP MOVSD
MOV ECX,EAX
AND ECX,03H { copy count MOD 4 bytes }
ADD ESI,4-1 { point to last byte of rest }
ADD EDI,4-1
REP MOVSB
CLD
@@exit:
POP EDI
POP ESI
end;
{$ENDIF}
/
← →
Delphi5.01 © (2006-03-22 05:54) [23]Джо
Вот это уже мне нравиться :-) Типа выше указанный код доказывает то что данная функция возможно является самым оптимальным решением для перемещения массива :-)
← →
SergP. (2006-03-22 07:57) [24]
> Джо © (22.03.06 01:26) [22]
М-да... Это я стормозил немного. Просто в данном случае не обратил внимания на директивы {$IFDEF...} {$ELSE} {$ENDIF} так как мне казалось что достаточно одного варианта move
Страницы: 1 вся ветка
Текущий архив: 2006.04.09;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.014 c