|
Вопрос # 4 817/ вопрос открыт / |
|
Здравствуйте!
ок. хочу получить возможность работать со вложенными открытыми массивами, вроде такого:
[ 'a', ['b','c'], ['d',['e','f'],'g'], 'h' ]
при этом желательно, чтобы это был массив array of const
собственно вопросы возникли по статье:
http://www.delphisources.ru/pages/fa..._of_const.html
Приложение: Переключить в обычный режим-
- type
- ArrayOfConst = array of TVarRec;
- TArrayOfConst = array [ 0 .. High (WORD) div SizeOf (TVarRec) - 1 ] of TVarRec;
- PArrayOfConst = ^TArrayOfConst;
-
- function PArrayOfConstMerge (anArgs1, anArgs2: array of const) : PArrayOfConst;
- var
- I : WORD;
- Index : WORD;
- Length : WORD;
- begin
- Result := NIL;
- try
- Length := 0;
- if ( High (anArgs1) >= 0 ) then
- Length := Length + High (anArgs1) - Low (anArgs1) +1;
- if ( High (anArgs2) >= 0 ) then
- Length := Length + High (anArgs2) - Low (anArgs2) +1;
- if ( Length > 0 ) then
- begin
- Result := AllocMem ( Length * SizeOf (TVarRec) );
- Index := 0;
- for I := Low (anArgs1) to High (anArgs1) do
- begin
- Result^ [Index] := anArgs1 [i];
- Inc (Index);
- end;
- for I := Low (anArgs2) to High (anArgs2) do
- begin
- Result^ [Index] := anArgs2 [i];
- Inc (Index);
- end;
- end;
- except
- Result := NIL;
- end;
- end;
-
- function ArrayOfConstMerge (anArgs1, anArgs2: array of const) : ArrayOfConst;
- var
- I : WORD;
- Index : WORD;
- Length : WORD;
- begin
- Result := NIL;
- try
- Length := 0;
- if ( High (anArgs1) >= 0 ) then
- Length := Length + High (anArgs1) - Low (anArgs1) +1;
- if ( High (anArgs2) >= 0 ) then
- Length := Length + High (anArgs2) - Low (anArgs2) +1;
- if ( Length > 0 ) then
- begin
- SetLength (Result,Length);
- Index := 0;
- for I := Low (anArgs1) to High (anArgs1) do
- begin
- Result [Index] := anArgs1 [i];
- Inc (Index);
- end;
- for I := Low (anArgs2) to High (anArgs2) do
- begin
- Result [Index] := anArgs2 [i];
- Inc (Index);
- end;
- end;
- except
- Result := NIL;
- end;
- end;
-
- function PointerToArrayOfConst (anArgs: array of const) : PArrayOfConst;
- var
- I : WORD;
- Index : WORD;
- Length : WORD;
- begin
- Result := NIL;
- try
- Length := 0;
- if ( High (anArgs) >= 0 ) then
- Length := Length + High (anArgs) - Low (anArgs) +1;
- if ( Length > 0 ) then
- begin
- Result := AllocMem ( Length * SizeOf (TVarRec) );
- Index := 0;
- for I := Low (anArgs) to High (anArgs) do
- begin
- Result^ [Index] := anArgs [i];
- Inc (Index);
- end;
- end;
- except
- Result := NIL;
- end;
- end;
-
-
-
- function f1 (anArgs: array of const) : String;
- var
- I : Integer;
- begin
- Result := '';
- for I := Low (anArgs) to High (anArgs) do
- Result := Format ('%s:%s',[ Result, ParamToStr (anArgs [i]) ]);
- end;
-
- function f2 (anArgs: array of const) : String;
- begin
- Result := f1 ( ArrayOfConstMerge (anArgs,['test','testtest','yo-ho','hi-hi','laaa']) );
- end;
-
- function arrays (anArgs: array of const) : String;
- var
- I : Integer;
- P : PArrayOfConst;
- begin
- Result := '';
- for I := Low (anArgs) to High (anArgs) do
- begin
- P := ParamToPointer (anArgs [i]);
- if Assigned (P) then
- Result := Format ('%s;%s',[ Result, f1 ( PointerToArrayOfConst (P) ) ])
- else
- Result := Format ('%s;%s',[ Result, ParamToStr (anArgs [i]) ]);
- end;
- end;
-
- s := arrays ( [ 'a', _const (['hello','world','test1']), 1, _const (['test2','test3']), _const ([])
] );
-
-
- ;a;:hello:world:test1;1;:test2:test3;0
-
-
-
- function _const (anArgs: PArrayOfConst) : ArrayOfConst;
- var
- ArrayOfConstCallAlias : procedure (var Result: ArrayOfConst; var anArgs: TVarRec; High: WORD);
- I : WORD;
- A : ArrayOfConst;
-
- procedure ArrayOfConstCall (var Result: ArrayOfConst; anArgs: array of const);
- var
- I : WORD;
- Index : WORD;
- Length : WORD;
- begin
- Result := NIL;
- try
- Length := 0;
- if ( High (anArgs) >= 0 ) then
- Length := Length + High (anArgs) - Low (anArgs) +1;
- if ( Length > 0 ) then
- begin
- SetLength (Result,Length);
- Index := 0;
- for I := Low (anArgs) to High (anArgs) do
- begin
- Result [Index] := anArgs [i];
- Inc (Index);
- end;
- end;
- except
- Result := NIL;
- end;
- end;
-
- begin
- Result := NIL;
- try
- @ArrayOfConstCallAlias := @ArrayOfConstCall;
- I := 0;
- while ( I < H ) do
- begin
- ArrayOfConstCallAlias ( A, anArgs^ [i], SizeOf (anArgs) div SizeOf (TVarRec) );
- if ( I = 0 ) then
- Result := A
- else
- Result := ArrayOfConstMerge (Result,A);
- Inc (I);
- end;
- except
- Result := NIL;
- end;
- end;
 |
Вопрос задал: mirt.steelwater (статус: Посетитель)
Вопрос отправлен: 14 декабря 2010, 09:55
Состояние вопроса: открыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 8; последнее сообщение — 16 декабря 2010, 13:20; участников в обсуждении: 2.
|
Вадим К (статус: Академик), 14 декабря 2010, 10:36 [#1]:
хочется массивы произвольной вложенности?
p.s. ссылка на в вопросе битая.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
mirt.steelwater (статус: Посетитель), 14 декабря 2010, 12:18 [#2]:
да, произвольной вложенности
ссылка побилась видимо(
я частично реализовал эту задачу вот так:
function _const (anArgs: array of const) : ArrayOfConst;
var
I : WORD;
Index : WORD;
Length : WORD;
begin
Length := 0;
if ( High (anArgs) >= 0 ) then
Length := Length + High (anArgs) - Low (anArgs) +1;
if ( Length > 0 ) then
begin
SetLength (Result,Length);
Index := 0;
for I := Low (anArgs) to High (anArgs) do
begin
Result [Index] := anArgs [I];
Inc (Index);
end;
end;
end;
function ParamToArrayOfConst (const aValue: TVarRec) : ArrayOfConst;
begin
Result := _const([]);
with aValue do
try
case VType of
vtPointer: Result := VPointer;
end;
except
Result := _const([]);
end;
end;
и теперь могу обходить массив вот так:
function arrays (anArgs: array of const) : String;
var
I : WORD;
A : ArrayOfConst;
begin
Result := '';
for I := Low (anArgs) to High (anArgs) do
begin
A := ParamToArrayOfConst (anArgs [I]);
if Assigned (A) then
begin
if ( I <= Low (anArgs) ) then
Result := arrays (A)
else
Result := Format ('%s, %s',[ Result, arrays (A) ]);
end
else if ( I <= Low (anArgs) ) then
Result := ParamToStr (anArgs [I])
else
Result := Format ('%s, %s',[ Result, ParamToStr (anArgs [I]) ]);
end;
Result := Format ('[%s]',[Result]);
end;
caption := arrays ([ 'a', _const(['test1']), 'b', _const(['test2','test3']), 'c', Pointer(TForm), NIL, self,
_const(['test4','test5','test6', _const(['A','B','C']), 'test7' ]), 'hello', 3.14159265 ]);
все работает, но возникает исключение, которое нельзя корректно обработать, если я передам Pointer (Form1) , например - процедуры пытается получить в этом случае из указателя массив и все плохо заканчивается
Ⓐ свобода сопротивление солидарность
|
|
mirt.steelwater (статус: Посетитель), 14 декабря 2010, 12:35 [#3]:
забыл описание функции
function ParamToStr (const aValue: TVarRec) : String;
begin
Result := '';
with aValue do
try
case VType of
vtInteger: Result := IntToStr (VInteger);
vtBoolean: Result := BooleanToStr (VBoolean);
vtChar: Result := VChar;
vtExtended: Result := FloatToStr (VExtended^);
vtString: Result := VString^;
vtPointer: Result := IntToStr ( Longint (VPointer) );
vtPChar: Result := StrPas (VPChar);
vtObject: Result := VObject.ClassName;
vtClass: Result := VClass.ClassName;
vtAnsiString: Result := String (VAnsiString);
vtWideChar: Result := Char (VWideChar);
vtPWideChar: Result := WideCharToString (VPWideChar);
vtWideString: Result := WideCharToString (VWideString);
vtCurrency: Result := FloatToStr (VCurrency^);
vtInt64: Result := IntToStr (VInt64^);
vtVariant: Result := VVariant^;
end;
except
Result := '';
end;
end;
Ⓐ свобода сопротивление солидарность
|
|
Вадим К (статус: Академик), 14 декабря 2010, 12:47 [#4]:
Я правильно понимаю, хочется сделать фактически питоновские типы?
Цитата:
если я передам Pointer (Form1) , например - процедуры пытается получить в этом случае из указателя массив и все плохо заканчивается
логично. указатель не хранит информацию о типе. Варианты решения:
- специфицировать, что произвольные указатели нельзя передавать. А в коде сделать try except, который просто будет возвращаться с процедуры или вообще закрывать программу, выдав отладочные сообщения.
- построить костыли и попытаться научиться угадывать тип указателя (и получить самые феерические ошибки)
- помещать в массив данные специального типа - variant
- помещать в массив данные своего типа. если делфи старше 2005-2007, то можно даже написать специальные методы, что бы сделать работу прозрачной.
- устроится на работу в Embracadero и поправить багу в компиляторе
- перейти на другой язык программирования
Галочка "подтверждения прочтения" - вселенское зло.
|
|
mirt.steelwater (статус: Посетитель), 14 декабря 2010, 15:56 [#5]:
спасибо
я отел вначале использовать типизированные указатели, но array of const четко содержит ссылку именно на такой вариант TVarRec - с нетипизированным указателем.
вариант с обработкой ошибки меня бы устроил, я собственно, и думал так сделать:
try
...
except
Result := _const([]);
end; в ряде случаев там возникают ошибки, которые покидают блок except - вероятно все из-за того же Acces Violation - можно ли как-нибудь хранить в указателе его тип и читать его на низком уровне? как-то это ведь работает с типизированными указателями дельфи?
однако
Ⓐ свобода сопротивление солидарность
|
|
Вадим К (статус: Академик), 14 декабря 2010, 17:19 [#6]:
указатель на то и указатель, что там только 4 байта данных - только адрес. Поэтому наверно придется заводить ассоциативный массив для указателей и помнить их тип. Но кому это нужно. Делфи в целом не различает указателей. Основная работа проводиться ещё на уровне компиляции.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
mirt.steelwater (статус: Посетитель), 16 декабря 2010, 13:03 [#7]:
>>Я правильно понимаю, хочется сделать фактически питоновские типы?
да
Ⓐ свобода сопротивление солидарность
|
|
Вадим К (статус: Академик), 16 декабря 2010, 13:20 [#8]:
Это очень плохая практика - писать в одном языке методами другого. Нужно просто искать правильный путь реализации идеи. А для этого иногда нужно менять алгоритмы и мировоззрение.
Говоря по простому - "со своим чайником в Тулу не едут "
Галочка "подтверждения прочтения" - вселенское зло.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|