passing an array of structs

This is a discussion on passing an array of structs within the C++ Programming forums, part of the General Programming Boards category; I'm making a class to handle and decide what polygons should be rendered and checked for collisions in a simple ...

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    29

    passing an array of structs

    I'm making a class to handle and decide what polygons should be rendered and checked for collisions in a simple game.

    I have a method in it, which will set the corners of the poly, and since i don't know how many corners there will be, i'll have to pass to this method an array.

    it wouldn't be such a problem if it was a simple int, but i have to pass my custom struct, which is used to define a 3D point:

    Code:
    struct p3d {
           float x;
           float y;
           float z;
    };
    i don't know how i should do it. i have tried several approaches, and nothing works. how should i write it?

    and one more thing. considering i want to do some experimenting, i have declared this:
    Code:
    p3d corners[4]
    is this the easiest approach to set all the values manually? i'll need to make more polys later, and before i'll make a file format, i'll have to hardcode it into them, at least in the first stage. i don't feel like doing this for several polys.

    Code:
    corners[0].x=-0.5;
    corners[0].y=0;
    corners[0].z=0;
    
    corners[1].x=0.5;
    corners[1].y=0;
    corners[1].z=0;
    
    corners[2].x=-0.5;
    corners[2].y=1;
    corners[2].z=0;
    
    corners[3].x=0.5;
    corners[3].y=1;
    corners[3].z=0;
    ty. i really appreciate all past support i have received.

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    RE: hardcoded stuff - do you mean initialization?
    RE: passing params - like this?
    Code:
    #include <cstddef>
    using std::size_t;
    
    struct p3d
    {
       float x, y, z;
    };
    
    void foo(p3d *p, size_t size)
    {
       // ...
    }
    
    int main()
    {
       p3d corners[4] = 
       {
          {-0.5,0,0},
          {-0.5,0,0},
          {-0.5,1,0},
          { 0.5,1,0},
       };
       foo(corners, sizeof corners / sizeof *corners);
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    29
    well, yes. consider it intialisation it's more like, i'm experimenting with it, to see if it behaves how i want.

    wow, that curly bracket sure saves a lot of typing..

    okay, and one more thing. what is that size_t argument in foo? what do i get in it?
    later edit: just found out tyvm. i guess it's so great for you to write up code that compiles up the first time.

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,510
    A struct is a class in C++ (Only difference is all members are public by default), which means you can define a constructor.

    Code:
    struct p3d {
           p3d(float ix, float iy, float iz): x(ix), y(iy), z(iz) {}
           p3d(): x(0), y(0), z(0) {} // default initialization
           float x;
           float y;
           float z;
    };
    
    int main () {
    
        p3d* corners = new p3d[3]; // declares array. Uses default constructor
    
        p3d rec(.5,1.,0.); // declares object. uses parameter constructor
    
        delete [] corners;
    
        return 0;
    
    }
    You can also define a member function in which you pass the arguments and it changes the object data members...

    rec.change(2,1,4); is easier than having to change each data member at a time

    EDIT: major oversight. Added the delete statement.
    Last edited by Mario F.; 11-26-2006 at 05:30 AM.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,510
    Post that back Tonto... hehe. You got me interested. Was about to ask you to copy it.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    29
    Mario, thanks. but i think it's easier to use the curly braces, at least for now. but i do see the purpose of that. I'm starting to see now where the "power" that c++ has comes from..

    Ouch, Tonto, put that back looks like it's already got some fans..
    (a voice from the public, not me: and if you're kind enough sharing the sources, too )

    one more thing, can anyone explain me the voodoo behind:
    foo(corners, sizeof corners / sizeof *corners); ?
    how does that ever gets me the number of items in the array? all i know is that sizeof returns how much a data type takes into memory - but all that pointer arithmethic..
    Last edited by izuael; 11-25-2006 at 08:33 PM.

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,510
    It's the size of the array divided by the size of the first element of the array.

    Since all elements have the same size, if the array size is, say 12, and each element is size 3, there's 12 / 3 = 4 elements.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    29
    so a pointer to corners returns me only the first element, and not everything?
    uuuh. pointers are such a hard concept.

    i've got some interesting question here: is there a way to only pass to foo the array, and the function will compute this value inside its scope?
    Last edited by izuael; 11-25-2006 at 08:51 PM.

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,510
    Ah... but you are not getting a pointer to corners. You are dereferencing corners.

    *corners dereferences corners. that is, accesses it's element.
    You cannot create a pointer to an object. You can create a pointer to a type.

    Without structs for easier reading...

    Code:
    int a = 13;
    int* value = &a; // Pointer to int.
    
    value* name; // error. value is an object. You can't create a pointer to it
    
    std::cout << *value; // derefences value. Outputs 13.
    Don't worry. You will get there.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    >> is there a way to only pass to foo the array, and the function will compute this value inside its scope?

    What value?

    >> so a pointer to corners returns me only the first element, and not everything?

    No. Corners is an array of these points. The name 'corners' acts as a pointer to the first address. If you dereference this point (*corners) you get the first elements. Likewise, if you add 1 to the pointer, you get the second element *(corners + 1). This notation is inconvenient, and corners[1] is the same as *(corners + 1)

    Okay. Point and vector class interfaces. Don't criticize me :>

    Code:
    class CPoint 
    {
    
        friend class CVector; // Cuddle fluffle shnuff
    
        friend std::istream & operator >> ( std::istream &, CPoint& );
        friend std::ostream & operator << ( std::ostream &, const CPoint & );
    
    private:
    
        int _dimensions;        // Number of used dimensions of our point
    
    public:
    
        double x, y, z;     // Coord values - note cap on 3 dimensions
    
        // Constructors and Destructors
        //  o 1-D
        //  o 2-D
        //  o 3-D
        //  o N-D
    
        CPoint( void );
    
        CPoint( int a );
        CPoint( double a );
    
        CPoint( int a, int b ); 
        CPoint( double a, double b );
    
        CPoint( int a, int b, int c );
        CPoint( double a, double b, double c );
    
        CPoint( int n, int * a );
        CPoint( int n, double * a );
    
        ~CPoint();
    
    
        // Available Operations
        //  o Translations
        //  o Scaling
        //  o Comparisons
    
        bool operator == ( const CPoint & other ) const;
        bool operator != ( const CPoint & other ) const;
    
        CVector operator - ( const CPoint & other ) const; 
        CPoint  operator + ( const CVector & translate ) const;
        CPoint  operator - ( const CVector & translate ) const;
    
        CPoint & operator += ( const CVector & translate );
        CPoint & operator -= ( const CVector & translate);
    
    
        friend CPoint operator * ( int scaler, CPoint v );
        friend CPoint operator * ( double scaler, CPoint v );
        friend CPoint operator * ( CPoint v, int scaler );
        friend CPoint operator * ( CPoint v, double scaler );
    
        friend CPoint operator / ( CPoint v, int  scaler );
        friend CPoint operator / ( CPoint v, double  scaler );
    
        friend CPoint operator + ( CPoint v, CPoint w );
    
        // General
    
        friend double distance( const CPoint & a, const CPoint & b );
    
        int getDimensions( void ) const;
        int setDimensions( int dim );
    
    };
    
    class CVector : public CPoint 
    {
    
    public:
    
        // Constructors and Destructors
        //  o 1-D
        //  o 2-D
        //  o 3-D
        //  o N-D
    
        CVector( void );
    
        CVector( int a );
        CVector( double a );
    
        CVector( int a, int b );
        CVector( double a, double b );
    
        CVector( int a, int b, int c );
        CVector( double a, double b, double c );
    
        CVector( int n, int * a );
        CVector( int n, double * a );
    
        ~CVector( void );
    
        CVector negate( void ) const;
        CVector perp( void ) const;
    
        // Arithmatic Operators
        //  o Scaling
        //  o Transformations
        //  o Cross product
        //  o 2-D 'perp' product
        //  o 3-D cross product
    
        friend CVector operator * ( int scaler, CVector v );     // S
        friend CVector operator * ( double scaler, CVector v );  // C
        friend CVector operator * ( CVector v, int scaler );     // A
        friend CVector operator * ( CVector v, double scaler );  // L
        friend CVector operator / ( CVector v, int scaler );     // I
        friend CVector operator / ( CVector v, double scaler );  // N'
    
        CVector operator + ( const CVector & v ) const;     // VSUB
        CVector operator - ( const CVector & v ) const;     // VADD
        double operator * ( const CVector & v ) const;      // Dot
        double operator | ( const CVector & v ) const;      // Perp
        CVector operator ^ ( const CVector & v ) const;     // Cross
    
        CVector & operator *= ( double scaler );        // Scale
        CVector & operator /= ( double scaler );        // Scale
        CVector & operator += ( const CVector & v );    // VADD
        CVector & operator -= ( const CVector & v );    // VSUB
        CVector & operator ^= ( const CVector & v );    // Cross Product
    
        //  o Norm
        //  o Normalize
    
        double norm( void );
        void normalize( void );
    
    };
    Oh right. Context. I designed these classes for my own use, and if you don't want to reinvent the wheel, I can provide the implementation that I made if you want.

    ╔╗╔╦══╦╗╔╦══╦╗
    ║╚╝║╔╗║╚╝║╔╗║║
    ║╔╗║╠╣║╔╗║╠╣╠╣
    ╚╝╚╩╝╚╩╝╚╩╝╚╩╝

    codez http://code.google.com/p/zxcvbn/

  11. #11
    Registered User
    Join Date
    Oct 2006
    Posts
    29
    i see. i always skipped the pointer part into tutorials, since it seems a pretty evil idea. i guess i'll have to start reading 'bout them from now on. they seem more usefull than i thought.

    thanks for the info, again.
    izuael

    @tonto: thanks.

    edit:
    instead of
    Code:
     void foo(p3d *p, size_t size) { }
    i want to have
    Code:
     void foo(p3d *p) { /* computing size here */ }
    this way, i know i can't pass "accidentaly" a wrong corner count to the second argument, that the method always computes the corners
    Last edited by izuael; 11-25-2006 at 09:11 PM.

  12. #12
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I'd suggest a container class. Such as C++'s STL vector class. Very basically, it acts as an array which can be of any size. That -> dereferences the pointer and access's the vector's member functions. There's some wierd concepts in that code, I dunno. http://www.sgi.com/tech/stl/Vector.html

    Code:
    #include <vector>
    
    struct p3d { /* yr stuffs */ };
    int main()
    {
            std::vector<p3d> v;
            v.push_back(p3d(1.0f, 2.0f, 3.0f));
            v.push_back(p3d(4.0f, 5.0f, 6.0f));
            foo(&v);
    }
    
    void foo(std::vector<p3d> * blaz)
    {
            int size = blaz->size()
            p3d local1 = blaz->at[0];
            p3d local2 = blaz->at[1];
    }
    Oh yeah, that vector class is not like the vector class I showed you. At all :>

    ╔╗╔╦══╦╗╔╦══╦╗
    ║╚╝║╔╗║╚╝║╔╗║║
    ║╔╗║╠╣║╔╗║╠╣╠╣
    ╚╝╚╩╝╚╩╝╚╩╝╚╩╝

    codez http://code.google.com/p/zxcvbn/

  13. #13
    Registered User
    Join Date
    Oct 2006
    Posts
    29
    yeah, i guess that vector is different of the 3D vector

    i was wondering now...
    i'm trying to instanciate an array of my class, but this class also needs a value in it's constructor.

    how should i do it, what's this thing called?

    i tried
    Poly square(4)[10]

    where Poly is my class, 4 is passed to the constructor, and 10 represents 10 elements in the array, but it doesn't work.

  14. #14
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I would probably supply a quadrilateral class class or something that had a default constructor to do that. I had a similar thing in that same project of mine where I did something like, with cthing analogous to poly and csquare analogous to something you might do:

    Code:
    class CThing
    {
    
    public:
    
        // Constructors / Destructor
    
        explicit CThing( void );
        virtual ~CThing( void );
    
        virtual void draw( void ) const = 0;
        virtual void update( double dt ) = 0;
    
        // Deal With Vector
        //  o Add
        //  o Remove
        //  o Iterators
    
        void add( const CPoint & point );
        void remove( int index );
    
        std::vector<CPoint>::iterator begin( void );
        std::vector<CPoint>::iterator end( void );
    
        std::vector<CPoint>::const_iterator begin( void ) const;
        std::vector<CPoint>::const_iterator end( void ) const;
    
    private:
    
        std::vector<CPoint> m_vPoints;
    
    };
    
    class CSquare : public CThing
    {
    
        friend dstream & operator << ( dstream &, const CSquare & );
    
    public:
    
        // Constructors / Destructor
        //  o I'm unbelievably lazy
    
        CSquare( double left = 0, double top = 0, double right = 0, double bottom = 0, const CVector & v = CVector(), const CVector & d = CVector() );
        CSquare( const CPoint & topleft, const CPoint & topright, const CVector & v = CVector(), const CVector & d = CVector() );
        virtual ~CSquare( void );
    
        virtual void draw( void ) const;
        virtual void update( double deltaTime );
    
        // Stuff To Do With Square
        //  o Displaced left, right, top, bottom
        //  o Velocity stuff
        //  o Displacement stuff
        //  o Translate
        //  o Check intersection
    
        double l( void ) const;
        double r( void ) const;
        double t( void ) const;
        double b( void ) const;
    
        void setVelocity( const CVector & v );
        const CVector & getVelocity( void ) const;
    
        void setDisplacement( const CVector & v );
        const CVector & getDisplacement( void ) const;
    
        bool intersects( const CSquare & other ) const;
    
        CSquare translate( const CVector & displacement );
        CSquare nextPos( double deltaTime );
    
    protected:
    
        double _left;
        double _right;
        double _top;
        double _bottom;
    
        CVector _velocity;
        CVector _displacement;
    
    };

    ╔╗╔╦══╦╗╔╦══╦╗
    ║╚╝║╔╗║╚╝║╔╗║║
    ║╔╗║╠╣║╔╗║╠╣╠╣
    ╚╝╚╩╝╚╩╝╚╩╝╚╩╝

    codez http://code.google.com/p/zxcvbn/

  15. #15
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Oh yeah. You could also use a container class like a vector again to assist you. The vector constructor can be used like so:

    Code:
    // vector(size_type n, const T& t)
    vector<foo> v(10, foo("test"));
    Creates 10 copies of foo("test"). This can be simulated by writing a routine to copy your objects, because that constructor creates 'n copies of t'

    Code:
    void supuh_copy(poly * array, size_type n, const poly & t)
    {
            for(int i = 0; i < n; ++i) array[i] = t;
    }
    Your code needs a copy constructor though for that. For example, with my foo example, I would have:

    Code:
    class foo
    {
        friend ostream & operator << (ostream & o, const foo & f);
    
    public:
    
        foo() { }
        foo(const char * c) { strcpy(buffer, c); }
        foo(const foo & o) { strcpy(buffer, o.buffer); }
    
    private:
    
        char buffer[1024];
    
    };
    Last edited by Tonto; 11-26-2006 at 02:03 PM.

    ╔╗╔╦══╦╗╔╦══╦╗
    ║╚╝║╔╗║╚╝║╔╗║║
    ║╔╗║╠╣║╔╗║╠╣╠╣
    ╚╝╚╩╝╚╩╝╚╩╝╚╩╝

    codez http://code.google.com/p/zxcvbn/

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help passing nxn array to 2d array.
    By beglaryanh in forum C Programming
    Replies: 2
    Last Post: 06-06-2009, 05:23 PM
  2. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  3. Creating array of structs
    By knirirr in forum C++ Programming
    Replies: 12
    Last Post: 06-18-2008, 08:30 AM
  4. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  5. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 05:58 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21