Arrays

Is there a way to get the size of an Array the way sizeof() lets you get the size of an array?
Doorsbert - Tue Apr 21 22:05:59 EDT 2009

Re: Arrays
Tony_Goodman - Wed Apr 22 02:26:26 EDT 2009

The Array type is dynamic and expands automatically to accomodate whatever you insert, so it does not have a size as such.

It is up to you to keep track of the "size" of the array, i.e. how many rows/columns you have used.

Re: Arrays
Doorsbert - Wed Apr 22 02:42:06 EDT 2009

Tony_Goodman - Wed Apr 22 02:26:26 EDT 2009
The Array type is dynamic and expands automatically to accomodate whatever you insert, so it does not have a size as such.

It is up to you to keep track of the "size" of the array, i.e. how many rows/columns you have used.

That is very surprising and disappointing because not every application of an array would be in the same unit. What I want to do is have a function that parses a string and returns an array that contains the tokens that were in that string. Without a size() function that would mean there would have to be int references passed in which is doable but undesirable.

Re: Arrays
Tippers - Wed Apr 22 03:28:28 EDT 2009

Doorsbert - Wed Apr 22 02:42:06 EDT 2009
That is very surprising and disappointing because not every application of an array would be in the same unit. What I want to do is have a function that parses a string and returns an array that contains the tokens that were in that string. Without a size() function that would mean there would have to be int references passed in which is doable but undesirable.

You could use a function of the form:

int parseString (string toParse, Array &parsed) {
...
}

Pass it the string and a created array, get it to parse the string into the array and return the number of elements. This also gives you the option of returning 0 for 'no elements' or a negative number for an error.

Re: Arrays
Doorsbert - Wed Apr 22 13:31:46 EDT 2009

Tony_Goodman - Wed Apr 22 02:26:26 EDT 2009
The Array type is dynamic and expands automatically to accomodate whatever you insert, so it does not have a size as such.

It is up to you to keep track of the "size" of the array, i.e. how many rows/columns you have used.

"The Array type is dynamic and expands automatically to accomodate whatever you insert, so it does not have a size as such."

The interpreted languages like Perl and Python and Ruby all have datatypes that expand automatically to accomodate whatever you type, and they all let you determine the current size of the object. I think DXL is unique in deciding not to give users the capability to determine the current size. I would hope they reconsider this decision.

Re: Arrays
Doorsbert - Wed Apr 22 13:32:58 EDT 2009

Tippers - Wed Apr 22 03:28:28 EDT 2009
You could use a function of the form:

int parseString (string toParse, Array &parsed) {
...
}

Pass it the string and a created array, get it to parse the string into the array and return the number of elements. This also gives you the option of returning 0 for 'no elements' or a negative number for an error.

"int parseString (string toParse, Array &parsed) "

Thanks Paul, I think you are right, it is better to return the int rather than the array.

Re: Arrays
Doorsbert - Wed Apr 22 13:38:16 EDT 2009

Doorsbert - Wed Apr 22 13:31:46 EDT 2009
"The Array type is dynamic and expands automatically to accomodate whatever you insert, so it does not have a size as such."

The interpreted languages like Perl and Python and Ruby all have datatypes that expand automatically to accomodate whatever you type, and they all let you determine the current size of the object. I think DXL is unique in deciding not to give users the capability to determine the current size. I would hope they reconsider this decision.

I guess there is a difference between Python and DXL data structures, in that they don't let you pre-allocate space. And then fill it in later. And they aren't two-dimensional. But DXL could still allow the retrieval of the current allocated sizes, if not the current used size.

Re: Arrays
llandale - Wed Apr 22 15:25:53 EDT 2009

Here are the 'array' commands in the doors.exe file; not counting a couple attribute commands that accept Array types:

void ::do (_y&, ArraySect__, void) ArrayDo
ArraySect__ array(Array,int,int,int,int) mkArrayRef
string get(Array,int,int,int) ArrayStringGet
_x get(Array,int,int) ArrayGet
void zeroArray(Array) ArrayZero
void printCharArray(Array,Stream,int,int,int,int) ArrayPrintChar
void putString(Array,string,int,int) ArrayPutString
void put(Array,_x,int,int) ArrayPut
void delete(Array) ArrayDelete
Array create(int,int) ArrayCreate

Testing, I see that you can indeed 'get' a location outside the current size of the array, no error and of course nothing is returned. the 'ArraySect__' stuff is curious, but that didn't work either. That looks like "for Contents in array(ary, 0, 0, NumX, Numy) do". I tried using that as well as 'cleverl' noError/lastError commands, but nothing worked.

Yes, hard to believe they are that lenient.

I think you can access location -1 -1, and if so I'd be tempted to reserve that location for the current sizes of the Array, and write functions that when data is inserted, it updates if needed the X and Y sizes in that location -1 , -1. A special 'get' function can check to make sure the user is not 'getting' outside the Array current bounds; not that it would do anything with that info.

  • Louie

Re: Arrays
Tippers - Thu Apr 23 08:53:56 EDT 2009

llandale - Wed Apr 22 15:25:53 EDT 2009
Here are the 'array' commands in the doors.exe file; not counting a couple attribute commands that accept Array types:

void ::do (_y&, ArraySect__, void) ArrayDo
ArraySect__ array(Array,int,int,int,int) mkArrayRef
string get(Array,int,int,int) ArrayStringGet
_x get(Array,int,int) ArrayGet
void zeroArray(Array) ArrayZero
void printCharArray(Array,Stream,int,int,int,int) ArrayPrintChar
void putString(Array,string,int,int) ArrayPutString
void put(Array,_x,int,int) ArrayPut
void delete(Array) ArrayDelete
Array create(int,int) ArrayCreate

Testing, I see that you can indeed 'get' a location outside the current size of the array, no error and of course nothing is returned. the 'ArraySect__' stuff is curious, but that didn't work either. That looks like "for Contents in array(ary, 0, 0, NumX, Numy) do". I tried using that as well as 'cleverl' noError/lastError commands, but nothing worked.

Yes, hard to believe they are that lenient.

I think you can access location -1 -1, and if so I'd be tempted to reserve that location for the current sizes of the Array, and write functions that when data is inserted, it updates if needed the X and Y sizes in that location -1 , -1. A special 'get' function can check to make sure the user is not 'getting' outside the Array current bounds; not that it would do anything with that info.

  • Louie

Ok, I'm heading slightly off-topic here, but I had a problem recently with extracting stuff from an array when it hadn't been stored at contiguous locations. It was plainly a bug in my code, but it showed up an 'interesting' feature.

Basically, I'd made the indices into the array global, but forgotten to make the array global. So on the first pass, all worked well. Stuff got put in the array, starting from (0,0), and the indices got updated to point at the next free location. At the end of the function, the array got deleted. On the second pass through, the array got recreated, but now the indices are not starting at (0,0), they're starting at wherever they left off last time. No problem with putting things in the array, and no problem with getting things out of the array. It was only when I tried to use the variables that had been extracted from the array that DOORS crashed. That use could be anything: adding the values together, printing them, finding which was the largest. But DOORS only crashed on use, not on extraction (get).
Fixed it by making the array global. No other changes to the code were required.

Like I say, the code was wrong ... err ... the declarations were misplaced, but I didn't expect that kind of failure -- except, of course, this is DXL... ;)

Re: Arrays
jszlatki - Mon Mar 24 07:01:26 EDT 2014

llandale - Wed Apr 22 15:25:53 EDT 2009
Here are the 'array' commands in the doors.exe file; not counting a couple attribute commands that accept Array types:

void ::do (_y&, ArraySect__, void) ArrayDo
ArraySect__ array(Array,int,int,int,int) mkArrayRef
string get(Array,int,int,int) ArrayStringGet
_x get(Array,int,int) ArrayGet
void zeroArray(Array) ArrayZero
void printCharArray(Array,Stream,int,int,int,int) ArrayPrintChar
void putString(Array,string,int,int) ArrayPutString
void put(Array,_x,int,int) ArrayPut
void delete(Array) ArrayDelete
Array create(int,int) ArrayCreate

Testing, I see that you can indeed 'get' a location outside the current size of the array, no error and of course nothing is returned. the 'ArraySect__' stuff is curious, but that didn't work either. That looks like "for Contents in array(ary, 0, 0, NumX, Numy) do". I tried using that as well as 'cleverl' noError/lastError commands, but nothing worked.

Yes, hard to believe they are that lenient.

I think you can access location -1 -1, and if so I'd be tempted to reserve that location for the current sizes of the Array, and write functions that when data is inserted, it updates if needed the X and Y sizes in that location -1 , -1. A special 'get' function can check to make sure the user is not 'getting' outside the Array current bounds; not that it would do anything with that info.

  • Louie

@IIlandale thanks for your idea: how to go through the array. I helped me how to calculate the size. here you are:

Array a = create(1,1)

put(a,"a",0,0)      //size: 2Bytes --> 'a' and '\n'
put(a,"aa",1,0)
put(a,"aaa",2,0)
put(a,"aaaa",3,0)
put(a,"aaaaa",4,0)
put(a,"aaaaaa",5,0) //size: 7Bytes --> 6x'a' and '\n'

/*

// int get() returns the address of the item, if it zero there is not item any more 
//control with this
print (int get(a,0,0))      //size: 2Bytes --> 'a' (1) + '\n'
print (int get(a,1,0))      //size: 3Bytes --> 'aa' (2) + '\n'
print (int get(a,2,0))
print (int get(a,3,0))
print (int get(a,4,0))
print (int get(a,5,0))

print (int get(a,6,0))
*/

int sizeX = 4294967295 //2^32-1 integers are 32bit long in all plattforms after dxl manual
int sizeY = 4294967295 //2^32-1
int iSize = 0
int iAddr = 0

for Contents in array(a, 0, 0, sizeX , sizeY) do{

 iAddr = (int Contents) //it returns the address of the item if it zero, means end of array
 if(0== iAddr)
  break
 
 iSize++
}


print iSize "\n"
delete a

Re: Arrays
Mathias Mamsch - Mon Mar 24 14:17:24 EDT 2014

jszlatki - Mon Mar 24 07:01:26 EDT 2014

@IIlandale thanks for your idea: how to go through the array. I helped me how to calculate the size. here you are:

Array a = create(1,1)

put(a,"a",0,0)      //size: 2Bytes --> 'a' and '\n'
put(a,"aa",1,0)
put(a,"aaa",2,0)
put(a,"aaaa",3,0)
put(a,"aaaaa",4,0)
put(a,"aaaaaa",5,0) //size: 7Bytes --> 6x'a' and '\n'

/*

// int get() returns the address of the item, if it zero there is not item any more 
//control with this
print (int get(a,0,0))      //size: 2Bytes --> 'a' (1) + '\n'
print (int get(a,1,0))      //size: 3Bytes --> 'aa' (2) + '\n'
print (int get(a,2,0))
print (int get(a,3,0))
print (int get(a,4,0))
print (int get(a,5,0))

print (int get(a,6,0))
*/

int sizeX = 4294967295 //2^32-1 integers are 32bit long in all plattforms after dxl manual
int sizeY = 4294967295 //2^32-1
int iSize = 0
int iAddr = 0

for Contents in array(a, 0, 0, sizeX , sizeY) do{

 iAddr = (int Contents) //it returns the address of the item if it zero, means end of array
 if(0== iAddr)
  break
 
 iSize++
}


print iSize "\n"
delete a

Wow. Now that really freaks me out ... And you really need much to freak me out, because normally I am the one who writes code like this. But your code just seems to be very wrong. It starts with your constants. Try: 

int a = 4294967295 
print a 
// prints 2147483647 
// because DXL uses signed integers and the interpreter will MIN/MAX out of bounds constants

Then you need to know that the whole idea of the 'size' of an array is misleading. When you talk of 'size' what you really mean is the maximum index, that you set in the array. However setting an element at (0, 10) and one at (10,0) does not mean that (10,10) is already set. So the whole concept of 'sizeOf' is wrong for a two dimensional array (and that is probably the reason, why no function exists to actually read those values).

You might want to know if an array item at some X/Y location is already set. Here you need to know that arrays are initialized with 0 bytes. That means, that you can of course test for integer 0 but that only works when you do not put integers in the Array:

Array ar = create(10,10); 

put (ar, 0, 5,5)

int a = (int (get (ar, 5,5))) // 0 we put it in
int b = (int (get (ar, 1,1))) // 0 was initialized by default

print "A = " a " B = " b "\n" // A = 0 B = 0

So that is also something that is not working in ALL cases. DXL is inconsistent here, because there is actually a value that would have been much better for initialization: -2023406815 (or -0x789abcdf) the value for an uninitialized value in DXL. If the DOORS developers would have put this value in the arrays for initialization it would have been much better, because we would get an error if we tried to read a value that has not been set and it would be easy to check:

Array createInitialized (int x, int y) {
  Array ar = create(x,y)
  // initialize the value with 'undefined'
  int i, j; 
  for (i = 0; i < x; i++) for (j = 0; j < y; j++) put (ar, -0x789abcdf, i,j)
  return ar
}
  

bool isSet(Array ar, int x, int y) { 
     return (-0x789abcdf != (int (get (ar, x, y))))
}

Array ar = createInitialized(10,10)

put (ar, 0, 1,1) 

print "Is Set 0/0: " (isSet(ar, 0,0)) "\n"
print "Is Set 1/1: " (isSet(ar, 1,1)) "\n"

int b = (int get (ar, 0,0));
print b // uninitialized variable b

At least you know that you would never intentionally put an uninitialized variable to an array, so that would be fine, anyway it does not work when the array resizes. So the best way to handle this, is to simply create a DropIn Replacement for Array that 'remembers' what indices you put in:

struct SmartArray {}

SmartArray createSmartArray (int x, int y) {
   DxlObject dx = new(); 
   Array ar = create(x, y); 
   dx->"array" = ar
   dx->"max_x" = -1; 
   dx->"max_y" = -1; 
   return (SmartArray (addr_ dx))
}

void put (SmartArray smar, _x valRef, int x, int y) {
   DxlObject dx = ((addr_ smar) DxlObject);
   Array ar = dx->"array"; 
   int val = (int valRef);
   put (ar, val, x, y); 
   // remember the last index we put in 
   int mx = dx->"max_x";
   int my = dx->"max_y";
   mx = mx >? x;
   my = my >? y;
   dx->"max_x" = mx; 
   dx->"max_y" = my; 
}

int maxX(SmartArray smar) {
   DxlObject dx = ((addr_ smar) DxlObject);
   return (int (dx->"max_x"));
}

int maxY(SmartArray smar) {
   DxlObject dx = ((addr_ smar) DxlObject);
   return (int (dx->"max_y"));
}


Array array (SmartArray smar)  {
   return (Array ((addr_ smar) DxlObject)->"array"); 
}

// omitted delete here ...

SmartArray ar = createSmartArray(10,10); 
put (ar, 5, 1, 1) 

int a = (int (get (array ar, 1, 1))); 
int b = (int (get (array ar, 5, 5))); 

print "A = " a " B = " b "\n"

print "MAX: " (maxX ar) "/" (maxY ar) "\n"

put (ar, 5, 1, 4) 
print "MAX after putting to 1/4: " (maxX ar) "/" (maxY ar) "\n"

put (ar, 5, 6, 2) 
print "MAX after putting to 6/2: " (maxX ar) "/" (maxY ar) "\n"

The big advantage of this, is that you can just drop that SmartArray in your code as a library, change certain declarations of array into smart array and then a few compiler errors will tell you exactly where you need to make adaptions (the get function cant be rebuilt by native DXL). In any case based on an approach like that you can make the array even smarter if you chose to.

Hopefully this lengthy discussion on Array is interesting to you (and/or someone else) ... Regards, Mathias

Re: Arrays
llandale - Mon Mar 24 14:29:49 EDT 2014

jszlatki - Mon Mar 24 07:01:26 EDT 2014

@IIlandale thanks for your idea: how to go through the array. I helped me how to calculate the size. here you are:

Array a = create(1,1)

put(a,"a",0,0)      //size: 2Bytes --> 'a' and '\n'
put(a,"aa",1,0)
put(a,"aaa",2,0)
put(a,"aaaa",3,0)
put(a,"aaaaa",4,0)
put(a,"aaaaaa",5,0) //size: 7Bytes --> 6x'a' and '\n'

/*

// int get() returns the address of the item, if it zero there is not item any more 
//control with this
print (int get(a,0,0))      //size: 2Bytes --> 'a' (1) + '\n'
print (int get(a,1,0))      //size: 3Bytes --> 'aa' (2) + '\n'
print (int get(a,2,0))
print (int get(a,3,0))
print (int get(a,4,0))
print (int get(a,5,0))

print (int get(a,6,0))
*/

int sizeX = 4294967295 //2^32-1 integers are 32bit long in all plattforms after dxl manual
int sizeY = 4294967295 //2^32-1
int iSize = 0
int iAddr = 0

for Contents in array(a, 0, 0, sizeX , sizeY) do{

 iAddr = (int Contents) //it returns the address of the item if it zero, means end of array
 if(0== iAddr)
  break
 
 iSize++
}


print iSize "\n"
delete a

Your "Contents" loop does not look familiar.

In any event it is wise to have a global integer associated with the "Array", something like

  • int iArray_Size = 0

when you need a new row:

  • iRowNew = iArray_Size++

You thus always know the size of the array.

-Louie

Re: Arrays
jszlatki - Tue Mar 25 05:24:39 EDT 2014

Mathias Mamsch - Mon Mar 24 14:17:24 EDT 2014

Wow. Now that really freaks me out ... And you really need much to freak me out, because normally I am the one who writes code like this. But your code just seems to be very wrong. It starts with your constants. Try: 

int a = 4294967295 
print a 
// prints 2147483647 
// because DXL uses signed integers and the interpreter will MIN/MAX out of bounds constants

Then you need to know that the whole idea of the 'size' of an array is misleading. When you talk of 'size' what you really mean is the maximum index, that you set in the array. However setting an element at (0, 10) and one at (10,0) does not mean that (10,10) is already set. So the whole concept of 'sizeOf' is wrong for a two dimensional array (and that is probably the reason, why no function exists to actually read those values).

You might want to know if an array item at some X/Y location is already set. Here you need to know that arrays are initialized with 0 bytes. That means, that you can of course test for integer 0 but that only works when you do not put integers in the Array:

Array ar = create(10,10); 

put (ar, 0, 5,5)

int a = (int (get (ar, 5,5))) // 0 we put it in
int b = (int (get (ar, 1,1))) // 0 was initialized by default

print "A = " a " B = " b "\n" // A = 0 B = 0

So that is also something that is not working in ALL cases. DXL is inconsistent here, because there is actually a value that would have been much better for initialization: -2023406815 (or -0x789abcdf) the value for an uninitialized value in DXL. If the DOORS developers would have put this value in the arrays for initialization it would have been much better, because we would get an error if we tried to read a value that has not been set and it would be easy to check:

Array createInitialized (int x, int y) {
  Array ar = create(x,y)
  // initialize the value with 'undefined'
  int i, j; 
  for (i = 0; i < x; i++) for (j = 0; j < y; j++) put (ar, -0x789abcdf, i,j)
  return ar
}
  

bool isSet(Array ar, int x, int y) { 
     return (-0x789abcdf != (int (get (ar, x, y))))
}

Array ar = createInitialized(10,10)

put (ar, 0, 1,1) 

print "Is Set 0/0: " (isSet(ar, 0,0)) "\n"
print "Is Set 1/1: " (isSet(ar, 1,1)) "\n"

int b = (int get (ar, 0,0));
print b // uninitialized variable b

At least you know that you would never intentionally put an uninitialized variable to an array, so that would be fine, anyway it does not work when the array resizes. So the best way to handle this, is to simply create a DropIn Replacement for Array that 'remembers' what indices you put in:

struct SmartArray {}

SmartArray createSmartArray (int x, int y) {
   DxlObject dx = new(); 
   Array ar = create(x, y); 
   dx->"array" = ar
   dx->"max_x" = -1; 
   dx->"max_y" = -1; 
   return (SmartArray (addr_ dx))
}

void put (SmartArray smar, _x valRef, int x, int y) {
   DxlObject dx = ((addr_ smar) DxlObject);
   Array ar = dx->"array"; 
   int val = (int valRef);
   put (ar, val, x, y); 
   // remember the last index we put in 
   int mx = dx->"max_x";
   int my = dx->"max_y";
   mx = mx >? x;
   my = my >? y;
   dx->"max_x" = mx; 
   dx->"max_y" = my; 
}

int maxX(SmartArray smar) {
   DxlObject dx = ((addr_ smar) DxlObject);
   return (int (dx->"max_x"));
}

int maxY(SmartArray smar) {
   DxlObject dx = ((addr_ smar) DxlObject);
   return (int (dx->"max_y"));
}


Array array (SmartArray smar)  {
   return (Array ((addr_ smar) DxlObject)->"array"); 
}

// omitted delete here ...

SmartArray ar = createSmartArray(10,10); 
put (ar, 5, 1, 1) 

int a = (int (get (array ar, 1, 1))); 
int b = (int (get (array ar, 5, 5))); 

print "A = " a " B = " b "\n"

print "MAX: " (maxX ar) "/" (maxY ar) "\n"

put (ar, 5, 1, 4) 
print "MAX after putting to 1/4: " (maxX ar) "/" (maxY ar) "\n"

put (ar, 5, 6, 2) 
print "MAX after putting to 6/2: " (maxX ar) "/" (maxY ar) "\n"

The big advantage of this, is that you can just drop that SmartArray in your code as a library, change certain declarations of array into smart array and then a few compiler errors will tell you exactly where you need to make adaptions (the get function cant be rebuilt by native DXL). In any case based on an approach like that you can make the array even smarter if you chose to.

Hopefully this lengthy discussion on Array is interesting to you (and/or someone else) ... Regards, Mathias

Thanks for your feedback!

You are right the init is bad.  I only  wanted to say with my post, what i realized, and I was happy about it :)

I say voow too because of respect of your code. But after the manual the struct did not implemented, so I did not try it out.

Thanks,
regards,
Józsi

Re: Arrays
jszlatki - Tue Mar 25 05:30:24 EDT 2014

llandale - Mon Mar 24 14:29:49 EDT 2014

Your "Contents" loop does not look familiar.

In any event it is wise to have a global integer associated with the "Array", something like

  • int iArray_Size = 0

when you need a new row:

  • iRowNew = iArray_Size++

You thus always know the size of the array.

-Louie

You mentioned in your post at: Apr 22, 2009

   "That looks like "for Contents in array(ary, 0, 0, NumX, Numy) do"."

I do not know how the Contents is declarated, and what kind of type does it have. You are right it is the easiest way to handle it.

-Józsi