Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сравнение записей [D7]


Страницы:   1 2

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].


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо