![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сравнение записей [D7]
Wistler © (2005-07-24 11:02:00)Доброго времени суток. Аж стыдно за такой вопрос, но заклинило.
Есть 2 переменные типа record. Необходимо сравнить их на равенство. Сравнивать все поля не красиво и глупо.
Заранее спасибо.
Essence (2005-07-25 11:42:00) [1]
> evvcom © (25.07.05 11:06) [32]
>
> > сравниваться будут указатели
>
> Где сравниваться? Если в CompareMem, то да.
Так, я о том же:)
> А если сравнивать надо именно данные, то одной CompareMem
> здесь не обойтись.
Да, да, да. Никто не спорит, за исключением некоторой поправки: поля типов Integer и Real - тоже относятся к данным:)
evvcom (2005-07-25 11:06:00) [2]
> сравниваться будут указатели
Где сравниваться? Если в CompareMem, то да. Она один к одному сравнит и усе, не различая что там указатели или данные. Ей по фиг. А если сравнивать надо именно данные, то одной CompareMem здесь не обойтись. Короче нужен ответ на
> Anatoly Podgoretsky © (24.07.05 12:57) [16]
> Что болтать, выдай критерий равенства двух записей с указательными
> типами, тогда будет предмет для разговора.
Essence (2005-07-25 09:59:00) [3]
> evvcom © (25.07.05 09:16) [30]
> Что-то не пойму, Wistler и Essence одно лицо иль нет?
Нет. У нас скорее разные лица:)
Просто подумалось, что, как и говорил begin...end © - сравниваться будут указатели. Решил проверить и ввёл себя в заблуждение. Захотелось на халяву, с помощью одной фукции CompareMem, завалить льва:)
evvcom (2005-07-25 09:16:00) [4]Что-то не пойму, Wistler и Essence одно лицо иль нет? Ладно, неважно. Теперь по теме.
Если есть необходимость/желание написать универсальную функцию сравнения, надо передавать в нее кроме указателей на запись, также их TypeInfo. А дальше по TypeInfo разруливать. Примеры в System._New/_Dispose и связанных с ними функциях. Тут уж, батенька, без асма не обойтись.
Essence (2005-07-24 17:16:00) [5]Да уж! Шкряб-шкряб озадачено по затылоку:)
К сожалению подумал, что явно не присваиваю значение одной переменной другой, а компилер, собака такая сам это за меня проделал. Раз присваиваю одинаковые значения, значит равносильно, что присвоить значение одной переменной другой.
Вляпался:(
begin...end (2005-07-24 17:04:00) [6]> Essence (24.07.05 17:00) [27]
Разумеется. О чём и было сказано в [14].
Essence (2005-07-24 17:00:00) [7]
> begin...end © (24.07.05 16:15) [26]
Выходит здесь тоже сравниваются указатели на строку?
begin...end (2005-07-24 16:15:00) [8]> Essence (24.07.05 15:52) [21]
Не будем пока касаться записей, содержащих поля типа Pointer или динамический массив, а ограничимся записями с полем string (AnsiString).
type
TRec = packed record
I: Integer;
S: string;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
R1, R2: TRec;
begin
R1.I := 1;
R1.S := 'abc';
R2.I := 1;
R2.S := 'abc';
// Убедимся, что поля R1.S и R2.S указывают на одинаковые тела строк
ShowMessageFmt('%s %s', [R1.S, R2.S]);
// Сравнение записей
if CompareMem(@R1, @R2, sizeof(TRec)) then
ShowMessage('Содержимое записей одинаково')
end.
Тест показал, что содержимое записей R1 и R2 одинаково (о чём Вы и говорили). Теперь немного изменим тест:
procedure TForm1.Button1Click(Sender: TObject);
var
R1, R2: TRec;
begin
R1.I := 1;
R1.S := 'abc';
R2.I := 1;
R2.S := Copy(R1.S, 1, Length(R1.S));
// Убедимся, что поля R1.S и R2.S указывают на одинаковые тела строк
ShowMessageFmt('%s %s', [R1.S, R2.S]);
// Сравнение записей
if CompareMem(@R1, @R2, sizeof(TRec)) then
ShowMessage('Содержимое записей одинаково')
end.
На этот раз тест показал, что содержимое R1 и R2 различно. Как же так -- строки одинаковые, а записи разные?
Какие есть предположения?
Essence (2005-07-24 16:13:00) [9]
> Antonn © (24.07.05 16:11) [24]
Ну тогда String[255]:)
Ето же был тест на сравнение.
Antonn (2005-07-24 16:11:00) [10]Essence (24.07.05 16:09) [23]
в поток не сохраняются... мне этого достаточно.
Essence (2005-07-24 16:09:00) [11]Чем не нравятся? Если в файл сохранять, то согласен. А чем ещё?
Antonn (2005-07-24 16:05:00) [12]Essence (24.07.05 15:23) [19]
TTest = record
i: Integer;
s: String;
end;
ох, не нравятся мне стринги в рекордах...
Essence (2005-07-24 15:52:00) [13]
> begin...end © (24.07.05 15:49) [20]
А как правильно?
begin...end (2005-07-24 15:49:00) [14]> Essence (24.07.05 15:23) [19]
Ваши выводы неверны. Потому что эксперимент поставлен неправильно.
Essence (2005-07-24 15:23:00) [15]Записи, которые содержат тип string и, разумеется, не динамические типы сравниваются корректно.
Записи, содержащие в себе динамический массив, не хотят корректно сравниваться. Понятно - там сравниваются адреса.
А записи, содержащие тип Pointer, вобще при сравнении вызывают ругань компилера:)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
TTestArray = array of Integer;
TTest = record
i: Integer;
s: String;
end;
TTest1 = record
i: Integer;
testArr: TTestArray;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function ListenVergleichen1(t1, t2: TTest):String;
begin
Result := 't1 ist ungleich t2';
if SizeOf(t1) = SizeOf(t2) then
if CompareMem(@t1,@t2, SizeOf(t1)) then
Result := 't1 ist gleich t2';
end;
function ListenVergleichen2(t3, t4: TTest1):String;
begin
Result := 't3 ist ungleich t4';
if SizeOf(t3) = SizeOf(t4) then
if CompareMem(@t3,@t4, SizeOf(t3)) then
Result := 't3 ist gleich t4';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Test1: TTest;
Test2: TTest;
Test3: TTest1;
Test4: TTest1;
i: Integer;
begin
Memo1.Clear;
Test1.i := 1000000;
Test1.s := 'bla-bla-bla-bla-bla-bla-bla-bla';
Test2.i := 1000000;
Test2.s := 'bla-bla-bla-bla-bla-bla-bla-bla';
Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
//-------------------------------------------------------
Test1.i := 1;
Test1.s := 'bla-bla-bla-bla-bla-bla-bla-bla';
Test2.i := 1000000;
Test2.s := 'bla-bla-bla-bla-bla-bla-bla-bla';
Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
//-------------------------------------------------------
Test1.i := 1;
Test1.s := 'bla-bla-bla-bla-bla-bla-bla-bla';
Test2.i := 1;
Test2.s := 'bla ein Mal';
Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
//-------------------------------------------------------
Test3.i := 10;
SetLength(Test3.testArr,100);
SetLength(Test4.testArr,100);
for i := Low(Test3.testArr) to High(Test3.testArr) do
begin
Test3.testArr[i] := i;
Test4.testArr[i] := i;
end;
Memo1.Lines.Add(ListenVergleichen2(Test3,Test4));
//-------------------------------------------------------
Test3.i := 10;
SetLength(Test3.testArr,10);
for i := Low(Test3.testArr) to High(Test3.testArr) do
Test3.testArr[i] := i;
Test4.i := 10;
SetLength(Test4.testArr,1000);
for i := Low(Test4.testArr) to High(Test4.testArr) do
Test4.testArr[i] := i;
Memo1.Lines.Add(ListenVergleichen2(Test3,Test4));
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
end.
Leonid Troyanovsky (2005-07-24 13:05:00) [16]
> begin...end © (24.07.05 12:58) [17]
> > Anatoly Podgoretsky © (24.07.05 12:57) [16]
>
> Вы это кому?
Тому, кто оный критерий утаил, IMHO.
--
Regards, LVT.
begin...end (2005-07-24 12:58:00) [17]> Anatoly Podgoretsky © (24.07.05 12:57) [16]
Вы это кому?
Anatoly Podgoretsky (2005-07-24 12:57:00) [18]Что болтать, выдай критерий равенства двух записей с указательными типами, тогда будет предмет для разговора.
msguns (2005-07-24 12:56:00) [19]Не совсем понятно, зачем нужно такое сравнение. Если запись хранит информацию о каком-либо объекте, то у этого объекта должно быть поле, однозначно его идентифицирующее (что-то типа ID), если же один и тот же объект (вернее, запись с его реквизитами-полями) хранится в двух списках - то это что-то, имхо, в голове ;)
begin...end (2005-07-24 12:52:00) [20]Тело длинной строки частью записи не является. В записи содержится указатель на это тело. Поэтому, строго говоря, для решения задачи сравнения записей вполне подойдёт [2].