Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.55 MB
Время: 0.028 c
2-1143089815
Der Nechk@ssoff
2006-03-23 07:56
2006.04.09
Календарь


2-1143091143
Nsk3D
2006-03-23 08:19
2006.04.09
Filter


2-1143047641
Adios
2006-03-22 20:14
2006.04.09
вопрос насчёт других приложений


1-1141496116
DR0N
2006-03-04 21:15
2006.04.09
Перехват PAINT панели.


3-1139495221
antoxa2005
2006-02-09 17:27
2006.04.09
Возможно ли получить значение св-ва "Описание" таблицы Access