Topic
  • 13 replies
  • Latest Post - ‏2014-03-25T09:30:24Z by jszlatki
Doorsbert
Doorsbert
16 Posts

Pinned topic Arrays

‏2009-04-22T02:05:59Z |
Is there a way to get the size of an Array the way sizeof() lets you get the size of an array?
Updated on 2009-04-23T12:53:56Z at 2009-04-23T12:53:56Z by Tippers
  • Tony_Goodman
    Tony_Goodman
    271 Posts

    Re: Arrays

    ‏2009-04-22T06:26:26Z  
    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.
  • Doorsbert
    Doorsbert
    16 Posts

    Re: Arrays

    ‏2009-04-22T06:42:06Z  
    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.
  • Tippers
    Tippers
    16 Posts

    Re: Arrays

    ‏2009-04-22T07:28:28Z  
    • Doorsbert
    • ‏2009-04-22T06:42:06Z
    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.
  • Doorsbert
    Doorsbert
    16 Posts

    Re: Arrays

    ‏2009-04-22T17:31:46Z  
    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.
  • Doorsbert
    Doorsbert
    16 Posts

    Re: Arrays

    ‏2009-04-22T17:32:58Z  
    • Tippers
    • ‏2009-04-22T07:28:28Z
    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.
  • Doorsbert
    Doorsbert
    16 Posts

    Re: Arrays

    ‏2009-04-22T17:38:16Z  
    • Doorsbert
    • ‏2009-04-22T17:31:46Z
    "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.
  • llandale
    llandale
    3035 Posts

    Re: Arrays

    ‏2009-04-22T19:25:53Z  
    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
  • Tippers
    Tippers
    16 Posts

    Re: Arrays

    ‏2009-04-23T12:53:56Z  
    • llandale
    • ‏2009-04-22T19:25:53Z
    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... ;)
  • jszlatki
    jszlatki
    3 Posts

    Re: Arrays

    ‏2014-03-24T11:01:26Z  
    • llandale
    • ‏2009-04-22T19:25:53Z
    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

    Updated on 2014-03-24T16:55:04Z at 2014-03-24T16:55:04Z by jszlatki
  • Mathias Mamsch
    Mathias Mamsch
    2161 Posts

    Re: Arrays

    ‏2014-03-24T18:17:24Z  
    • jszlatki
    • ‏2014-03-24T11:01:26Z

    @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

  • llandale
    llandale
    3035 Posts

    Re: Arrays

    ‏2014-03-24T18:29:49Z  
    • jszlatki
    • ‏2014-03-24T11:01:26Z

    @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

  • jszlatki
    jszlatki
    3 Posts

    Re: Arrays

    ‏2014-03-25T09:24:39Z  

    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: 

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">int a = 4294967295 print a // prints 2147483647 // because DXL uses signed integers and the interpreter will MIN/MAX out of bounds constants </pre>

    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:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">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 </pre>

    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:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">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 </pre>

    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:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">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" </pre>

    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

  • jszlatki
    jszlatki
    3 Posts

    Re: Arrays

    ‏2014-03-25T09:30:24Z  
    • llandale
    • ‏2014-03-24T18:29:49Z

    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