[Delphi]Meerdere variabelen veranderen tegelijk

Pagina: 1
Acties:

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Ik heb een procedure waarin ik een paar variabelen heb van hetzelfde type. Zodra ik 1 van die variabelen verander veranderen ze allemaal :?

Ik vind het raar, maar ik maak denk ik een beginnersfout (ben ten slotte beginner :))

Het gaat om de volgende code:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
procedure TfrMain.SimulatedAnnealing(ZA:ZoneArray);
var
  Gevonden:                                         boolean;
  VerwisselingenPerIt, i,Zone1,Zone2,
  Artikel1, Artikel2:                               integer;
  AfkoelingsFactor, StartTemp, StopTemp, Temp,
  BesteKosten, tmpKosten, HuidigeKosten, expn:      double;
  BesteZA, tmpZA, huidigeZA:                        ZoneArray;
  tmpArtikel:                                       ArtikelRec;
begin
  {Eerst wordt de boel geinitialiseerd}
  VerwisselingenPerIt:=StrToInt(edtAantalVerwisselingenPerIteratie.text);
  AfkoelingsFactor:=StrToFloat(edtAfkoelingsfactor.text);
  StartTemp:=StrToFloat(edtStartTemperatuur.text);
  StopTemp:=StrToFloat(edtStopTemperatuur.text);
  temp:=StartTemp;
  BesteZA:=ZA;
  BesteKosten:=BerekenKosten(BesteZA);
  HuidigeZA:=BesteZA;
  HuidigeKosten:=BesteKosten;


  repeat
    tmpZA:=HuidigeZA;

    {Vervolgens worden er in tmpZA VerwisslingenPerIt verwisselingen gedaan}
    for i:=1 to VerwisselingenPerIt do
    begin
      {Kies twee verschillende zones waartussen verwisseld moet worden}
      Gevonden:=false;
      randomize;
      Zone1:=Random(High(tmpZA));
      while NOT(Gevonden) do
      begin
       Zone2:=Random(High(tmpZA));
       if (Zone1<>Zone2) then
         Gevonden:=true;
      end;

      {Kies een willekeurig artikel uit Zone1 en Zone2}
      Artikel1:=Random(High(tmpZA[Zone1]));
      Artikel2:=Random(High(tmpZA[Zone2]));

      {Verwissel de twee artikelen}
      tmpArtikel:= tmpZA[Zone1,Artikel1];
      tmpZA[Zone1,Artikel1]:=tmpZA[Zone2,Artikel2];
      tmpZA[Zone2,Artikel2]:=tmpArtikel;
    end;

    {Als de nieuwe toewijzing, tmpZA, betere kosten heeft dan de huidige kosten
    dan worden de verwisselingen geaccepteerd, zo niet dan worden
    de verwisselingen met een bepaalde kans geaccepteerd}
    tmpKosten:=BerekenKosten(tmpZA);
    if (tmpKosten < HuidigeKosten) then
    begin
      HuidigeKosten:=tmpKosten;  //geaccepteerd
      HuidigeZA:=tmpZA;          //geaccepteerd
    end
    else
    begin
     expn:= ((BesteKosten-tmpKosten)/(Temp));
      if (exp(expn)>random) then
      begin
        HuidigeKosten:=tmpKosten; //geaccepteerd
        HuidigeZA:=tmpZA;         //geaccepteerd
      end;
    end;

    {Als de huidige toewijzing beter is dan de beste dan wordt de beste de
    huidige}
    HuidigeKosten:=BerekenKosten(HuidigeZA);
    if (HuidigeKosten<BesteKosten) then
    begin
     BesteKosten:=HuidigeKosten;
     BesteZA:=HuidigeZA;
    end;

    {De temperatuur neemt af}
    Temp:= Temp*AfkoelingsFactor;

  {Stopcriterium}
  until temp<=StopTemp;
  ZA:=BesteZA;
 
end;


Zodra ik 1 van "BesteZA, tmpZA, huidigeZA" deze drie verander veranderen ze allemaal, wat ik dus niet wil, anders had ik wel 1 variabele genomen. Wat gaat er verkeerd?

Voor degenen die het willen weten, dit is een procedure voor simulated annealing, een optimaliseringsmethode.

[ Voor 3% gewijzigd door Oscar Mopperkont op 04-06-2003 16:56 . Reden: Aanvulling ]


Verwijderd

Die BesteZA etc. zijn objecten gok ik (type ZoneArray). Dat werkt iets anders dan een gewone variabele.

Stel ik heb een class TMyClass, en ik ga objecten aanmaken (=instanties van die class).

Delphi:
1
2
3
4
5
var
   oMijnObject : TMyClass
begin
   oMijnObject :=  TMyClass.Create;
end;


Op dat moment heb ik een object van class TMyClass. oMijnObject is niets meer en minder dan een pointer naar het geheugenadres waar dat object staat.

Doe ik dan:
Delphi:
1
  oMijnObject2 := oMijnObject;


Dan laat ik in feite oMijnObject2 naar hetzelfde stuk geheugen wijzen. Verander ik dan een veld van oMijnObject, dan verandert dat veld in oMijnObject2 dus mee, want die zijn hetzelfde.

De declaratie van die ZoneArray zit er niet bij, dus het blijft een beetje gokwerk wat het precies is. Overigens is het niet netjes om eigen types zo te noemen, netter is het om altijd een T als eerste letter te nemen, gevolgd door bv. je initialen. In mijn geval zou dat ThzZoneArray zijn.

//edit
hoe je dit dan wel moet oplossen, is afhankelijk van wat voor iets die zonearray is..

[ Voor 10% gewijzigd door Verwijderd op 04-06-2003 17:50 ]


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Thnx Hezik, ik zal het eens bestuderen wat je zei.

Ik zal declaratie ZoneArray ook even geven:
Delphi:
1
2
3
4
5
6
7
8
9
type
  ArtikelRec =  record
                Index: integer;
                Naam: String;
                Aantal: Integer;
                end;
  ArtikelArray = Array of ArtikelRec;
  ZoneArray = Array of ArtikelArray;
  CombinatieArray = Array of array of integer;


Dat van die namen wist ik nog niet, ga ik bij mijn volgende prog wel doen, vind het nu te veel werk om te veranderen :) (ook al heb je replace functies)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:45

Creepy

Tactical Espionage Splatterer

Een dynamische array's dus. Als je de gehele inhoud van de ene array over wilt zetten naar een andere array variabele, zul je dit per item moeten doen (i.p.v. gewoon array1 := array2). Zie het verhaal over pointer hierboven.

Maar als je Delphi gebruikt waarom maak je dan gebruik van records en array's i.p.v objecten en (een descendant van) TObjectList? Een Tobjectlist kan z'n eigen geheugen beheer doen, voor invoegen, toevoegen, verwijderen etc. zijn standaard methods en de inhoud van de ene TObjectList naar de andere kopieren kan m.b.v. een assign

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

^^^

/me sluit zich hier volledig bij aan.

Je hebt dan gelijk het voordeel dat je die SimulatedAnnealing als methode van je array object kunt neerzetten. Daar wordt je form ook gelijk een stuk overzichtelijker van.. (en groepeerd functionaliteit bij data)

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Creepy schreef op 04 juni 2003 @ 18:13:
Een dynamische array's dus. Als je de gehele inhoud van de ene array over wilt zetten naar een andere array variabele, zul je dit per item moeten doen (i.p.v. gewoon array1 := array2). Zie het verhaal over pointer hierboven.

Maar als je Delphi gebruikt waarom maak je dan gebruik van records en array's i.p.v objecten en (een descendant van) TObjectList? Een Tobjectlist kan z'n eigen geheugen beheer doen, voor invoegen, toevoegen, verwijderen etc. zijn standaard methods en de inhoud van de ene TObjectList naar de andere kopieren kan m.b.v. een assign
Thnx, maar ik snap er weinig van. Ik zal me er eens in gaan verdiepen. Vereist het veel werk om van die ZoneArray een object te maken ipv een "Array van een Array van Records".

Of is het denk je makkelijker om per item alles te laten kopieren? Hoe gaat dat dan in zijn werk eigenlijk? Moet ik dan eerst de lengte van die andere Array bepalen en dan gewoon array per array in die nieuw array neerzetten? (voor wie het nog kan volgen ;))

Verwijderd

Voor het hoe en wat over het opzetten van een objectmodel verwijs ik je even naar wat documentatie, om specifiek te zijn het boek 'mastering delphi' van marco cantu. Deze is voor elke delphi-versie te krijgen, en is eigenlijk een must-have voor elke serieuze delphi programmeur.

www.marcocantu.com

Dan deel 2, hoe de ene array naar de andere kopieren.. we gaan uit van:
Delphi:
1
2
3
4
5
6
7
ArtikelRec =  record
                Index: integer;
                Naam: String;
                Aantal: Integer;
                end;
  ArtikelArray = Array of ArtikelRec;
  ZoneArray = Array of ArtikelArray;


en we hebben 2 variabelen, A en B. A willen we kopieren naar B:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var
  nZoneLus, nArtikelLus, nLength: Integer;
begin
  nLength:=High(A)-Low(A);
  SetLength(B,nLength);
  For nZoneLus:=Low(A) to High(A) do
     begin
        nLength:=High(A[nZoneLus])-Low(A[nZoneLus]);
        SetLength(B[nZoneLus],nLength);
        For nArtikelLus:=Low(A[nZoneLus]) to High(A[nZoneLus]) do
          begin
            B[nZonelus][nArtikelLus].Index:=A[nZonelus][nArtikelLus].Index;
            B[nZonelus][nArtikelLus].Naam:=A[nZonelus][nArtikelLus].Naam;
            B[nZonelus][nArtikelLus].Aantal:=A[nZoneLus][nArtikelLus].Aantal;
          end;
     end;
end;

[ Voor 3% gewijzigd door Verwijderd op 04-06-2003 21:03 ]


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Verwijderd schreef op 04 June 2003 @ 21:01:
...uitleg over hoe het moet
_/-\o_ THNX!!! Hezik je bent een koning, ik ga het morgen allemaal meteen proberen! En tevens die link van jou eens volgen :7

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:45

Creepy

Tactical Espionage Splatterer

Oscar Mopperkont schreef op 04 juni 2003 @ 21:48:
[...]


_/-\o_ THNX!!! Hezik je bent een koning, ik ga het morgen allemaal meteen proberen! En tevens die link van jou eens volgen :7
En mocht je eenmaal met objecten en objects lists kunnen omgaan, dan kan je heel die loop van low() naar high() vervangen door een MyList1.assign(MyList2) ;)

Een beetje Delphi tutorial leert je met objecten werken.. dan nog "leren" een beetje OO te denken :)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Creepy schreef op 04 June 2003 @ 22:21:
[...]

En mocht je eenmaal met objecten en objects lists kunnen omgaan, dan kan je heel die loop van low() naar high() vervangen door een MyList1.assign(MyList2) ;)

Een beetje Delphi tutorial leert je met objecten werken.. dan nog "leren" een beetje OO te denken :)
Tja, ik heb de beginners tutorial gedaan van about delphi, maar daar leer je niks over OO programmeren. Alleen heel basis met Delphi omgaan, ze hebben wel meer tutorials, maar tot nu toe ging het allemaal wel goed, zonder het OO denken.

Heb namelijk wel een heeeeeel klein beetje Pascal programmeren gehad, maar dat is niet OO, en dat blijkt nu ook wel ;)

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Geldt dit verhaal van 1 voor 1 kopieren trouwens alleen voor arrays? Want ik heb bij de zelfgmaakte record "ArtikelRec" volgens mij nergens last van.

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Verwijderd schreef op 04 June 2003 @ 21:01:
Voor het hoe en wat over het opzetten van een objectmodel verwijs ik je even naar wat documentatie, om specifiek te zijn het boek 'mastering delphi' van marco cantu. Deze is voor elke delphi-versie te krijgen, en is eigenlijk een must-have voor elke serieuze delphi programmeur.

www.marcocantu.com

Dan deel 2, hoe de ene array naar de andere kopieren.. we gaan uit van:
Delphi:
1
2
3
4
5
6
7
ArtikelRec =  record
                Index: integer;
                Naam: String;
                Aantal: Integer;
                end;
  ArtikelArray = Array of ArtikelRec;
  ZoneArray = Array of ArtikelArray;


en we hebben 2 variabelen, A en B. A willen we kopieren naar B:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var
  nZoneLus, nArtikelLus, nLength: Integer;
begin
  nLength:=High(A)-Low(A);
  SetLength(B,nLength);
  For nZoneLus:=Low(A) to High(A) do
     begin
        nLength:=High(A[nZoneLus])-Low(A[nZoneLus]);
        SetLength(B[nZoneLus],nLength);
        For nArtikelLus:=Low(A[nZoneLus]) to High(A[nZoneLus]) do
          begin
            B[nZonelus][nArtikelLus].Index:=A[nZonelus][nArtikelLus].Index;
            B[nZonelus][nArtikelLus].Naam:=A[nZonelus][nArtikelLus].Naam;
            B[nZonelus][nArtikelLus].Aantal:=A[nZoneLus][nArtikelLus].Aantal;
          end;
     end;
end;
Zit toch nog een klein foutje in, de nlengte moet +1 zijn.

Verder heb ik er een procedure van gemaakt, zodat ik het niet telkens hoef te herhalen, code is dus identiek.

Procedure TfrMain.KopieerZA (ZA1, ZA2 : ZoneArray);
enz....

Maar als ik die aanroep, dan doet die procedure het prima. Maar er gebeurt uiteindelijk niks mee :?

Maak ik dan wederom bijna dezelfde fout?

Roep hem dus aan met Kopieer(BesteZA, ZA).

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:45

Creepy

Tactical Espionage Splatterer

Oscar Mopperkont schreef op 05 June 2003 @ 08:34:
Geldt dit verhaal van 1 voor 1 kopieren trouwens alleen voor arrays? Want ik heb bij de zelfgmaakte record "ArtikelRec" volgens mij nergens last van.
Het geld voor dynamische arrays en objecten. Voor records en normale var's geld dit niet nee.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Creepy schreef op 05 June 2003 @ 09:35:
[...]

Het geld voor dynamische arrays en objecten. Voor records en normale var's geld dit niet nee.
Dus het kan nog ietsjes simpeler dan Hezik voorstelt? Dus niet een voor 1 alle dingen uit de record kopieren (naam, index, aantal), maar gewoon de record kopieren?

Verder werkt het wel als ik het in een functie plaats. Dus ik heb van de procedure een functie gemaakt, met als input een ZoneArray en als output ook. Waarom werkt dat eigenlijk wel?

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Verwijderd schreef op 04 June 2003 @ 21:01:
Voor het hoe en wat over het opzetten van een objectmodel verwijs ik je even naar wat documentatie, om specifiek te zijn het boek 'mastering delphi' van marco cantu. Deze is voor elke delphi-versie te krijgen, en is eigenlijk een must-have voor elke serieuze delphi programmeur.

www.marcocantu.com
Weet je misschien ook goede site met online informatie over het opzetten van een objectmodel?

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Creepy schreef op 05 juni 2003 @ 09:35:
[...]

Het geld voor dynamische arrays en objecten. Voor records en normale var's geld dit niet nee.
Waarom geldt het eigenlijk voor dynamische arrays en objecten? Ik zie niet in wat voor functionaliteit het geeft. Waaro zou je met twee verschillende namen naar 1 geheugenadres willen wijzen?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:45

Creepy

Tactical Espionage Splatterer

Oscar Mopperkont schreef op 10 June 2003 @ 08:35:
[...]


Waarom geldt het eigenlijk voor dynamische arrays en objecten? Ik zie niet in wat voor functionaliteit het geeft. Waaro zou je met twee verschillende namen naar 1 geheugenadres willen wijzen?
Lees het pointer verhaal hierboven even door (en zoek anders ff een tutorial over pointers).

Als je dus zegt array1:=array2 dan stel je de pointers (!!) gelijk, dus wijzen de array's allebei naar hetzelfde stuk geheugen. Dat is alles. Vandaar dat je bij een dynamische array item voor item moet kopieren, en vandaar dat er ook zoiets bestaat als een TObject.assign() dat alle properties van een object kopieert.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Creepy schreef op 10 June 2003 @ 09:27:
[...]

Lees het pointer verhaal hierboven even door (en zoek anders ff een tutorial over pointers).

Als je dus zegt array1:=array2 dan stel je de pointers (!!) gelijk, dus wijzen de array's allebei naar hetzelfde stuk geheugen. Dat is alles...
Dat snap ik dus. Maar ik vraag mij af waarom Delphi daarvoor gekozen heeft. Waarom krijgt het bij dynamische arrays en objecten alleen dezelfde pointer, en bij de rest wel een nieuw stuk geheugen met dezelfde waarde (en dus ook een nieuwe pointer)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:45

Creepy

Tactical Espionage Splatterer

Oscar Mopperkont schreef op 10 June 2003 @ 09:38:
[...]


Dat snap ik dus. Maar ik vraag mij af waarom Delphi daarvoor gekozen heeft. Waarom krijgt het bij dynamische arrays en objecten alleen dezelfde pointer, en bij de rest wel een nieuw stuk geheugen met dezelfde waarde (en dus ook een nieuwe pointer)
Omdat tijdens het compileren nog niet bekend is hoe groot het stuk geheugen is waar de pointer naar wijst. Dit is alleen tijdens runtime bekend. En dan kan de compiler dus ook niet bepalen wat er precies gekopieerd moet worden, dit kan pas at runtime. Vandaar dat je dynamische array's element voor element moet kopieren, en dat TObjects een assign method hebben.

Voor paramaters aan een functie is het om performance redenen en geheugen gebruik meestal ook beter om "grote" variabelen (dus dynamische arrays en object) by reference mee te geven (i.p.v. by value zoals met "normale" variabelen). Dit gebeurt dus nu automatisch mar array's en objecten (aangezien je alleen de pointer mee geeft). Anders raakt de stack zo snel vol ;)

[ Voor 4% gewijzigd door Creepy op 10-06-2003 10:16 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Verwijderd schreef op 04 June 2003 @ 21:01:
Voor het hoe en wat over het opzetten van een objectmodel verwijs ik je even naar wat documentatie, om specifiek te zijn het boek 'mastering delphi' van marco cantu. Deze is voor elke delphi-versie te krijgen, en is eigenlijk een must-have voor elke serieuze delphi programmeur.

www.marcocantu.com
Je had wel ff mogen zeggen dat dat boek dus ook gewoon te downen is van internet! Het is dat ik er nu toevallig tegen aangelopen ben, en hem nu dus als pdf file heb >:)

Nu nog ff 1071 pagina's uiprinten en inbinden :/

Nog tips voor het uitrpinten en inbinden?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Oscar Mopperkont schreef op 16 June 2003 @ 09:47:Je had wel ff mogen zeggen dat dat boek dus ook gewoon te downen is van internet!
Dat is een niet legale versie, oftwel warez. Het echte boek, met pdf, moet je gewoon kopen.

We adore chaos because we like to restore order - M.C. Escher


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
LordLarry schreef op 16 juni 2003 @ 10:26:
[...]


Dat is een niet legale versie, oftwel warez. Het echte boek, met pdf, moet je gewoon kopen.
Heb je gelijk aan natuurlijk. En het is een beetje grijs gebeid of je wel of niet mag aangeven of er een digale versie van op i-net rondzwerft.

Nouja, iig heb ik het nu, uiteraard naast de hard-copy die ik ga aanschaffen ;)
Pagina: 1