Toon posts:

[Delphi] Toewijzen array aan andere variabele *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik zit met het probleem dat ik een access violation krijg (dus geheugen probeer aan te spreken wat eigenlijk niet mag).

Ik heb 2 variabelen voor speler gegevens (FOriginalPlayers en FOtherPlayers).

Delphi:
1
2
3
4
5
6
  TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;

  FOriginalPlayers: TPlayerArray;
  FOtherPlayers: TPlayerArray;

  FPlayers: TPlayerArray;


Nu kan het zo zijn dat ik of gebruik moet maken van FOriginalPlayers of FOtherPlayers. Er wordt daarom een procedure aangeroepen die bepaalt welke spelers aan de beurt zijn.

Binnen die procedure wordt dit uitgevoerd:

Delphi:
1
2
3
4
5
6
7
8
  if (Andere spelers aan de beurt) then
  begin
    FPlayers := FOtherPlayers;
  end
  else
  begin
    FPlayers := FOriginalPlayers;
  end;



Vervolgens gebruik ik overal in het programma waar ik speler gegevens nodig heb de volgende functie:
Delphi:
1
2
3
4
  function GetPlayers: TPlayerArray;
  begin
    Result := FPlayers;
  end;


Maar dit gaat dus op een of andere manier fout. Maar dat toekennen aan FPlayers, daar wordt er toch voor gezord dat FPlayers naar hetzelfde adres wijst als FOtherPlayers of FOriginalPlayers?

  • Cai
  • Registratie: December 2001
  • Laatst online: 09:43

Cai

Ik weet niet of dat met Delphi kan, maar probeer uit te zoeken of je met pointers kan werken, dat is in C namelijk de oplossing.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 29 September 2003 @ 11:03:
Ik zit met het probleem dat ik een access violation krijg (dus geheugen probeer aan te spreken wat eigenlijk niet mag).

Ik heb 2 variabelen voor speler gegevens (FOriginalPlayers en FOtherPlayers).

Vervolgens gebruik ik overal in het programma waar ik speler gegevens nodig heb de volgende functie:
Delphi:
1
2
3
4
  function GetPlayers: TPlayerArray;
  begin
    Result := FPlayers;
  end;


Maar dit gaat dus op een of andere manier fout.
Je krijgt dus die access violation? En waar in je code krijg je die??
Maar dat toekennen aan FPlayers, daar wordt er toch voor gezord dat FPlayers naar hetzelfde adres wijst als FOtherPlayers of FOriginalPlayers?
Klopt.

Weet je zeker dat je niet ergens in een lokale var een array aanmaakt die je dan weer teruggeeft met een result? Dat gaat namelijk mis ;)

En één standaard opmerking die ik eigenlijk altijd geef: Waarom een (dynamische) array gebruiken als je ook een TObjectList (en varianten) hebt? ;)

[ Voor 22% gewijzigd door Creepy op 29-09-2003 11:47 ]

"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

Topicstarter
Creepy schreef op 29 september 2003 @ 11:46:Je krijgt dus die access violation? En waar in je code krijg je die??
Zodra ik GetPlayers[..] doe gaat het fout (dus wanneer ik gebruik ga maken van die array)
Weet je zeker dat je niet ergens in een lokale var een array aanmaakt die je dan weer teruggeeft met een result? Dat gaat namelijk mis ;)
Nee het staat allemaal in 1 object en zijn gewoon private variabelen
En één standaard opmerking die ik eigenlijk altijd geef: Waarom een (dynamische) array gebruiken als je ook een TObjectList (en varianten) hebt? ;)
Zou kunnen, maar je hebt zoiezo wel wat meer overhead dan.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Eh, FPlayers is een private var?

Ik moet eens opzoeken hoe het precies in elkaar steekt in Delphi, maar het lijkt mij dat als je een adres van een private var toekent aan het result van een public method dat het mis kan gaan. Check eens of het result van de functie is wat jij verwacht. (en dus niet met de debugger in de functie zelf, maar het result van de functie toekennen aan een een lokale var). Want wat je nu probeert met GetPlayers[1] is direct een private var aan te spreken.

En waarom niet een
Delphi:
1
Property players: TPlayerArray read FPlayers;

"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


  • Aetje
  • Registratie: September 2001
  • Laatst online: 18-12-2025

Aetje

Troubleshooting met HAMERRR

In jouw geval defineer je TPlayerArray als een object. Je wilt echter een type denk ik. Probeer:
code:
1
2
3
4
5
6
7
8
9
10
type TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;

function EenFunctie:output;
begin
  var FOriginalPlayers: TPlayerArray;
  var FOtherPlayers: TPlayerArray;
  var FPlayers: TPlayerArray;

<< rest code >>
end;


Indien je TPlayerArray echt als een object aan wil maken moet je het object een constructor en een destructor geven. Anders maak je idd alleen (lege) pointers aan.

Forget your fears...
...and want to know more...


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Aetje schreef op 29 September 2003 @ 13:23:
In jouw geval defineer je TPlayerArray als een object. Je wilt echter een type denk ik. Probeer:
code:
1
2
3
4
5
6
7
8
9
10
type TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;

function EenFunctie:output;
begin
  var FOriginalPlayers: TPlayerArray;
  var FOtherPlayers: TPlayerArray;
  var FPlayers: TPlayerArray;

<< rest code >>
end;


Indien je TPlayerArray echt als een object aan wil maken moet je het object een constructor en een destructor geven. Anders maak je idd alleen (lege) pointers aan.
Delphi:
1
2
3
4
5
6
TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;

  FOriginalPlayers: TPlayerArray;
  FOtherPlayers: TPlayerArray;

  FPlayers: TPlayerArray;

Dit komt uit de topicstart. Conclusie: het zijn types en geen objecten.

Als ik het zo lees heeft Tokkie een object waarin hij die typen gebruikt ;) (en uiteraard moet dat object wel zijn aangemaakt)

[ Voor 5% gewijzigd door Creepy op 29-09-2003 13:47 ]

"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


  • Aetje
  • Registratie: September 2001
  • Laatst online: 18-12-2025

Aetje

Troubleshooting met HAMERRR

idd. Ik zie echter nergens een object aangemaakt en/of volledig gedefineerd worden. Dus hij maakt een lege pointer aan waar ie vervolgens mee gaat werken. Nogal logisch dat je dan een zut AV's krijgt.

Forget your fears...
...and want to know more...


  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Maak je de objecten in je array van tevoren aan? Zoniet, dan zul je zoiets moeten doen:

if GetPlayers[index] = nil then begin
GetPlayers[index] := TPlayer.Create(constructor params);
end if;

Working @ http://www.tricode.nl


Verwijderd

Topicstarter
Alles staat inderdaad in een object, waarvan ik ook daadwerkelijk een instantie aanmaak.

Ik snap niet echt waarom ik voor die Player gegevens ook een object aan zou moeten maken?

  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Verwijderd schreef op 29 September 2003 @ 14:11:
Alles staat inderdaad in een object, waarvan ik ook daadwerkelijk een instantie aanmaak.
Ik begrijp je niet helemaal, kun je de code van het aanmaken van de objecten misschien posten?

Working @ http://www.tricode.nl


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Beowulf27 schreef op 29 September 2003 @ 14:19:
[...]

Ik begrijp je niet helemaal, kun je de code van het aanmaken van de objecten misschien posten?
Die players array's zijn private variabelen in een class. Die GetPlayers is een public method van die class, en van die class maakt tokkie ook daadwerkelijk een een instantie aan. (zo, duidelijker kan ik het niet uitleggen :P )

Wat is TPlayer overigens? Als dat een class is zul je die inderdaad wel moeten instantieren (per array item), maar als dat een record is hoeft dat uiteraard weer niet (alhoewel ik niet denk dat je zo'n fout maakt, maar goed..

[ Voor 22% gewijzigd door Creepy op 29-09-2003 14:31 ]

"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

Topicstarter
Dit is alle code waar het om gaat:

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
type
  TPlayer = record
    PlayerID: Integer;
    Synchronized: Boolean;
    Name: String;
    StartPosition: Integer;
    HCP: Integer;
    MemberID: String;
    PreviousTotal: Integer; // Total score van voorgaande serie
    BumperEnable: Boolean;
    Picture: TBitmap;

    MaxThrows: Integer;
    ThrowCount: Integer;
    PlayerReady: Boolean;
    FallOut: Boolean;

    BlindScore: Boolean;
    BlindScoreNumber: Integer;
    ScoreGame: TScoreGameArray;
  end;

  TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;


  TBowlingLane = class(TObject)
  private
    FPlayers: TPlayerArray;
    FOriginalPlayers: TPlayerArray;
    FOtherPlayers: TPlayerArray;

    ...... heel veel andere variabelen en methodes
  public
    procedure SetAMAndere(AMAndere: Boolean);

    function GetPlayers: TPlayerArray;
  end;

procedure TBowlingLane.SetAMAndere(AMAndere: Boolean);
begin
  FAMAndere := AMAndere;

  if AMAndere then
    FPlayers := FOtherPlayers
  else
    FPlayers := FOriginalPlayers;
end;

function TBowlingLane.GetPlayers: TPlayerArray;
begin
  Result := FPlayers;
end;

  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Oke, je hoeft TPlayer dus niet te 'createn', omdat het een record is. Objecten in het record moet je wel createn (zoals Picture). In principe zou het opvragen van bijvoorbeeld de naam van een player wel goed moeten gaan, deze zal initieel wel leeg zijn uiteraard. Als je dit doet:

ShowMessage(GetPlayers[1].Naam), gaat dit goed? (Je index begint overigens bij 1, dus niet [0] gaan gebruiken.)

Als je picture benaderd gaat het dus wel fout, want dit object is nog niet aangemaakt.

Working @ http://www.tricode.nl


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 29 September 2003 @ 11:03:
Delphi:
1
2
3
4
5
6
  TPlayerArray = array[1..MAX_PLAYERS_SELECTION_LIST] of TPlayer;

  FOriginalPlayers: TPlayerArray;
  FOtherPlayers: TPlayerArray;

  FPlayers: TPlayerArray;


Maar dit gaat dus op een of andere manier fout. Maar dat toekennen aan FPlayers, daar wordt er toch voor gezord dat FPlayers naar hetzelfde adres wijst als FOtherPlayers of FOriginalPlayers?
Nee, dus toch niet zie ik net. Dit gebeurt alleen bij dynamische array's, maar TPlayerArray is een statische :P .
De items van de ene array zullen naar de andere array worden gekopieerd, het zijn dus allemaal verschillende array's met andere items!
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var test: TBowlingLane;
    player: TPlayer;
    players: TPlayerArray;
begin
 test:=TBowlingLane.Create;
 test.SetAMAndere(false);

 players:=test.GetPlayers;
 player:=players[1];
 player.name:='woei';

 players[1]:=player;

 showmessage(test.getPlayers[1].name);
 showmessage(players[1].name);
 showmessage(player.name);

 test.free;

Dit is een leuke. Met een dynamische array zou elke showmessage hetzelfde moeten geven. Nu geeft de eerste showmessage niks, en de laatste twee geven allebei "woei". Leuk detail: een "test.getplayers[1].name" geeft een leuke compiler error :P

Ik gok dat als je er een dynamische array van maakt dat het wel werkt zoals je bedoelt (vergeet dan niet in de constructor van je object de array size te zetten, en de array weer leeg te maken in je destructor

"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


  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Creepy schreef op 29 september 2003 @ 15:02:
[...]
Ik gok dat als je er een dynamische array van maakt dat het wel werkt zoals je bedoelt (vergeet dan niet in de constructor van je object de array size te zetten, en de array weer leeg te maken in je destructor
Dynamisch of statisch heeft er niets mee te maken. Het zou nu al moeten werken, kijk naar dit voorbeeld (als toevoeging op eerdere code):

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var
  Form1: TForm1;
  a : TBowlingLane;

procedure TBowlingLane.bla;
begin
  FOriginalPlayers[1].Name := 'hallo';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  a := TBowlingLane.Create();
  a.bla;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  a.SetAMAndere(true);
  showmessage(a.getplayers[1].Name);
  a.SetAMAndere(false);
  showmessage(a.getplayers[1].Name);
end;

Zoals verwacht is het eerste resultaat leeg, terwijl de tweede keer 'hallo' wordt getoond.

Working @ http://www.tricode.nl


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Beowulf27 schreef op 29 September 2003 @ 15:27:
[...]

Dynamisch of statisch heeft er niets mee te maken. Het zou nu al moeten werken, kijk naar dit voorbeeld (als toevoeging op eerdere code):

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var
  Form1: TForm1;
  a : TBowlingLane;

procedure TBowlingLane.bla;
begin
  FOriginalPlayers[1].Name := 'hallo';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  a := TBowlingLane.Create();
  a.bla;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  a.SetAMAndere(true);
  showmessage(a.getplayers[1].Name);
  a.SetAMAndere(false);
  showmessage(a.getplayers[1].Name);
end;

Zoals verwacht is het eerste resultaat leeg, terwijl de tweede keer 'hallo' wordt getoond.
Ja klopt. Omdat de inhoudt van de ene array wordt gekopieerd naar de andere, en omdat je het aan 1 van de private array's toekent. Probeer maar eens buiten het bowlinglane object iets toe te kennen aan één van de private array's, dat gaat je niet lukken ;)

Tuurlijk is dit niet het "precieze" probleem, maar er wordt hier wel een denkfout gemaakt waardoor het ergens anders in de code best eens mis zou kunnen gaan.

"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


  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Creepy schreef op 29 september 2003 @ 15:30:
[...]
Probeer maar eens buiten het bowlinglane object iets toe te kennen aan één van de private array's, dat gaat je niet lukken ;)

Tuurlijk is dit niet het "precieze" probleem, maar er wordt hier wel een denkfout gemaakt waardoor het ergens anders in de code best eens mis zou kunnen gaan.
Ah, ok, dan begrijp ik wat je bedoeld. Maar dan kan TS beter dit gaan gebruiker:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type
  PPlayerArray = ^TPlayerArray;

function GetPlayers: PPlayerArray;

procedure TBowlingLane.SetAMAndere(AMAndere: Boolean);
begin
  FAMAndere := AMAndere;
end;

function TBowlingLane.GetPlayers: PPlayerArray;
begin
  if FAMAndere then
    result := @FOtherPlayers
  else
    result := @FOriginalPlayers;
end;


Hiermee kun je zowel lezen als schrijven naar de juiste array:

Delphi:
1
2
3
4
5
6
  a.SetAMAndere(true);
  showmessage(a.getplayers[1].Name);
  a.SetAMAndere(false);
  showmessage(a.getplayers[1].Name);
  a.getplayers[1].Name := 'dit werkt wel';
  showmessage(a.getplayers[1].Name);

Working @ http://www.tricode.nl


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Een Dynamisch Array is een Reference variable en zal dus hetzelfde werken als in jouw pointer voorbeeld. Het is dus wel een mogelijke oplossing.

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


  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
LordLarry schreef op 29 September 2003 @ 15:55:
Een Dynamisch Array is een Reference variable en zal dus hetzelfde werken als in jouw pointer voorbeeld. Het is dus wel een mogelijke oplossing.
Een dynamische array is een reference variabele? Pardon? Een array is een verzameling objecten, een variabele bevat 1 object (dit kan een array zijn). En dynamisch wil alleen maar zeggen dat de lengte van de array runtime kan worden aangepast.

Dus om dynamische arrays nu met reference variabelen te vergelijken...?

Working @ http://www.tricode.nl


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Beowulf27 schreef op 29 september 2003 @ 16:10:
[...]

Een dynamische array is een reference variabele? Pardon? Een array is een verzameling objecten, een variabele bevat 1 object (dit kan een array zijn). En dynamisch wil alleen maar zeggen dat de lengte van de array runtime kan worden aangepast.

Dus om dynamische arrays nu met reference variabelen te vergelijken...?
Ja, want als je dynamische array's aan elkaar gaat toekennen (bijv.) dan wordt dus NIET de inhoudt van de array overgenomen, maar verwijzen ze allebij naar precies dezelfde items omdat alleen de referentie naar de plek in het geheugen wordt gekopieerd. (in feite is het dus een pointer ook wel een referentie genoemd ;) ).

Overigens geeft Delphi 6 in elk geval nog steeds een foutmelding op a.getplayers[1].name dat er niet aan de "left side" niet "assigned" kan worden :P

[ Voor 13% gewijzigd door Creepy op 29-09-2003 16:28 ]

"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


  • Beowulf27
  • Registratie: September 2003
  • Laatst online: 11-09-2024
Creepy schreef op 29 September 2003 @ 16:22:
[...]
Overigens geeft Delphi 6 in elk geval nog steeds een foutmelding op a.getplayers[1].name dat er niet aan de "left side" niet "assigned" kan worden :P
Hm, mijn Delphi 6 slikt het als zoete koek :)

Working @ http://www.tricode.nl


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 00:12

Tomatoman

Fulltime prutser

Verwijderd schreef op 29 September 2003 @ 12:10:
[...]

En één standaard opmerking die ik eigenlijk altijd geef: Waarom een (dynamische) array gebruiken als je ook een TObjectList (en varianten) hebt?

Zou kunnen, maar je hebt zoiezo wel wat meer overhead dan.
Een beetje overhead, nou en? Sinds niemand meer met een XT of AT werkt is dit voor niet-tijdkritische code absoluut een non-issue. Misschien bespaar je een milliseconde, maar wie merkt dat nou?

No offence, maar dit is een typisch voorbeeld van de verkeerde optimalisaties uitvoeren. Je kunt de extra tijd die je nodig hebt om dat array-verhaal rond te breien beter steken in andere delen van je programma.

Een goede grap mag vrienden kosten.

Pagina: 1