Уніфікований спосіб порівнювати масиви

Уніфікований спосіб порівнювати масиви?

Пишу тести модулів, часто виникає необхідність порівнювати два динамічних масиву на ідентичність. Поки що тупо порівнюю поелементно. Чи можна в Delphi реалізувати якусь функцію, яка б порівнювала два масиви на ідентичність, незалежно від типу містяться в них елементів, щоб можна було цю функцію використовувати і для порівняння масивів рядків, масивом чисел і т. Д.?

Наприклад, в Perl існує можливість порівняти масиви будь-якого типу на ідентичність, передавши посилання на них в якості параметра в одну уніфіковану функцію. Далі функція сама з'ясовує їх типізацію та розмірність, і повертає істину, якщо кількість елементів і їх тип і значення збігаються. Чи можна так само в Delphi зробити?

Заздалегідь дякую за поради.

Зрозумів тут, що питання фактично є питанням про можливість порівняти змінну будь-якого типу (об'єкт, масив, запис та ін.) З будь-якої іншої змінної.

if MegaEqual (PVarA, PVarB: Pointer) then
# XA0; ShowMessage ( "Змінні рівні");
else
# XA0; ShowMessage ( "Змінні нерівні");

де PVarA, PVarB - покажчики на змінні будь-якого типу.

P. S. Не судіть строго, якщо щось не так, з покажчиками працював дуже мало.

В принципі так, якщо в кожному масиві змінні йдуть послідовно. Тоді їх можна представити як два здоровенних масиву байт і порівнювати побайтно.


> В принципі так, якщо в кожному масиві змінні йдуть послідовно.
> # XA0; Тоді їх можна представити як два здоровенних масиву
> Байт і порівнювати побайтно.
>

А як це можна зробити? Можете показати невеличкий приклад?

Xor за розміром масиву?

Хз. Ось щас тільки що написав. Чи не тестував, але теоретично повинно спрацювати. Len - це довжина більшого з масивів. Знаходиться за допомогою length (Масив). Через Пойнтер її не одержати. А, так - якщо один з масивів коротше ніж Len, то або виникне AV, або продовження масиву буде випадковим чином братися з пам'яті.

procedure TForm1.Button1Click (Sender: TObject);

function Сompare (a, b: pointer; sizeOfElement: byte): Boolean;
var La, Lb, j: integer;
# XA0; # XA0; 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 # XA0; x [i]: = (i + 1);
SetLength (y, 3);
for i: = low (y) to High (y) do # XA0; 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)) тип масиву повинен бути однаковий. Якщо елементи масиву - суть посилання на об'єкти (рядки, класи), то природно не працює.

-d FFF2: 93F1
FFF2: 93F0 # XA0; # XA0; BF 5C 00 8A 1C F3 A4-33 C0 AB AB 59 5E 1F 1E # XA0; # XA0;. \. 3. Y ^ ..
FFF2: 9400 # XA0; 56 C5 74 0A 8A 3C F3 A4-AB AB 5E 1F C5 74 02 80 # XA0; V.t ..<. ^..t..
FFF2: 9410 # XA0; C9 80 8B F9 F3 A4 FE C9-8A C7 32 FF E8 A7 0C 73 # XA0 ;. 2. s
FFF2: 9420 # XA0; 02 8A F9 8A C3 32 DB E8-9C 0C 73 02 8A D9 E8 36 # XA0 ;. 2. s. 6
FFF2: 9430 # XA0; A4 66 FF 74 12 66 FF 74-12 66 26 8F 06 0A 00 33 # XA0; .f.t.f.t.f. 3
FFF2: 9440 # XA0; C0 8E D8 66 8F 06 88 00-36 C7 06 2C 03 80 00 36 # XA0 ;. f. 6. 6
FFF2: 9450 # XA0; 8E 1E 30 03 36 8C 1E 2E-03 F6 46 FB 01 74 27 36 # XA0 ;. 0.6. F..t "6
FFF2: 9460 # XA0; C5 36 BF 0E C4 7E FC 26-8C 5D 10 4E 4E 89 1C 26 # XA0; .6.

.]. NN ..
FFF2: 9470 # XA0; 89 # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0 ;.

> Result: = CompareMem (a, b, Len);

Хмм. А ось і рішення! Ну ладно, будемо вважати, що у мене просто показаний принцип.

Ні, оскільки немає ніяких методів підтвердити, що покажчик вказує на подібну структуру.

Величезне спасибі вам за поради. Спробував такий код:


var
# XA0; PA, PB: Pointer;
# XA0; A, B: array of string;
begin
# XA0; SetLength (A, 2);
# XA0; A [0]: = "1";
# XA0; A [1]: = "2";
# XA0; SetLength (B, 2);
# XA0; B [0]: = "1";
# XA0; B [1]: = "2";

# XA0; PA: = Pointer (A);
# XA0; PB: = Pointer (B);

# XA0; if CompareMem (PA, PB, Length (A)) then
# XA0; # XA0; ShowMessage ( "Чи рівні")
# XA0; else
# XA0; # XA0; ShowMessage ( "НЕ Рівні");

Для масивів Integer працює, для масивів рядків - немає.


> Чи це прихований питання "чому для рядків не працює"?

) Так, це був прихований питання. Прошу вибачення, не звернув уваги на слово «рядки».

Загалом, загальний висновок, напевно, полягає в тому, що простіше робити поелементне порівняння, а Delphi не дозволяє «залізно» порівнювати змінні невідомого типу. Ех.