![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
добавить элемент в динамический массив в начало и в конец [D7, WinXP]
Delphi5.01 © (2006-03-20 02:46:00)Доброе время суток,
Есть ли способ который позволил бы добавить элемент в динамический массив в начало и в конец, не повреждая все остальные элементы, типа имеем
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 я знаю а вот как с дельфи проблемы
Заранее благодарен за помощь
п.с. Прошу банальные варианты с увеличением размера массива и циклом перемещение всех элементов на одну позицию не предлагать
SergP. (2006-03-22 07:57:00) [1]
> Джо © (22.03.06 01:26) [22]
М-да... Это я стормозил немного. Просто в данном случае не обратил внимания на директивы {$IFDEF...} {$ELSE} {$ENDIF} так как мне казалось что достаточно одного варианта move
Delphi5.01 (2006-03-22 05:54:00) [2]Джо
Вот это уже мне нравиться :-) Типа выше указанный код доказывает то что данная функция возможно является самым оптимальным решением для перемещения массива :-)
Джо (2006-03-22 01:26:00) [3]> [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}
/
SergP. (2006-03-22 00:36:00) [4]
> Amoeba © (21.03.06 11:47) [18]
ну а зачем тогда в system.pas существует [15] ?
Я вобще-то подозревал что Borland не опустится до [15], но нормального кода пока не нашел. Подскажите плиз где он...
Delphi5.01 (2006-03-21 20:18:00) [5]Amoeba
Как я думаю единственный выход это протестировать функцию практически и стравнить с стандартным переносом циклом.
Sapersky
Идея очень понравилась на счет большого массива, можно взять в 3 раза больше и как только массив дойдет до начала или конца, типа больше двагать нельзя, вот потом можно массив перенести в середину и сново все повторить, теоретитески у меня движения в обои стороны массива рандомом, так что вероятность что он постоянно будет двигаться в одно напровление очень мала, типа теоретически думаю это самым оптимальным решением для моей конкретной задачи и перенос массива как уже предлагали делать процедурой move
п.с.
Сечас только что с работы пришел, проверю по позже, если у кого еще мысли появяться то выкладывайте не стесняйтесь ;-)
Sapersky (2006-03-21 13:18:00) [6]Чтобы меньше двигать массив при добавлении в начало, можно выделить сначала некоторый объём и добавлять элементы начиная со середины, отслеживая начальный и конечный индексы; если не влезает - перевыделять память блоками, на несколько элементов сразу.
Можно и списком.
Amoeba (2006-03-21 11:47:00) [7]
> 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, ни приведенного тобой кода, и вся процедура целикос на ассемблере.
Delphi5.01 (2006-03-21 09:09:00) [8]п.с. Как я понимаю здесь на форуме раздел "Начинающим" зашифрован, вот только что видел топик с названием "Динамическая память" ну как можно такой топик отнести к начинающим? Что тогда надо писать в "Основная". Скоро в разделе "Начинающим" появиться вопросы, как можно реализовать Х проблему используя Turbo Assembler :-)
Delphi5.01 (2006-03-21 08:58:00) [9]SergP
Согласен что сделано как я понимаю банально циклом, вот только думаю что у этого метода преимущества с банальным перемещением никакого :-( если я точно понимаю что есть структура PChar (это стоковой параметр с нулевым символом в конце).
Полюбому надо что-то на уровне указателей. Вот что мне пришло в голову пока я данный топик создал. Если каждый элемент массива как структура LinkList то можно довольно легко добавлять новый элемент в начало и конец массива указав элементу массива что следующий элемент находиться по такому адресу. Но для этого надо понять как устроен массив и есть ли у меня возможность вмешиваться на такой низкий уровень ...
Есть ли у кого идеи?
SergP. (2006-03-21 05:18:00) [10]
> я вообше хотел вопрос в 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 04:40:00) [11]Ок одинм словом многие высказывания в постах 11, 12, 13 принимаю, возможно зря я вообше завелся переносом ветки, но всеже мое ИМХО тему не надо было переносить, я вообше хотел вопрос в API задать так как знал что для этого возможно придеться воспользоваться некой API функцией.
п.с. Я как подумал мне больше не понравился пост который приравнивал меня с начинающим ламаком :-) Млин я же не говорю что я вундеркинд но давно не делетант :-)
Германн (2006-03-21 02:58:00) [12]
> как сделать в РНР или в Java я знаю а вот как с дельфи проблемы
Ну вот лично для меня, вышеуказанная строка - является несомненной причиной переноса в "Начинающие"! Т.е. ты сам иницировал сей перенос своими высказываниями.
Ещё одна причина является в виде Пост-Фактум. Тебе всё-таки помогли, несмотря на перенос (а может и благодаря ему?).
Джо (2006-03-21 02:50:00) [13]... но после прямых оскорблений, я думаю, мнение модератора, если и изменится, то только не в лучшую сторону. И это есть правильно.
SergP. (2006-03-21 02:42:00) [14]
> Delphi5.01 © (20.03.06 14:21) [5]
> п.с. И хотелось увидеть того ... который данный
> топик из общего перенес в начинающим :-) Там же в вопросе
> было написно не предлогать банальные решения а что мне в
> рзаделе для начинающих могут посоветовать, как лудше цикл
> устроить? Ну вы блин даете если новички задают вопросы про
> динамические массивы и работу с ними на уровне адресов то
> что можно ожидать в разделе общие вопросы или даже WinAPI.
> Дело просто в том что вместо тупой сортировки иногда вместо
> Ж подумайте и головой!!! больше 4 лет с этим форумом и такого
> пока еще ни когда не происходило, наверно новых ...
> наняли для сортировки тем
ИМХО как раз дело в том что не новых наняли, а продолжают это делать старые. А у них соответствующие критерии с течением времени меняются...
Но не стоит так все воспринимать, особенно не стоит это воспринимать как оскорбление. Лично мне было бы пофик куда что перенесли. главное чтобы ответили...
Да и часто бывает что топики которые содержат "нормальные" вопросы переносяться в "Новичкам", а топики которые следовало бы туда перенести остаются в основном. Но это мое мнение. Мнение же другого человека (например того же модератора) может быть иное.
Delphi5.01 (2006-03-20 21:57:00) [15]DelphiCity
начнем с того что топик оценивается вопросом а не ответами в нем! Во вторых перед тем как на кого-то наезжать сначала узнай кто он и что он из себя представляет в программировании. Если ты думаешь что кидая кнопки на форму ты программируем то ты глубоко заблужаещся, ты сначала для примера разбери KOL (key object library) и создай в нем компонент, потом можно графику подучить с DirectX-ом, немного сетевых программ напиши, под конец разберись в API функциях (самых распространенных) и вот потом я к твоему совету прислушаюсь.
А то что я не знал о команде move еще ни о чем не говорит :-) В Джаве к примру все сложные структуры и так на уровне пойнтеров в дельфи надо через спец символ обрушаться и у каждого языка свой стиль, так что назубок только не нормальный параноик может учить. Что касается доки то там как всегда не описываться те нюансы о которых могут сказать люди кто с этим уже давно работал, и я подозреваю что к таким людям ты не относишься
Так как флудить в теме кроме самоуверенного любителя ни кто не будет!!!
п.с. Параллельно не буду затрагивать тему создания много потокового режима в PHP в котором такое вообще не реально и должно делаться на уровне операционной системы.
DelphiCity (2006-03-20 18:59:00) [16]
> Delphi5.01 © (20.03.06 14:21) [5]
Данному топику место как раз в «начинающим»
> И вообще как массив устроен в Delphi? вот уже больше 5 лет
> под него программирую а вопрос только сейчас возник
ну и чем можно было 5 лет заниматься, не зная элементарных вещей, тот же move который еще в школе проходят(серьезно), и не уметь пользоваться справкой?
Delphi5.01 (2006-03-20 17:17:00) [17]Da zabil dobavit chto massiv budet record tipa. Dumau eto ne doljno povlech problem
Delphi5.01 (2006-03-20 17:16:00) [18]Bolshoe spasibo za pmosh GuAV, teper budu eksperementirovat.
GuAV (2006-03-20 14:39:00) [19]Доб в начало:
Если массив не содердит типы с управляемым временем жизни (т.е. анси строки, другие дин массивы, варианты, интерфейсы), то SetLength + Move + доб в начало.
Если содержит, то код немного усложняется - нужно явно финализировать последний элемент до замещения, и обнулить без финализации первый.
Доб в конец тривиально.
> Учти, что вызов SetLength в любом случае повлечет за
> собой реаллокацию памяти под массив.
Может полечь а может и не повлечь. Но таки в любом случае.
Delphi5.01 (2006-03-20 14:21:00) [20]Спасибо за помощь
п.с. И хотелось увидеть того придурка админа который данный топик из общего перенес в начинающим :-) Там же в вопросе было написно не предлогать банальные решения а что мне в рзаделе для начинающих могут посоветовать, как лудше цикл устроить? Ну вы блин даете если новички задают вопросы про динамические массивы и работу с ними на уровне адресов то что можно ожидать в разделе общие вопросы или даже WinAPI. Дело просто в том что вместо тупой сортировки иногда вместо Ж подумайте и головой!!! больше 4 лет с этим форумом и такого пока еще ни когда не происходило, наверно новых придурков наняли для сортировки тем