Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.04.09;
Скачать: [xml.tar.bz2];

Вниз

добавить элемент в динамический массив в начало и в конец   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.014 c
4-1137700717
AlexOld
2006-01-19 22:58
2006.04.09
Программирование USB порта


2-1143275526
Alex7
2006-03-25 11:32
2006.04.09
????????????


2-1143184401
mmms
2006-03-24 10:13
2006.04.09
Здравствуйте! Простите за простой вопрос, не могу преобразовать


2-1143273355
Vitalik__
2006-03-25 10:55
2006.04.09
Если экран с крупным шрифтом - на форме всё налазит друг на друга


15-1142407750
Alex.
2006-03-15 10:29
2006.04.09
Enterprise Manager для Oracle 10 g





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский