![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Размер динамического массива
learner © (2006-09-06 17:22:00)Здравствуйте !
Type
TMyArray = array of integer;
TMyDblArray = array of TMyArray;
Как можно узнать "истинный" размер переменной типа TMyDblArray ?
Типа: Length(MyArr)*Length(MyArr[0])*SizeOf(integer) + "еще что-то";
default (2006-09-07 18:44:00) [1]learner © (07.09.06 18:31) [9]
а чего тебе хотелось?
к чему Palladin тут раскодировался?
learner (2006-09-07 18:31:00) [2]>Palladin © (06.09.06 22:37) [8]
Спасибо за "фух... " :))
Оказывается, для некоторых, верно утверждение:
"Если нельзя, но очень хочется, то - можно" :))
Palladin (2006-09-06 22:37:00) [3]фух... :)
в случае n-мерноугольного массива
Type
ExDimDimOutOfARange=Class(Exception);
ExDimOutOfARange=Class(Exception);
TxDPoint=Array of Cardinal;
TxDIntArray=Class
Private
m_nShift:Cardinal;
m_aData:Array of Integer;
m_aDims:TxDPoint;
m_nSize:Cardinal;
m_bNoRangeCheck:Boolean;
Function lcGetItem(Const p_axDPoint:TxDPoint):Integer;
Procedure lcSetItem(Const p_axDPoint:TxDPoint;p_nValue:Integer);
Procedure lcCalcShift(Const p_axDPoint:TxDPoint);
Function lcGetPointer:Pointer;
Public
Constructor Create(Const p_axDims:TxDPoint);
Constructor CreateFrom(p_theOtherArray:TxDIntArray);
Destructor Destroy; Override;
Property Item[Const axDPoint:TxDPoint]:Integer Read lcGetItem Write lcSetItem; Default;
Property NoRangeCheck:Boolean Read m_bNoRangeCheck Write m_bNoRangeCheck;
Property Memory:Pointer Read lcGetPointer;
Property Size:Cardinal Read m_nSize;
Property Dims:TxDPoint Read m_aDims;
Class Function xDPoint(xDP:Array of Cardinal):TxDPoint; Overload;
Class Procedure xDPoint(xDP:Array of Cardinal;Var vxDP:TxDPoint); Overload;
End;
Destructor TxDIntArray.Destroy;
Begin
m_aDims:=Nil;
m_aData:=Nil;
End;
Function TxDIntArray.lcGetItem;
Begin
lcCalcShift(p_axDPoint);
Result:=m_aData[m_nShift];
End;
Procedure TxDIntArray.lcSetItem;
Begin
lcCalcShift(p_axDPoint);
m_aData[m_nShift]:=p_nValue;
End;
Procedure TxDIntArray.lcCalcShift;
Var
i:Integer;
Begin
If Not m_bNoRangeCheck Then
Begin
If Length(m_aDims)<>Length(p_axDPoint) Then Raise ExDimDimOutOfARange.Create(IntToStr(Length(p_axDPoint))+','+IntToStr(Length(m_aDims)));
For i:=0 to Length(m_aDims)-1 Do
If m_aDims[i]<=p_axDPoint[i] Then
Raise ExDimOutOfARange.Create('Dimension '+IntToStr(i)+', Size='+IntToStr(m_aDims[i])+', Request='+IntToStr(p_axDPoint[i]));
End;
m_nShift:=0;
For i:=0 to Length(p_axDPoint)-1 Do m_nShift:=m_nShift+m_aDims[i]*p_axDPoint[i];
End;
Function TxDIntArray.lcGetPointer;
Begin
If m_nSize=0 Then Result:=Nil Else Result:=@m_aData[0];
End;
Constructor TxDIntArray.Create;
Begin
m_bNoRangeCheck:=True;
If Length(p_axDims)=0 Then
Begin
m_nSize:=0;
m_aData:=Nil;
m_aDims:=Nil;
End Else
Begin
SetLength(m_aDims,Length(p_axDims));
Move(p_axDims[0],m_aDims[0],Length(p_axDims)*SizeOf(Cardinal));
lcCalcShift(p_axDims);
SetLength(m_aData,m_nShift);
m_nSize:=m_nShift;
End;
End;
Constructor TxDIntArray.CreateFrom;
Begin
m_bNoRangeCheck:=True;
If p_theOtherArray.Size=0 Then
Begin
m_nSize:=0;
m_aData:=Nil;
m_aDims:=Nil;
End Else
Begin
m_nSize:=p_theOtherArray.Size;
SetLength(m_aData,m_nSize);
Move(p_theOtherArray.Memory^,m_aData[0],m_nSize);
SetLength(m_aDims,Length(p_theOtherArray.Dims));
Move(p_theOtherArray.Dims[0],m_aDims[0],Length(m_aDims)*SizeOf(Cardinal));
End;
End;
Class Function TxDIntArray.xDPoint(xDP:Array of Cardinal):TxDPoint;
Begin
SetLength(Result,Length(xDP));
Move(xDP[0],Result[0],Length(xDP));
End;
Class Procedure TxDIntArray.xDPoint(xDP:Array of Cardinal;Var vxDP:TxDPoint);
Begin
SetLength(vxDP,Length(xDP));
Move(xDP[0],vxDP[0],Length(xDP));
End;
пример:
Var
a,b:TxDIntArray;
nxDPoint:TxDPoint;
begin
TxDIntArray.xDPoint([100,40,5,5,5],nxDPoint);
a:=TxDIntArray.Create(nxDPoint);
a[a.xDPoint([1,5,2,1,1])]:=500;
ShowMessage('a[1,5,2,1,1] = '+IntToStr(a[a.xDPoint([1,5,2,1,1])]));
b:=TxDIntArray.CreateFrom(a);
a[a.xDPoint([1,5,2,1,1])]:=501;
ShowMessage('b[1,5,2,1,1] = '+IntToStr(b[a.xDPoint([1,5,2,1,1])])+' a[1,5,2,1,1] = '+IntToStr(a[a.xDPoint([1,5,2,1,1])]) );
a.Free;
b.Free;
end;
guav (2006-09-06 21:10:00) [4]> [3] learner ©
Если нужны "настоящие" многомерные динамические массивы, т.е. динамические по всем размерам и с элементами, лежащими подряд, используй Variant Arrays, см. VarArrayCreate
Anatoly Podgoretsky (2006-09-06 20:31:00) [5]Джо © (06.09.06 17:30) [2]
Неправильно, массив не обязан быть прямоугольным.
Вот у Palladin © (06.09.06 17:27) [1]
правильный ответ.
learner (2006-09-06 19:43:00) [6]>неполучится
"и это очень прискорбно" (ц). :))
Palladin (2006-09-06 17:53:00) [7]
> Хочу воспользоваться CopyMemory без создания цикла
неполучится
каждый элемент TMyDblArray является указателем
learner (2006-09-06 17:44:00) [8]Вот меня и интересует "служебная информация для самого массива".
Хочу воспользоваться CopyMemory без создания цикла
Джо (2006-09-06 17:30:00) [9]> Как можно узнать "истинный" размер переменной типа TMyDblArray
> ?
"Истинный размер" этой переменной равен SizeOf(Pointer). А вот объем памяти, занимаемый самими данными — Length(MyArr) * SizeOf(Integer) * Length(TMyDblArray) . Плюс служебная информация для самого массива.
Palladin (2006-09-06 17:27:00) [10]
Function GetTMyDblSize(a:TMyDblArray):Integer;
Var
i:Integer;
Begin
Result:=0;
For i:=0 to Length(a)-1 Do Inc(Result,Length(a[i])*SizeOf(Integer));
Inc(Result,Length(a)*SizeOf(TMyArray));
End;