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

Вниз

Подскажите функцию   Найти похожие ветки 

 
Андрусь   (2002-08-21 12:10) [0]

Привет всем! Такая вот проблемка:работаю с динамическими массивами,объявленными как array of ....Есть ли функция удаления i-го элемента массива(память до этого элемента не трогать,а начиная с данного сдвинуть все элементы на sizeof(type)) байт влево.Зараннее всем большое спасибо!


 
Val   (2002-08-21 12:15) [1]

To truncate a dynamic array, pass it to the Copy function and assign the result back to the array variable. For example, if A is a dynamic array, A := Copy(A, 0, 20) truncates all but the first 20 elements of A.


 
Alx2   (2002-08-21 12:18) [2]

Но надо проверить - не уверен за количество :)
move(a[i+1],a[i],(length(a)-i)*sizeof(a[i]));


 
Alx2   (2002-08-21 12:20) [3]

>Alx2 © (21.08.02 12:18)
Так и есть. Осекся малость.
move(a[i+1],a[i],(length(a)-i-1)*sizeof(a[i]));
а потом:
setlength(a,length(a)-1);


 
Val   (2002-08-21 12:22) [4]

>Alx2 © (21.08.02 12:18)
слышал, что используя move можно получить проблему при работе со строками, не просвятите конктретнее?


 
Alx2   (2002-08-21 12:27) [5]

>Val © (21.08.02 12:22)
А подробнее? Что за проблему?


 
Андрусь   (2002-08-21 12:28) [6]

Вы хотели сказать:скопировал в новую перем до,после,переприсоил старой и порядок,эт понятно.
Тут немного я не договорил. Мне нужна ф-я для дин.массивов разл.типа(все типы в общ. случае не известны(варианты с перебором мне не нравятся)).


 
Alx2   (2002-08-21 12:33) [7]

>Андрусь © (21.08.02 12:28)
А что в моем варианте не нравится?


 
Val   (2002-08-21 12:41) [8]

>Alx2 © (21.08.02 12:27)
потеря данных конечно, при переносе. подробнее не скажу, поскольку слышал где-то краем уха, просто увидел ваш пример и вспомнил(по-моему при копировании record, которая содержит элемент типа строка). возможно связано с некоректным определением их длины и получения вместо нее длины указателя? не знаю, просто хотел спросить, может встречались, с какими особенностями move, где надо быть предельно внимательным?
>Андрусь © (21.08.02 12:28)
все типы в общ. случае не известны
может, использовать Variant? неплхо бы знать задачу.


 
Alx2   (2002-08-21 12:46) [9]

>Val © (21.08.02 12:41)
Тогда достаточно научится корректно работать с адресами. А при перемещении символов в строке помнить, что первый элемент имеет индекс 1, и использование просто S вместо S[1] в таких вещах некорректно.


 
Alx2   (2002-08-21 12:48) [10]

>может, использовать Variant? неплхо бы знать задачу.

описание array of ... уже подразумевает, что элементы массива будут однотипными (пусть, даже, и variant)


 
Андрусь   (2002-08-21 12:51) [11]

>Alx2 © (21.08.02 12:27)
Вариант красив,но Val © (21.08.02 12:41) - настораживает.Будет ли корректно работать,если элемент - класс.

Задача,в принципе излагалась уже.Но повторюсь:нужна процедура, удаляющая элемент из динамического массива. Словами тип не известен,я хотел сказать,что элементами массива являются в основном определённые мной типы. Т.е. процедуру пишу сейчас,а типы не известны.


 
Alx2   (2002-08-21 12:57) [12]

>Андрусь © (21.08.02 12:51)
>Будет ли корректно работать,если элемент - класс.

Будет.
Но если класс, то лучше использовать списки - там все готово.
Иначе до места move(a[i+1],a[i],(length(a)-i-1)*sizeof(a[i])) нужно вызвать a[i].free (если не задумано что-то иное :) ). Но прежде всего нужна проверка на то, что элемент - действительно экземпляр класса.

>Задача,в принципе излагалась уже.Но повторюсь:нужна процедура,
>удаляющая элемент из динамического массива. Словами тип не
>известен,я хотел сказать,что элементами массива являются в
>основном определённые мной типы. Т.е. процедуру пишу сейчас,а
>типы не известны.

Единственная несложная сложность - освобождение памяти, занятой удаляемым из массива элементом (если это нужно, конечно) (см. выше).


 
Alx2   (2002-08-21 13:02) [13]

>Alx2 © (21.08.02 12:57)
Сорри, вот так, конечно
(a[i] as TObject).free или TObject(a[i]).free


 
Alx2   (2002-08-21 13:09) [14]

Единственно, как такие массивы передавать в качестве параметра в общую процедуру с сохранением информации о типе?
Думаю, для полноценного решения задачи все-таки подойдет вместо массива тип variant с дальнейшим анализом его содержимого :(


 
Андрусь   (2002-08-21 13:28) [15]

Хорошо,если у меня array of MyRecord?


 
Андрусь   (2002-08-21 13:51) [16]

Как там вариант использовать,чего-то не доезжаю..


 
Alx2   (2002-08-21 14:01) [17]

>Андрусь © (21.08.02 13:28)
>Хорошо,если у меня array of MyRecord?
Все равно спасет мой вариант без изменений (sizeof(a[i]) даст то, что надо), или тот же Delete.
>Как там вариант использовать,чего-то не доезжаю
см. :

{ Variant type codes (wtypes.h) }

varEmpty = $0000; { vt_empty 0 }
varNull = $0001; { vt_null 1 }
varSmallint = $0002; { vt_i2 2 }
varInteger = $0003; { vt_i4 3 }
varSingle = $0004; { vt_r4 4 }
varDouble = $0005; { vt_r8 5 }
varCurrency = $0006; { vt_cy 6 }
varDate = $0007; { vt_date 7 }
varOleStr = $0008; { vt_bstr 8 }
varDispatch = $0009; { vt_dispatch 9 }
varError = $000A; { vt_error 10 }
varBoolean = $000B; { vt_bool 11 }
varVariant = $000C; { vt_variant 12 }
varUnknown = $000D; { vt_unknown 13 }
//varDecimal = $000E; { vt_decimal 14 } {UNSUPPORTED as of v6.x code base}
//varUndef0F = $000F; { undefined 15 } {UNSUPPORTED per Microsoft}
varShortInt = $0010; { vt_i1 16 }
varByte = $0011; { vt_ui1 17 }
varWord = $0012; { vt_ui2 18 }
varLongWord = $0013; { vt_ui4 19 }
varInt64 = $0014; { vt_i8 20 }
//varWord64 = $0015; { vt_ui8 21 } {UNSUPPORTED as of v6.x code base}
{ if adding new items, update Variants" varLast, BaseTypeMap and OpTypeMap }

varStrArg = $0048; { vt_clsid 72 }
varString = $0100; { Pascal string 256 } {not OLE compatible }
varAny = $0101; { Corba any 257 } {not OLE compatible }
// custom types range from $110 (272) to $7FF (2047)

varTypeMask = $0FFF;
varArray = $2000;
varByRef = $4000;

{ TVarRec.VType values }

vtInteger = 0;
vtBoolean = 1;
vtChar = 2;
vtExtended = 3;
vtString = 4;
vtPointer = 5;
vtPChar = 6;
vtObject = 7;
vtClass = 8;
vtWideChar = 9;
vtPWideChar = 10;
vtAnsiString = 11;
vtCurrency = 12;
vtVariant = 13;
vtInterface = 14;
vtWideString = 15;
vtInt64 = 16;

{ Virtual method table entries }

vmtSelfPtr = -76;
vmtIntfTable = -72;
vmtAutoTable = -68;
vmtInitTable = -64;
vmtTypeInfo = -60;
vmtFieldTable = -56;
vmtMethodTable = -52;
vmtDynamicTable = -48;
vmtClassName = -44;
vmtInstanceSize = -40;
vmtParent = -36;
vmtSafeCallException = -32;
vmtAfterConstruction = -28;
vmtBeforeDestruction = -24;
vmtDispatch = -20;
vmtDefaultHandler = -16;
vmtNewInstance = -12;
vmtFreeInstance = -8;
vmtDestroy = -4;

vmtQueryInterface = 0;
vmtAddRef = 4;
vmtRelease = 8;
vmtCreateObject = 12;



 
Андрусь   (2002-08-21 14:22) [18]

Всё равно не понял как вариант к Myrec привязать.Как из него тип узнать typeof(p) не работает.Да и не красиво как-то у меня получается...

Procedure Delete_Element(p:variant; i: integer);
var a1:TMyrecArray1;a2:TMyrecArray2;
Begin
If typeof(p) is TMyrecArray1 Then
Begin
move(a1[i+1],a1[i],(length(a1)-i-1)*sizeof(a1[i]));
setlength(a1,length(a1)-1);
End
Else if typeof(p) is TMyrecArray2 Then
Begin
move(a2[i+1],a2[i],(length(a2)-i-1)*sizeof(a2[i]));
setlength(a2,length(a2)-1);
End;
End;


 
Alx2   (2002-08-21 14:33) [19]

Вот этого хватит на оба случая:
move(a1[i+1],a1[i],(length(a1)-i-1)*sizeof(a1[i]));
setlength(a1,length(a1)-1);


 
Андрусь   (2002-08-21 15:45) [20]

Не понял - поправь мой пример,бо не работает.Тип не разделяется..


 
Alx2   (2002-08-21 16:02) [21]

>Андрусь © (21.08.02 15:45)
Что-то у тебя напахано нехорошее. Я имел ввиду следущее:

var a1:TMyrecArray1;a2:TMyrecArray2;
Begin
move(a1[i+1],a1[i],(length(a1)-i-1)*sizeof(a1[i]));
setlength(a1,length(a1)-1);

move(a2[i+1],a2[i],(length(a2)-i-1)*sizeof(a2[i]));
setlength(a2,length(a2)-1);
End;

А реализация с типом variant скорее всего заткнется на пользовательских типах.
Но есть еще идеи:
делаем процедуру Delete_что-то_там, параметром в которую пойдет указатель на твой массив (пусть даже как безтиповая переменная), количество элементов в нем, размер одного элемента. На основании этих данных легко получить искомое :)


 
Alx2   (2002-08-21 17:04) [22]

>Андрусь © (21.08.02 15:45)
Получилось именно для динамических массивов.

UniversalDelete(Var Arr; ArrSize : Integer; ElemSize, DeleteIdx : Integer);
Var
Source, Dest : Integer;
DummyArr : array of char absolute Arr;
Begin
ArrSize := ArrSize * ElemSize;
Source := (DeleteIdx+1)*ElemSize;
Dest := Source-ElemSize;
Move(DummyArr[Source],DummyArr[Dest],ArrSize-(DeleteIdx+1)*ElemSize);
SetLength(DummyArr,ArrSize div ElemSize - 1);
End;


Пример использования:
Var
SS : array of integer;
begin
setlength(SS,10);

for k := 0 to 9 do SS[k] := (k);

UniversalDelete(SS,Length(SS),SizeOf(SS[0]),2);
Первый параметр - массив.
Второй - количество элементов в нем
Третий - размер одного элемента массива
Четвертый - номер удаляемого элемента (считая с нуля).

PS.
Будь осторожен. Написано в черновую, хоть глюков пока не замечено (но потенциально может испортить работу менеджера памяти - надо проверить)


 
Андрусь   (2002-08-21 19:45) [23]

Что-то не работает.


 
Alx2   (2002-08-22 08:15) [24]

>Андрусь © (21.08.02 19:45)
>Что-то не работает
Пример (и не только этот) работает точно.
Напиши что именно не работает. С примером кода.


 
Андрусь   (2002-08-22 10:56) [25]

Пишу вот такой код,один в один сдуваю у тебя - код красивый не спорю,у самого такие же мысли были. НО...На второй месседж выдаёт
такую строку:0,1,2,4634116,12656560,4148,7,8,9.

Procedure TForm1.Delete_Element(Var Arr; ArrSize : Integer; ElemSize, DeleteIdx : Integer);
Var
Source, Dest : Integer;
DummyArr : array of char absolute Arr;
Begin
ArrSize := ArrSize * ElemSize;
Source := (DeleteIdx+1)*ElemSize;
Dest := Source-ElemSize;
Move(DummyArr[Source],DummyArr[Dest],ArrSize-(DeleteIdx+1)*ElemSize);
SetLength(DummyArr,ArrSize div ElemSize - 1);
End;

procedure TForm1.Button1Click(Sender: TObject);
const del=3;
n=10;
var SS:array of integer;i:integer;

procedure ShowArray(s:string);
var j:integer;s1:string;
Begin
s1:="";
For j:=0 To Length(SS)-1 Do
s1:=s1+#10+" a["+IntToStr(j)+"]="+IntToStr(SS[j]);
ShowMessage(s+" удаляли "+IntToStr(del)+#10+s1);
End;

begin
SetLength(SS,n);
For i:=0 To n-1 Do SS[i]:=i;
ShowArray("Begin");
Delete_Element(SS,Length(SS),SizeOf(SS[0]),del);
ShowArray("End");
end;


 
Alx2   (2002-08-22 11:11) [26]

Да. Та самая проблема с менеджером памяти.
Надо подумать.


 
Андрусь   (2002-08-22 12:46) [27]

Что-то вот конструкция DummyArr : array of char absolute Arr;немного навевает опасения - каков размер этого массива,я посмотрел под дебагером - его размер равен размеру Arr.Видимо придётся делать через указатели.


 
Андрусь   (2002-08-22 12:57) [28]

А вот так работает:

Var
Source, Dest : Integer;
// DummyArr : array of char absolute Arr;
p_source,p_dest:pointer;
Begin
ArrSize := ArrSize * ElemSize;
Source := (DeleteIdx+1)*ElemSize;
Dest := Source-ElemSize;
p_dest:=Pointer(Integer(Arr)+Dest);
p_source:=Pointer(Integer(Arr)+Source);
Move(p_source^,p_dest^,ArrSize-(DeleteIdx+1)*ElemSize);
SetLength(..);
End;

Только вот что делать с SetLength(..)?


 
Alx2   (2002-08-22 14:10) [29]

>Только вот что делать с SetLength(..)?
Поэтому и был dummy :(


 
Андрусь   (2002-08-22 15:24) [30]

В принципе можно поставить DynArraySetLength,но не очень красиво получится.


 
Alx2   (2002-08-22 17:08) [31]

>Андрусь © (22.08.02 15:24)
В твоей ветке про SetLength Ученик дал корректное решение.
А все-таки, если принять во внимание описанную тобоу задачу, лучше использовать списки объектов (или объект-список).
Если жесткая оптимизация - то статические структуры.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2002.09.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.008 c
14-3619
MeamoryLeak
2002-08-06 14:08
2002.09.02
Непростая задачка... кому интересно...


1-3460
A7exander
2002-08-20 17:54
2002.09.02
Добавить кнопку


7-3640
Arkady
2002-06-22 08:16
2002.09.02
Печать


14-3599
SPeller
2002-08-05 20:31
2002.09.02
Опять РНР


3-3266
Loco
2002-08-12 14:25
2002.09.02
Поиск





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский