Initialise vector of vectors using structure as da

2019-08-26 01:04发布

问题:

I would rather use a class, but my requirement is simpler than that. Which is to create a two dimensional array of elements, with each element representing a structure datatype. The problem is when I try to do a variable initialisation after the multi vector is passed into a function. The simple version of my code is as follows:

#include <iostream>
#include <vector>

using namespace std;

struct Twalker
{
    int state;  
    float x,y; 
};`

void initialise(vector<vector<Twalker>>& walker,int n)
{   
   vector<Twalker> tempWalker;
   for (int i=0; i<n; i++)
   {
     tempWalker.state.push_back(+1); //need help!
     tempWalker.y.push_back(float(rand() % 10)); //need help!
     tempWalker.x.push_back(0.0); //need help!
   }
   walker.push_back(tempWalker);

}

int main(int argc, char** argv) 
{   
   int n = 5;
   vector<vector<Twalker>> walker;
   initialise(walker,n);
}

I have seen that we can add multiple values into a structure using push_back. But i was trying to input values more liberally. Did I miss any syntax while using push_back? I started learning the concept of vectors few hours before and I am trying to shift my code from arrays into vectors.

回答1:

First of all, structures are equivalent to classes - the only difference is that their members are by default public, while class members are by default private.

Your program has multiple issues, and here is one possible solution to it:

#include <iostream>
#include <vector>
#include <ctime>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

struct Twalker
{
    int state;
    float x,y;
};

// Initialize the vector of vectors of Twalker objects
void initialise(vector<vector<Twalker>>& walker, int nv, int n)
{ 
    Twalker wlk;
    vector<Twalker> tempWalker;

    // Outer loop - vector of vectors
    for (int i=0; i<nv; i++){
        // Inner loop - vector of Twalker objects
        for (int j=0; j<n; j++){
            // Temporary Twalker
            wlk.state = 1;
            wlk.x = 0.0; 
            wlk.y = float(rand()%10);
            // Add it to the inner vector
            tempWalker.push_back(wlk);
        }
        // Add the inner vector to the vector of vectors
        walker.push_back(tempWalker);
        // Reset the inner vector
        tempWalker.clear();
    }
}

int main()
{
    // Set the seed
    std::srand(std::time(0));

    int nv = 3, n = 2;
    vector<vector<Twalker>> walker;

    // Initialize   
    initialise(walker, nv, n);

    // Print 
    for (int i = 0; i < nv; i++)
        for (int j = 0; j < n; j++)
            cout << walker[i][j].state << " " 
                 << walker[i][j].x << " "
                 << walker[i][j].y << endl; 
    return 0;
}

You should definitely read more on vectors including basics and concepts like iterators and size_t. Here I only used variations of what it seems you are familiar with, but some parts of this program would normally look quite different (like printing part).

Some notes and suggestions related to this code:

  • Generally don't use using namespace std. You may, for instance, end up overwriting stl functions with your own by accident. It is more recommended to use using for specific, commonly used components like cin, cout, vector etc.
  • You are initializing a vector of vectors - thus you need two loops in your initialization function (and possibly an extra parameter to control the vector of vectors size).
  • While you can access object (here Twalker) members directly from the vector, like in the print part at the end, you reversed the order for that in your program. You would need to push back a temporary Twalker first and then fill each member with a value. Here the Twalker is filled first and then pushed back.
  • At the end of the inner loop the inner (temporary) vector is cleared - its size is reset to 0. If not for this, the inner loop would be increasing the size of the vector each time it performs a push_back. Last vector in the vector of vectors would be nv times longer than the first!
  • The srand function resets the random seed every time the program is ran. Without it, executing the same program would always lead to the same set of random numbers.
  • I normally use argc and argv only when I have command line arguments in the program. Also, you can but don't have to add a return 0 statement at the end of your main (compiler will add it for you if you don't).
  • As @Caleth said in the comment, instead of clearing tempWalker after the inner loop, you can also declare it in the inner loop which will create a new, empty tempWalker vector each time the inner loop is re-entered. On the other hand, as noted by @MatteoItalia, this approach allocates and deallocates memory for the inner vector each time the inner loop is executed. In larger programs with larger vectors this kind of redundant allocations will cause performance losses and should be avoided.


标签: c++ c++11 struct