Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.10.09;
Скачать: [xml.tar.bz2];

Вниз

косвенная рекурсия   Найти похожие ветки 

 
теркин ©   (2011-06-17 22:42) [0]

Кто сможет объяснить почему при опережающем объявлении классов, ссылающихся друг на друга в динамическом массиве не происходит присвоение в данном примере.

type  TRebro=class;
TYzel=class(TObject)
constructor CreateYzel(Nomer,IndexStorka:Integer);
private
ListRebro:array of TRebro;
public
NomerYzla:Integer;
StrokaMatriz:Integer;
end;

TRebro=class(TObject)
constructor CreateRebro(ID,IndexStolb:Integer);
private
ListYzel:array of TYzel;
public
IDRebra:Integer;
StolbMatriz:Integer;
end;

type TMatrizaInciden=Class(TObject)
constructor CreateMatriza(DMYhastok: TDMYhastok);
private
MassivReber:array of TRebro;
MassivYzlov:array of TYzel;
....
....
public
property Yzel[Stroka:Integer]:TYzel read ReadTYzel write WriteTYzel;
property Rebro[stolb:Integer]:TRebro read ReadTRebro write WriteTRebro;
.....
.....
procedure PerestanovkaStrok(Stroka1,Stroka2:Integer);
procedure PerestanovkaStolbov(Stolb1,Stolb2:Integer);
.......
end;
implementation
{Данная процедура работает, все нормально}
procedure TMatrizaInciden.PerestanovkaStolbov(Stolb1, Stolb2: Integer);
var Reb:TRebro;
begin
   if ErrorIndexStolba(Stolb1) or ErrorIndexStolba(Stolb2) then exit;
   reb:=Rebro[Stolb1];
   rebro[stolb1]:=rebro[stolb2];
   rebro[stolb2]:=reb;
end;
{Данная процедура меняет местами поля объекта, динамические массивы не присваиваются, значения остаются прежними}
procedure TMatrizaInciden.PerestanovkaStrok(Stroka1, Stroka2: Integer);
Var Yz:TYzel;
begin
   if ErrorIndexStroki(Stroka1) or ErrorIndexStroki(Stroka2) then exit;
   yz:=Yzel[Stroka1];
   yzel[stroka1]:=yzel[stroka2];
   yzel[stroka2] :=yz ;
end;


 
Игорь Шевченко ©   (2011-06-17 22:44) [1]


> Кто сможет объяснить почему при опережающем объявлении классов,
>  ссылающихся друг на друга в динамическом массиве не происходит
> присвоение в данном примере.


Форматируй текст, и люди к тебе потянутся. Глядишь, и объяснят


 
теркин ©   (2011-06-17 22:59) [2]

В смысле форматируй


 
sniknik ©   (2011-06-17 23:18) [3]

> В смысле форматируй
нувсмыслепишитакчтобывсембылопонятноесливдругзахотятразбиратьсяствоейпроблемойип омогатьтебевидеалекоддолженбытьдлякопипастеипроверкивживую.

доступно?


 
Dimka Maslov ©   (2011-06-17 23:32) [4]

WriteTYzel?


 
Rouse_ ©   (2011-06-17 23:41) [5]

Судя по всему неверная реализация WriteTYzel, либо происходит выход на следующем условии:
if ErrorIndexStroki(Stroka1) or ErrorIndexStroki(Stroka2) then exit;


 
теркин ©   (2011-06-18 15:47) [6]

Нет выход не происходит. Если бы выход произошел присвоения вообще не было. Поля объектов присваиваются за исключением динамических массивов. Тут косвенная рекурсия при объявлении объектов. Каждый объект содержит динамический массив, которые рекурсивно ссылаются друг на друга

type  TRebro=class;{Опережающее объявление класса}
TYzel=class(TObject)
....
ListRebro:array of TRebro;{Рекурсия}
.....
end;
TRebro=class(TObject)
.....
ListYzel:array of TYzel;{Рекурсия}
......
end;
Далее объявлен объект
type TMatrizaInciden=Class(TObject)
......
MassivReber:array of TRebro;{TRebro ссылается на TYzel }
MassivYzlov:array of TYzel;{TYzel Ссылается на TRebro}
.....
end;
Получается что TYzel ссылается TRebro обратно на TYzel и т.д. Вот где рекурсия, при объявление классов. Проблема заключается в том что если происходит перестановка элементов массива MassivReber, он перетаскивает за собой ListRebro, а вот если переставлять элементы MassivYzlov он значения ListRebro не меняет, они остаются прежними. Поля объекта меняют свои значения а динамические массивы нет. В этом вся проблема


 
Игорь Шевченко ©   (2011-06-18 23:53) [7]

Мозгов купи, партизан

Тебе уже в двух постах намекнули, что надо привести код методов, а не заниматься гаданием на кофейной гуще.


 
теркин ©   (2011-06-19 20:04) [8]

Прошу прощения все свойства и методы привести не могу из за ограничения по количеству символов, привожу полное описание объектов и все методы и свойства отношение к проблеме.

uses Classes,SysUtils,DataModuleYhastok, DB, DBTables;

type  TRebro=class;
TYzel=class(TObject)
constructor CreateYzel(Nomer,IndexStorka:Integer);
private
ListRebro:array of TRebro;
maxIndex:Integer;
procedure AddRebro(Rebro:TRebro);
function ReadRebro(Ind:Integer):TRebro;
public
NomerYzla:Integer;
StrokaMatriz:Integer;
property Rebro[Ind:Integer]:TRebro read ReadRebro;
end;

TRebro=class(TObject)
constructor CreateRebro(ID,IndexStolb:Integer);
private
ListYzel:array of TYzel;
maxIndex:Integer;
procedure AddYzel(Yzel:TYzel);
function ReadYzel(Ind:Integer):TYzel;
public
IDRebra:Integer;
StolbMatriz:Integer;
property Yzel[Ind:Integer]:Tyzel read ReadYzel;
end;

type TMatrizaInciden=Class(TObject)
constructor CreateMatriza(DMYhastok: TDMYhastok);
private
MassivReber:array of TRebro;
MassivYzlov:array of TYzel;
function ErrorIndexStroki(Index:Integer):Boolean;
function ErrorIndexStolba(Index:Integer):Boolean;
function ReadNameYzel(Stroka:Integer):String;
function ReadNameRebro(Stolb:Integer):String;
function ReadCells(Stroka,Stolb:Integer):String;
function ReadTYzel(Stroka:Integer):TYzel;
procedure WriteTYzel(Stroka:Integer;Value:TYzel);
function ReadTRebro(Stolb:Integer):TRebro;
procedure WriteTRebro(Stolb:Integer;Value:TRebro);
procedure YdalenieNilStrok;
procedure YdalenieNilStolb;
procedure YdalenieIzolirStolb;
function IzolirRebro(Rebro:Trebro):boolean;
function YzelZepi(Yzel:TYzel):Boolean;
procedure YdelenieZepi;
procedure ZapolnenieMatriz;
public
MaxStolb:Integer;
MaxStrok:Integer;
property Rebro[stolb:Integer]:TRebro read ReadTRebro write WriteTRebro;
property NameYzel[Stroka:Integer]:String read ReadNameYzel;
property NameRebro[Stolb:Integer]:String read ReadNameRebro;
property Cells[Stroka,Stolb:Integer]:String read ReadCells;default;
property Yzel[Stroka:Integer]:TYzel read ReadTYzel write WriteTYzel;
procedure PerestanovkaStrok(Stroka1,Stroka2:Integer);
procedure PerestanovkaStolbov(Stolb1,Stolb2:Integer);
procedure YdalenieStroki(Stroka:Integer);{Пресевдоудаление}
procedure YdalenieStolba(Stolb:Integer);{Пресевдоудаление}
end;

implementation

function TMatrizaInciden.ReadNameYzel(Stroka:Integer):String;
begin
   if ErrorIndexStroki(Stroka) then exit;
   result:=inttostr(massivyzlov[Stroka-1].NomerYzla);
end;

function TMatrizaInciden.ErrorIndexStroki(Index:Integer):Boolean;
begin
   if (Index>maxStrok) or (Index<1) then
   result:=true
   else
   result:=false;
end;

function TMatrizaInciden.ErrorIndexStolba(Index:Integer):Boolean;
begin
   if (Index>MaxStolb) or (Index<1) then
   result:=true
   else
   result:=false;
end;

constructor TMatrizaInciden.CreateMatriza(DMYhastok: TDMYhastok);

begin
   MaxStolb:=DMYhastok.TableYhastok.RecordCount;
   MaxStrok:=DMYhastok.TableYzel.RecordCount;
   setlength(MassivReber,(MaxStolb));
   setlength(MassivYzlov,(MaxStrok));
ZapolnenieMatriz;
YdalenieNilStrok;
YdalenieNilStolb;
YdalenieIzolirStolb;
YdelenieZepi;
end;

procedure TMatrizaInciden.ZapolnenieMatriz;
var i,j:integer;
begin
   dmyhastok.TableYhastok.First;
   dmyhastok.TableYzel.First;
    i:=0;
while not(DMYhastok.TableYhastok.Eof) do
begin
    massivreber[i]:=Trebro.CreateRebro(dmyhastok.TableYhastok.FieldValues["IDYhastok "],i);
    j:=0;
    DMYhastok.TableYzel.First;
    while not(DMYhastok.TableYzel.Eof) do
    begin
        if (Dmyhastok.TableYhastokYzel1.Value =dmyhastok.TableYzelYzel.Value)
        or (dmyhastok.TableYhastokYzel2.Value =dmyhastok.TableYzelYzel.Value)  then
        begin
            if massivyzlov[j]=nil then massivyzlov[j]:=TYzel.CreateYzel(dmyhastok.TableYzelYzel.Value,j);
               massivyzlov[j].AddRebro(massivreber[i]);
               massivreber[i].AddYzel(massivyzlov[j]);
        end;
    inc(j);
    DMYhastok.TableYzel.Next;
    end;
inc(i);
DMYhastok.TableYhastok.Next;
end;
end;
{Описание ребра}
procedure TRebro.AddYzel(Yzel:TYzel);
begin
inc(maxIndex);
  SetLength(ListYzel,MaxIndex);
  listyzel[MaxIndex-1]:=Yzel;
end;

constructor TRebro.CreateRebro(ID,IndexStolb:Integer);
begin
inherited Create;
IdRebra:=ID;
StolbMatriz:=IndexStolb+1;
maxIndex:=0;
end;

{Описение узла}
procedure TYzel.AddRebro(Rebro:TRebro);
begin
inc(MaxIndex);
   setlength(listrebro,MaxIndex);
   ListRebro[MaxIndex-1]:=Rebro;
end;

constructor TYzel.CreateYzel(Nomer,IndexStorka:Integer);
begin
   inherited create;
   NomerYzla:=Nomer;
   StrokaMatriz:=IndexStorka+1;
   MaxIndex:=0;
end;

function TYzel.ReadRebro(Ind: Integer): TRebro;
begin
   if (Ind>maxIndex-1) or (ind<0) then exit;
   result:=ListRebro[ind];
end;

function TRebro.ReadYzel(Ind: Integer): TYzel;
begin
if (Ind<0) or (Ind>MaxIndex-1) then exit;
result:=ListYzel[ind];
end;

procedure TMatrizaInciden.PerestanovkaStrok(Stroka1, Stroka2: Integer);
Var Yz:TYzel;
   Str:Integer;
begin
   if ErrorIndexStroki(Stroka1) or ErrorIndexStroki(Stroka2) then exit;
   yz:=Yzel[Stroka1];
   yzel[stroka1]:=yzel[stroka2];
   yzel[stroka2]:=yz;
end;

function TMatrizaInciden.ReadTYzel(Stroka: Integer): TYzel;
begin
 if ErrorIndexStroki(Stroka)then exit;
 result:=MassivYzlov[stroka-1];
end;

procedure TMatrizaInciden.WriteTYzel(Stroka: Integer; Value: TYzel);
begin
    if ErrorIndexStroki(Stroka)then exit;
    MassivYzlov[stroka-1]:=Value;
end;

procedure TMatrizaInciden.PerestanovkaStolbov(Stolb1, Stolb2: Integer);
var Reb:TRebro;
begin
   if ErrorIndexStolba(Stolb1) or ErrorIndexStolba(Stolb2) then exit;
   reb:=Rebro[Stolb1];
   rebro[stolb1]:=rebro[stolb2];
   rebro[stolb2]:=reb;
end;

function TMatrizaInciden.ReadTRebro(Stolb: Integer): TRebro;
begin
 if   ErrorIndexStolba(Stolb) then exit;
 result:=massivreber[stolb-1];
end;

procedure TMatrizaInciden.WriteTRebro(Stolb: Integer; Value: TRebro);
begin
 if   ErrorIndexStolba(Stolb) then exit;
 MassivReber[Stolb-1]:=Value;
end;

end.


 
Игорь Шевченко ©   (2011-06-19 20:56) [9]


> procedure TMatrizaInciden.WriteTYzel(Stroka: Integer; Value:
>  TYzel);
> begin
>     if ErrorIndexStroki(Stroka)then exit;
>     MassivYzlov[stroka-1]:=Value;
> end;


здесь происходит присваивание указателя, без копирования содержимого (что в общем-то разумно).
Поэтому


 
Игорь Шевченко ©   (2011-06-19 20:58) [10]

добавил рано.

Поэтому


> Поля объекта меняют свои значения а динамические массивы
> нет


быть вряд ли может, так как по сути элементы массива не меняются местами, а меняются только указатели на них.

Я бы посмотрел, что там с индексами.


 
теркин ©   (2011-06-19 22:09) [11]

Спасибо за совет на счет индексов. Для меня пока это темный лес-признаюсь честно. Пробовал работать со стандартным списком TList-картина та же.А на счет прямого копирования нельзя ли по подробней. Прошу прощения что пишу с большими перерывами-ребенок болеет.


 
Игорь Шевченко ©   (2011-06-19 22:42) [12]

теркин ©   (19.06.11 22:09) [11]

Совет насчет индексов следующий: создать протокол, в который выводить текущий индекс для элемента и содержимое этого элемента.


> procedure TMatrizaInciden.PerestanovkaStrok(Stroka1, Stroka2:
>  Integer);
> Var Yz:TYzel;
> begin
>    if ErrorIndexStroki(Stroka1) or ErrorIndexStroki(Stroka2)
> then exit;
>    yz:=Yzel[Stroka1];
>    yzel[stroka1]:=yzel[stroka2];
>    yzel[stroka2] :=yz ;
> end;


изменить на

procedure TMatrizaInciden.PerestanovkaStrok(Stroka1, Stroka2: Integer);

 procedure Log(const Msg: string);
 const
   LogName = ".\matrix_log.txt";
 var
   F: TextFile;
 begin
   AssignFile(F, LogName);
   if FileExists(LogName) then
     Append(F)
   else
     Rewrite(F);
   try
     writeln(F, Msg);
   finally
     CloseFIle(F);
   end;
 end;

 procedure LogNodeContents(const Node: TYzel; const Comment: string);
 var
   I: Integer;
 begin
   Log(Format("Node(%s) NomerYzla=%d, StrokaMatriz=%d", [Comment, Node.NomerYzla, Node.StrokaMatriz]));
   Log(Format("%d edges", [Length(Node.ListRebro)]));
   for I:=0 to Pred(Length(Node.ListRebro)) do
     Log(Format("Node(%s).Edge%d: IDRebra=%d, StolbMatriz=%d",
       [Comment, I, Node.ListRebro[I].IDRebra, Node.ListRebro[I].StolbMatriz]));
 end;

Var Yz:TYzel;
begin
  Log(Format("PerestanovkaStrok: Stroka1=%d, Stroka2=%d", [Stroka1, Stroka2]));
  if ErrorIndexStroki(Stroka1) or ErrorIndexStroki(Stroka2) then exit;
  LogNodeContents(Yzel[Stroka1], "Yzel[Stroka1] before swap");
  LogNodeContents(Yzel[Stroka2], "Yzel[Stroka2] before swap");
  yz:=Yzel[Stroka1];
  yzel[stroka1]:=yzel[stroka2];
  yzel[stroka2] :=yz ;
  LogNodeContents(Yzel[Stroka1], "Yzel[Stroka1] after swap");
  LogNodeContents(Yzel[Stroka2], "Yzel[Stroka2] after swap");
end;


и посмотреть потом файл matrix_log.txt


> procedure TMatrizaInciden.WriteTYzel(Stroka: Integer; Value:
>  TYzel);
> begin
>     if ErrorIndexStroki(Stroka)then exit;
>     MassivYzlov[stroka-1]:=Value;
> end;


Сама по себе перестановка в данном конкретном случае меняет значения указателей на TYzel в массиве MassivYzlov, не трогая содержимое самого объекта (что у него было в ребрах, то и осталось)


 
теркин ©   (2011-06-20 02:12) [13]

Спасибо Игорь попробовал. Произошла полная перестановка с небольшим побочным эффектом(с ним разберусь позже). А теперь сразу встает вопрос в чем фишка объясните, если Вас не затруднит.


 
Игорь Шевченко ©   (2011-06-20 10:52) [14]


> А теперь сразу встает вопрос в чем фишка объясните, если
> Вас не затруднит.


Так я вроде объяснил - перестановка в данном конкретном случае меняет значения указателей на TYzel в массиве MassivYzlov, не трогая содержимое самого объекта (что у него было в ребрах, то и осталось)

Если бы при присваивании (WriteTYzel) создавался новый экземпляр класса TYzel и туда бы аккуратно копировалось все содержимое источника, тогда бы можно было говорить о возможных ошибках в присваивании, а в существующем коде единственный путь для ошибки - это какая-нибудь некорректность работы с индексами массивов.


 
теркин ©   (2011-06-20 17:15) [15]

Как говорят в нашей местности -"От глубины до слез!"(ОГРОМЕННОЕ СПАСИБО!!!) за код. Осмелюсь побеспокоить Вас еще разок. Подскажите литературы по Delhi где популярно излагается работа с указателями. Просто по моему проще один раз разобраться, чем беспокоить других такими вопросами. Вот пожалуй и все. Маленький постскриптум -на пяти форумах ответ дать так и не смогли и решений не предложили(просмотров много толку никакого). Уровень форумов настораживает.


 
Игорь Шевченко ©   (2011-06-20 17:46) [16]


> Подскажите литературы по Delhi где популярно излагается
> работа с указателями.


Вот что не могу подсказать, так это литературу :)
Если по Delphi, то Тейксейра с Пачеко неплохие книжки пишут с названием "Delphi <номер версии>. Руководство разработчика."


 
теркин ©   (2011-06-20 17:50) [17]

Направление понял. Начну изучать. Спасибо!



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.10.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.004 c
2-1308318070
@!!ex
2011-06-17 17:41
2011.10.09
PageControl как нарисовать полностью свои закладки?


9-1189763352
andreil
2007-09-14 13:49
2011.10.09
Глюк OpenGL


2-1308570515
Alex_C
2011-06-20 15:48
2011.10.09
Событие OnTimer


2-1308655885
Kilowatt
2011-06-21 15:31
2011.10.09
Label поверх ProgressBar


2-1308354496
Германн
2011-06-18 03:48
2011.10.09
Как рассчитать "необходимый и достаточный" размер кнопки TButton





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский