Getting pointers from array
Blitz3D Forums/Blitz3D Beginners Area/Getting pointers from array
| ||
I've got this testprogram:Type Station Field Name$ Field FileName$ Field PosX% Field PosY% Field PosZ% End Type Dim ArrayStations.Station(15, 10) For i = 1 To 15 For j = 1 To 10 ArrayStations(i, j) = New Station Next Next For i = 1 To 10 Print ArrayStations(1, i) Next WaitKey() But it gives an error on the line with the Print-command. My intension was to have a different amount of (space)stations in each sector of space. The first index-number (1-15) of the array is used as the sectornumber, the second one is used as the stationnumber. One given sector may contain all 10 stations, where other sectors may contain only 1. Since it is unneccessary to create ALL type-instances (which consumes memory if you have lots of fields), I only create a new type-instance when there's supposed to be a station in that sector (I read all data from txt-files, which works perfectly). For looping through all stations in a specific sector, I thought I could check if the index of the array is bigger than "0". If it is, do some stuff with the data of that type-instance. I thought this would work, as a pointer is (AFAIK) just a memory-address, which is an integer. This way I could check if a specific arrayindex held a value bigger than "0". If it was bigger, than it would point to a type-instance and the station exists. In this example, in sector 2 exists only 3 stations (not 10): For i = 1 To 10 If ArrayStations(2, i) <> 0 Then ; do stuff here with the data of this type-instance EndIf Next But it doesn't work, as I get "Illegal type conversion error" on the IF-statement. Now I bypassed this approach with some extra fields in another type (which existed also) and is used by another array, which hold the exact number of stations each sector contains. Type Sector Field Name$ Field StationsInSector% End Type Type Station Field Name$ Field FileName$ Field PosX% Field PosY% Field PosZ% End Type Dim ArraySectors.Sector(15) Dim ArrayStations.Station(15, 10) ; Fill the sector-array with pointers to all sector-instances For i = 1 To 15 ArraySectors(i) = New Sector Next ; some other routines come here to load data from txt-files, which also state ; the number of stations in each sector ; Only create type-instances for the number of stations in each sector which are needed For i = 1 To 15 For j = 1 To ArraySectors(i)\StationsInSector% ArrayStations(i, j) = New Station Next Next ; Here are some routines which load data from the txt-file ; and put all values into the fields of the type-instances ; print the name of all stations in the galaxy For i = 1 To 15 For j = 1 To ArraySectors(i)\StationsInSector% Print ArrayStations(i, j)\Name$ Next Next WaitKey() In this last example, the program creates only the type-instances which are needed, to save some memory (unused type-instances are a total waste). So if all sectors would have only 1 station in them, then only 1 secondary index (the second indexnumber) is a valid link to a type-instance. Is there no other way of doing this? I know I could loop through ALL Station-type-instances (which have a field which holds the name of the sector they are located in), but this would be too big/long. As all routines in the game only need to know data about stuff in the sector where the player is located (cannot be in 2 or more sectors at once). |
| ||
Type Station Field Name$ Field FileName$ Field PosX% Field PosY% Field PosZ% End Type Dim ArrayStations.Station(15, 10) For i = 1 To 15 For j = 1 To 10 ArrayStations(i, j) = New Station arraystations(i,j)\name=Mid$("abcdefghijklmnopqrst",j,1) Next Next For i = 1 To 10 Print Handle(arraystations(1,i)) Print ArrayStations(1, i)\name Next WaitKey() Try the above which is almost identical to your original. To print the value of a type instance handle use handle(typevar). |
| ||
You will get problems using Handle(). Say ArrayStation(1,5) doesn't contain a type pointer, then Handle(ArrayStation(1,5)) will cause an error. [edit] Actually, this won't cause an error. It just returns 0. Oh, well. Take your pick :) [edit] Instead, just explicitly cast the type pointer to an int before comparing it to zero to see if it's a valid pointer: Type Station Field Name$ Field FileName$ Field PosX% Field PosY% Field PosZ% End Type Dim ArrayStations.Station(15, 10) For i = 1 To 15 For j = 1 To Rand(0,10) ArrayStations(i, j) = New Station arraystations(i,j)\name=Mid$("abcdefghijklmnopqrst",j,1) Next Next For i = 1 To 15 For j = 1 To 10 ptr = Int(arraystations(i,j)) If ptr Then Print ptr + " " + ArrayStations(i,j)\name Next Next WaitKey() TBH, I was surprised this worked as I'm sure I tried something similar in the past. Seems to work fine, though. I must be thinking of something else. :) |
| ||
An alternative:Type Station Field Name$ Field FileName$ Field PosX% Field PosY% Field PosZ% End Type Dim ArrayStations.Station(15, 10) For i = 1 To 15 For j = 1 To 10 ArrayStations(i, j) = New Station Next Next For i = 1 To 10 Print Str(ArrayStations(1, i)) Next WaitKey() End |
| ||
The correct way to see if a Type object exists is by comparing to Null. Casting to an integer and comparing to zero is not reliable. Type T Field n End Type Dim a.T( 5 ) a(4) = New T For i = 0 To 5 If a(i) <> Null Then Print "Element " + i + " exists." If Int( a(i) ) <> 0 Then Print "Pointer a(" + i + ") is non-zero." Next Print Delete a(4) For i = 0 To 5 If a(i) <> Null Then Print "Element " + i + " exists." If Int( a(i) ) <> 0 Then Print "Pointer a(" + i + ") is non-zero." Next WaitKey : End |
| ||
Thanks all, I can really use those things, especially the comparison with Null, didn't know about that yet. But as you stated, Floyd, the comparison with Int(...) will also work, as long as the type-instance exists and wasn't created before (checked that with commenting the line "a(4) = New T"). For my game, both ways will work the same (Int and Null), because the type-instances are created when loading data and are only destroyed (or deleted) when the game quits. The game needs all data in memory (which speeds up loading times between sector-jumps). When the game is running, no type-instance is deleted (for stations, sectors, asteroids, jumpgates and many more stuff in space (except spaceships I think, I'm not that far yet). If I get it right, the comparison to Null actually checks if the pointer (that's stored in the array) in valid (points to a existing type-instance) and the Int-comparison just compares the integer-value of that pointer with 0 (and doesn't check if that pointer is a valid one). Is this correct? Or is it just that an empty array-index holds the value Null instead of "0" (in case of an array which holds pointers)? |
| ||
God, I feel like such a numpty! :) Of course a comparison to Null is the right way to do it. I think I got suduced by the original code that needed to actually print the pointer. Well, that's my excuse and I'm sticking to it! :P If I get it right, the comparison to Null actually checks if the pointer (that's stored in the array) in valid (points to a existing type-instance) and the Int-comparison just compares the integer-value of that pointer with 0 (and doesn't check if that pointer is a valid one). Is this correct? Yes, from Floyd's code, this does indeed seem to be the case. This surprised me as I had no idea a comparison to Null in Blitz worked like this. It's been a while but I'm sure a comparison to NULL in C/C++ isn't this helpful. Thanks for the tip, Floyd! ;) |