Форум: "Основная";
Текущий архив: 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