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

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
    270 Posts
    ACCEPTED ANSWER

    Re: Arrays

    ‏2009-04-22T06:26:26Z  in response to Doorsbert
    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
      ACCEPTED ANSWER

      Re: Arrays

      ‏2009-04-22T06:42:06Z  in response to Tony_Goodman
      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
        ACCEPTED ANSWER

        Re: Arrays

        ‏2009-04-22T07:28:28Z  in response to Doorsbert
        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
          ACCEPTED ANSWER

          Re: Arrays

          ‏2009-04-22T17:32:58Z  in response to Tippers
          "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
      ACCEPTED ANSWER

      Re: Arrays

      ‏2009-04-22T17:31:46Z  in response to Tony_Goodman
      "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
        ACCEPTED ANSWER

        Re: Arrays

        ‏2009-04-22T17:38:16Z  in response to Doorsbert
        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
    2943 Posts
    ACCEPTED ANSWER

    Re: Arrays

    ‏2009-04-22T19:25:53Z  in response to Doorsbert
    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
      ACCEPTED ANSWER

      Re: Arrays

      ‏2009-04-23T12:53:56Z  in response to llandale
      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
      ACCEPTED ANSWER

      Re: Arrays

      ‏2014-03-24T11:01:26Z  in response to llandale

      @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
        1936 Posts
        ACCEPTED ANSWER

        Re: Arrays

        ‏2014-03-24T18:17:24Z  in response to jszlatki

        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

        • jszlatki
          jszlatki
          3 Posts
          ACCEPTED ANSWER

          Re: Arrays

          ‏2014-03-25T09:24:39Z  in response to Mathias Mamsch

          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

      • llandale
        llandale
        2943 Posts
        ACCEPTED ANSWER

        Re: Arrays

        ‏2014-03-24T18:29:49Z  in response to jszlatki

        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
          ACCEPTED ANSWER

          Re: Arrays

          ‏2014-03-25T09:30:24Z  in response to llandale

          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