Форум: "Начинающим";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];
ВнизУнифицированный способ сравнивать массивы? Найти похожие ветки
← →
alex_ant © (2007-09-30 17:15) [0]Пишу тесты модулей, часто возникает необходимость сравнивать два динамических массива на идентичность. Пока что тупо сравниваю поэлементно. Можно ли в Delphi реализовать некую функцию, которая бы сравнивала два массива на идентичность, вне зависимости от типа содержащихся в них элементов, чтобы можно было эту функцию использовать и для сравнения массивов строк, массивом чисел и т. д.?
К примеру, в Perl существует возможность сравнить массивы любого типа на идентичность, передав ссылки на них в качестве параметра в одну унифицированную функцию. Далее функция сама выясняет их типизацию и размерность, и возвращает истину, если количество элементов и их тип и значение совпадают. Можно ли так же в Delphi сделать?
Заранее благодарю за советы.
← →
alex_ant © (2007-09-30 17:23) [1]Понял тут, что вопрос фактически является вопросом о возможности сравнить переменную любого типа (объект, массив, запись и пр.) с любой другой переменной...
Типа
if MegaEqual(PVarA, PVarB: Pointer) then
ShowMessage("Переменные равны");
else
ShowMessage("Переменные не равны");
где PVarA, PVarB — указатели на переменные любого типа.
P. S. Не судите строго, если что-то не так, с указателями работал очень мало.
← →
Dib@zol © (2007-09-30 17:25) [2]В принципе да, если в каждом массиве переменные идут последовательно. Тогда их можно представить как два здоровенных массива байт и сравнивать побайтно...
← →
alex_ant © (2007-09-30 17:36) [3]
> В принципе да, если в каждом массиве переменные идут последовательно.
> Тогда их можно представить как два здоровенных массива
> байт и сравнивать побайтно...
>
А как это можно сделать? Можете показать небольшой пример?
← →
tesseract © (2007-09-30 17:48) [4]Xor по размеру массива?
← →
Dib@zol © (2007-09-30 17:52) [5]Хз. Вот щас только что написал. Не тестировал, но теоретически должно сработать. Len - это длина большего из массивов. Находится с помощью length(Массив). Через Пойнтер её не получить. А, да - если один из массивов короче чем Len, то либо возникнет AV, либо продолжение массива будет случайным образом браться из памяти.
function MegaCompare(A, B : Pointer; Len:Cardinal):boolean;
var
b1, b2 : Byte;
i, k : Cardinal;
begin
Result:=true;
k:=Len-1;
for i:=0 to k do begin
CopyMemory(@b1, Pointer(longInt(A)+i), 1);
CopyMemory(@b2, Pointer(longInt(B)+i), 1);
if b1<>b2 then begin
Result:=false;
break;
end;
end;
end;
← →
vpbar © (2007-09-30 17:57) [6]
procedure TForm1.Button1Click(Sender: TObject);
function Сompare(a,b:pointer;sizeOfElement:byte):Boolean;
var La,Lb,j:integer;
ca,cb:Pchar;
begin
result:=false;
if (a=nil)or(b=nil)then exit;
La:=PInteger(Integer(a)-4)^*sizeOfElement;
Lb:=PInteger(Integer(b)-4)^*sizeOfElement;
if La<>Lb then exit;
Ca:=Pchar(a);
Cb:=Pchar(b);
result:=CompareMem(a,b,La)
end;
var x,y:array of byte;
i:integer;
begin
SetLength(x,3);
for i:=low(x) to High(x) do x[i]:=(i+1);
SetLength(y,3);
for i:=low(y) to High(y) do y[i]:=(i+1);
//y[2]:=5;
if compare(x,y,sizeof(x[666])) then
caption:="Равны" else Caption:="Не равны";
end;
compare - сравнивает два динамических массива (можно и строки если вызывать так compare(@s1[1],@s2[1],1)) тип массива должен быть одинаковый. Если элементы массива - суть ссылки на объекты (строки, классы), то естественно не работает.
← →
vpbar © (2007-09-30 17:59) [7]>>Dib@zol © (30.09.07 17:52) [5]
>>Через Пойнтер её не получить.
Гы. А я получил. Вот только размер и тип елемента никак (точнее сложно) ибо он известен только при компиляции.
← →
vpbar © (2007-09-30 18:05) [8]Dib@zol © (30.09.07 17:52) [5]
кстати ваш вариант проще сделать так
function MegaCompare(A, B : Pointer; Len:Cardinal):boolean;
begin
result:=CompareMem(a,b,Len);
end;
← →
Dib@zol © (2007-09-30 18:07) [9]> Гы. А я получил.
Ну и как же? А? Ведь что такое Pointer? Это ссылка на начало (первый байт) блока данных в адресном пространстве проги. И длиться этот блок может хоть до $7FFFFFFF. Так что ты не прав. Допустим есть у нас "голое" содержимое RAM. И есть первый байт (выделен). И как узнать какой байт является последним?-d FFF2:93F1
FFF2:93F0 BF 5C 00 8A 1C F3 A4-33 C0 AB AB 59 5E 1F 1E .\.....3...Y^..
FFF2:9400 56 C5 74 0A 8A 3C F3 A4-AB AB 5E 1F C5 74 02 80 V.t..<....^..t..
FFF2:9410 C9 80 8B F9 F3 A4 FE C9-8A C7 32 FF E8 A7 0C 73 ..........2....s
FFF2:9420 02 8A F9 8A C3 32 DB E8-9C 0C 73 02 8A D9 E8 36 .....2....s....6
FFF2:9430 A4 66 FF 74 12 66 FF 74-12 66 26 8F 06 0A 00 33 .f.t.f.t.f&....3
FFF2:9440 C0 8E D8 66 8F 06 88 00-36 C7 06 2C 03 80 00 36 ...f....6..,...6
FFF2:9450 8E 1E 30 03 36 8C 1E 2E-03 F6 46 FB 01 74 27 36 ..0.6.....F..t"6
FFF2:9460 C5 36 BF 0E C4 7E FC 26-8C 5D 10 4E 4E 89 1C 26 .6...~.&.].NN..&
FFF2:9470 89 .
← →
Dib@zol © (2007-09-30 18:13) [10]> result:=CompareMem(a,b,Len);
Хмм. А вот и решение! Ну ладно, будем считать, что у меня просто показан принцип...
← →
vpbar © (2007-09-30 18:21) [11]Dib@zol © (30.09.07 18:07) [9]
запусти код из [6] . Работает? Хотя в Сompare длина массивов не передается. Истина проверяется практикой (с) Классик.
А по поводу. "Ну и как же?" Посмотри что такое динамический массив и строка. Это адрес блока. А четыре байта перед указателем - это длина блока. (Строка еще нулем заканчивается).
"Ведь что такое Pointer? " -Pointer - это Указатель(Pointer по англ). Т.е. вещь в себе. Pointer - это четыре байта в которых должен содержаться адрес в памяти. А что там по этому адресу - это только творцу(программеру) известно. Может массив, а может объект.
← →
Dib@zol © (2007-09-30 18:37) [12]> [11] vpbar © (30.09.07 18:21)
Через указатель-Pointer-адрес длину получить невозможно, за исключением тех случаев, когда это предусмотрено структурой хранящегося в памяти объекта, на которого поинтер указывает. Все довольны?
← →
Anatoly Podgoretsky © (2007-09-30 18:41) [13]> Dib@zol (30.09.2007 18:37:12) [12]
Нет, поскольку нет никаких методов подтвердить, что указатель указывает на подобную структуру.
← →
vpbar © (2007-09-30 19:00) [14]Dib@zol © (30.09.07 18:37) [12]
Ага. Именно так. Доволен. Приятно что собеседник умен.
Anatoly Podgoretsky © (30.09.07 18:41) [13]
ну в данном случае оба решения нетипобезопастны. И типобезопастных я не вижу. Это в дотнете наверно можно, а в делфи вряд ли.
← →
alex_ant © (2007-09-30 19:08) [15]Огромное спасибо вам за советы. Попробовал такой код:
var
PA, PB: Pointer;
A, B: array of string;
begin
SetLength(A, 2);
A[0] := "1";
A[1] := "2";
SetLength(B, 2);
B[0] := "1";
B[1] := "2";
PA := Pointer(A);
PB := Pointer(B);
if CompareMem(PA, PB, Length(A)) then
ShowMessage("Равны")
else
ShowMessage("НЕ Равны");
Для массивов Integer работает, для массивов строк — нет.
← →
vpbar © (2007-09-30 19:09) [16]>>alex_ant © (30.09.07 19:08) [15]
Читал [6] ??
Если элементы массива - суть ссылки на объекты (строки, классы), то естественно не работает.
Или это скрытый вопрос "почему для строк не работает"?
← →
alex_ant © (2007-09-30 19:29) [17]
> Или это скрытый вопрос "почему для строк не работает"?
:) Да, это был скрытый вопрос. Прошу прощения, не обратил внимания на слово «строки».
В общем, общий вывод, наверное, заключается в том, что проще делать поэлементное сравнение, а Delphi не позволяет «железно» сравнивать переменные неизвестного типа. Эх...
← →
vpbar © (2007-09-30 19:38) [18]>>alex_ant © (30.09.07 19:29) [17]
Дело в том что в этом (array of string) в массиве хранятся указатели (строка это по сути указатель).
Здесь
B[0] := "1";
A[0] := "1";
память будет выделятся для каждой строки и следовательно указатели (строки B[0],A[0]) будут разные.
Надеюсь понятно.
В общем случае вывод правильный. В частном случае (массив простых типов) быстрее и проще как я указал или как в [15]. Но в при этом можно по ошибке передать массив не того типа.
← →
oxffff © (2007-09-30 20:01) [19]
> alex_ant © (30.09.07 19:29) [17]
>
> > Или это скрытый вопрос "почему для строк не работает"?
>
>
>
> :) Да, это был скрытый вопрос. Прошу прощения, не обратил
> внимания на слово «строки».
>
> В общем, общий вывод, наверное, заключается в том, что проще
> делать поэлементное сравнение, а Delphi не позволяет «железно»
> сравнивать переменные неизвестного типа. Эх...
TypeInfo?
← →
Riply © (2007-10-01 06:37) [20]> [0] alex_ant © (30.09.07 17:15)
http://www.rsdn.ru/article/Delphi/dynarrays.xml
P.S.
Если внимательно прочитать эту статью и разобраться, то все получиться :)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.033 c