Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
ВнизСравнение записей Найти похожие ветки
← →
Wistler © (2005-07-24 11:02) [0]Доброго времени суток. Аж стыдно за такой вопрос, но заклинило.
Есть 2 переменные типа record. Необходимо сравнить их на равенство. Сравнивать все поля не красиво и глупо.
Заранее спасибо.
← →
Плохиш © (2005-07-24 11:11) [1]В цикле по всем полям, сравнивая соответствующие.
← →
Leonid Troyanovsky © (2005-07-24 11:17) [2]
> Wistler © (24.07.05 11:02)
> Доброго времени суток. Аж стыдно за такой вопрос, но заклинило.
>
> Есть 2 переменные типа record. Необходимо сравнить их на
> равенство. Сравнивать все поля не красиво и глупо.
Сравниваешь SizeOf, а затем CompareMem.
Можно и без SizeOf, если они однотипны.
--
Regards, LVT.
← →
Lamer@fools.ua © (2005-07-24 11:34) [3]>>Wistler © (24.07.05 11:02)
Какого типа поля у записи?
← →
Anatoly Podgoretsky © (2005-07-24 11:36) [4]Чего же глупого, кроме то в общем иначе и не возможно. Как сравнить две записи, в которых динамические типы, например string. Кроме того сравнение далеко не тривиально как кажется, типы могут быть очень сложные
← →
Wistler © (2005-07-24 11:39) [5]
> Сравниваешь SizeOf, а затем CompareMem.
> Можно и без SizeOf, если они однотипны
CompareMem сравнивает данные в динамической памяти, а у меня переменные описаны:Type
TV:record
...
end;
V1, V2:TV;
Можно конечно завести 2 дополнительные переменные типа ^TV, и использовать CompareMem, но хотелось напрямую сравнить 2 переменные.
← →
Wistler © (2005-07-24 11:41) [6]
> Какого типа поля у записи?
String и запись в которой тоже String.
← →
Гаврила © (2005-07-24 11:52) [7]
> [5] Wistler ©
> CompareMem сравнивает данные в динамической памяти, а у
> меня переменные описаны:
Что такое "динамической памяти"??
← →
Гаврила © (2005-07-24 11:53) [8]
> String и запись в которой тоже String.
Кром как "сравнение по полям" ничего не получится
← →
Wistler © (2005-07-24 11:54) [9]
> Что такое "динамической памяти"??
В функцию надо передать тип Pointer, а не TV!
← →
Гаврила © (2005-07-24 12:12) [10]
> В функцию надо передать тип Pointer, а не TV!
> Type
> TV:record
> ...
> end;
> V1, V2:TV;
Это делается так:
CompareMem(@V1, @V2, ...)
но ,если в записи указатели (huge стринг - это указатель), то, соответственно, не получится, так что - сравнивай по полям
← →
Leonid Troyanovsky © (2005-07-24 12:13) [11]
> Wistler © (24.07.05 11:54) [9]
>
> > Что такое "динамической памяти"??
> В функцию надо передать тип Pointer, а не TV!
Дык, передай адрес TV.
Только, оно не решит твоей проблемы, как коллеги уже объяснили.
Если надо сравнивать строки, то record не лучшее для них место. Т.е., или их в TStringList или все в TObject с специализированными методами сравнения.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2005-07-24 12:18) [12]
> Гаврила © (24.07.05 12:12) [10]
> но ,если в записи указатели (huge стринг - это указатель),
Почему это не получится?
Если строка тажа самая (вплоть до копий - huge ;),
то - изволь.
Так, что сравнение сравнению - рознь.
--
Regards, LVT.
← →
Wistler © (2005-07-24 12:25) [13]Написал свою функцию сравнения, в которой сравниавю по полям, так что если изменится структура записи, придётся менять и функции. И как оказалось интересная тема, как написать универсальную функцию сравнения записей.
← →
begin...end © (2005-07-24 12:52) [14]Тело длинной строки частью записи не является. В записи содержится указатель на это тело. Поэтому, строго говоря, для решения задачи сравнения записей вполне подойдёт [2].
← →
msguns © (2005-07-24 12:56) [15]Не совсем понятно, зачем нужно такое сравнение. Если запись хранит информацию о каком-либо объекте, то у этого объекта должно быть поле, однозначно его идентифицирующее (что-то типа ID), если же один и тот же объект (вернее, запись с его реквизитами-полями) хранится в двух списках - то это что-то, имхо, в голове ;)
← →
Anatoly Podgoretsky © (2005-07-24 12:57) [16]Что болтать, выдай критерий равенства двух записей с указательными типами, тогда будет предмет для разговора.
← →
begin...end © (2005-07-24 12:58) [17]> Anatoly Podgoretsky © (24.07.05 12:57) [16]
Вы это кому?
← →
Leonid Troyanovsky © (2005-07-24 13:05) [18]
> begin...end © (24.07.05 12:58) [17]
> > Anatoly Podgoretsky © (24.07.05 12:57) [16]
>
> Вы это кому?
Тому, кто оный критерий утаил, IMHO.
--
Regards, LVT.
← →
Essence (2005-07-24 15:23) [19]Записи, которые содержат тип 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.
← →
begin...end © (2005-07-24 15:49) [20]> Essence (24.07.05 15:23) [19]
Ваши выводы неверны. Потому что эксперимент поставлен неправильно.
← →
Essence (2005-07-24 15:52) [21]
> begin...end © (24.07.05 15:49) [20]
А как правильно?
← →
Antonn © (2005-07-24 16:05) [22]Essence (24.07.05 15:23) [19]
TTest = record
i: Integer;
s: String;
end;
ох, не нравятся мне стринги в рекордах...
← →
Essence (2005-07-24 16:09) [23]Чем не нравятся? Если в файл сохранять, то согласен. А чем ещё?
← →
Antonn © (2005-07-24 16:11) [24]Essence (24.07.05 16:09) [23]
в поток не сохраняются... мне этого достаточно.
← →
Essence (2005-07-24 16:13) [25]
> Antonn © (24.07.05 16:11) [24]
Ну тогда String[255]:)
Ето же был тест на сравнение.
← →
begin...end © (2005-07-24 16:15) [26]> 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 17:00) [27]
> begin...end © (24.07.05 16:15) [26]
Выходит здесь тоже сравниваются указатели на строку?
← →
begin...end © (2005-07-24 17:04) [28]> Essence (24.07.05 17:00) [27]
Разумеется. О чём и было сказано в [14].
← →
Essence (2005-07-24 17:16) [29]Да уж! Шкряб-шкряб озадачено по затылоку:)
К сожалению подумал, что явно не присваиваю значение одной переменной другой, а компилер, собака такая сам это за меня проделал. Раз присваиваю одинаковые значения, значит равносильно, что присвоить значение одной переменной другой.
Вляпался:(
← →
evvcom © (2005-07-25 09:16) [30]Что-то не пойму, Wistler и Essence одно лицо иль нет? Ладно, неважно. Теперь по теме.
Если есть необходимость/желание написать универсальную функцию сравнения, надо передавать в нее кроме указателей на запись, также их TypeInfo. А дальше по TypeInfo разруливать. Примеры в System._New/_Dispose и связанных с ними функциях. Тут уж, батенька, без асма не обойтись.
← →
Essence (2005-07-25 09:59) [31]
> evvcom © (25.07.05 09:16) [30]
> Что-то не пойму, Wistler и Essence одно лицо иль нет?
Нет. У нас скорее разные лица:)
Просто подумалось, что, как и говорил begin...end © - сравниваться будут указатели. Решил проверить и ввёл себя в заблуждение. Захотелось на халяву, с помощью одной фукции CompareMem, завалить льва:)
← →
evvcom © (2005-07-25 11:06) [32]
> сравниваться будут указатели
Где сравниваться? Если в CompareMem, то да. Она один к одному сравнит и усе, не различая что там указатели или данные. Ей по фиг. А если сравнивать надо именно данные, то одной CompareMem здесь не обойтись. Короче нужен ответ на
> Anatoly Podgoretsky © (24.07.05 12:57) [16]
> Что болтать, выдай критерий равенства двух записей с указательными
> типами, тогда будет предмет для разговора.
← →
Essence (2005-07-25 11:42) [33]
> evvcom © (25.07.05 11:06) [32]
>
> > сравниваться будут указатели
>
> Где сравниваться? Если в CompareMem, то да.
Так, я о том же:)
> А если сравнивать надо именно данные, то одной CompareMem
> здесь не обойтись.
Да, да, да. Никто не спорит, за исключением некоторой поправки: поля типов Integer и Real - тоже относятся к данным:)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.014 c