mohrphium
mohrphium

Reputation: 363

Assign a whole struct at once in an array

I am learning C++ and I have a problem with struct and arrays. My struct is:

struct board
{
    string name;
    string desc;
    int nval;
    int sval;
    int eval;
    int wval;
};

My array looks like this:

board field[10][10];

I'm able to do for example:

field[5][6].name = "ExampleName";
field[5][6].desc = "This is an example";
field[5][6].nval = 3;
//and so on...

But I want to assign to the whole structure at once, something like this:

field[5][6] = {"ExampleName", "This is an example", 3, 4, 5, 6};
//so I don't have to type everything over and over again...

Upvotes: 4

Views: 8019

Answers (6)

The question is not too clear as of what you mean with one line, so I will start providing suggestions:

Use aggregate initialization:

board fields[10][10] = { 
                  { {"ExampleName","This is an example",3,4,5,6}, // Element 0,0
                    {"ExampleName","This is an example",3,4,5,6}, // Element 0,1
                // ...
                  },
                  { {"ExampleName","This is an example",3,4,5,6}, // Element 1,0
                // ... 
                  }
                };

This is the closest to one-liner that you can get, it is valid C++ (in all variants, given that board is an aggregate, an thus board[10][10] is also an aggregate), but it can be hard to read.

The next step is getting closer to what you are doing, which is initializing each element (rather than the array), for that in C++11 you can use the same type of initialization as you suggest. In C++03 you need to do this through either a constructor (note, this will change the properties of the type, and you will need to create a default constructor for the array):

 struct board {
    string name;
    string desc;
    int nval;
    int sval;
    int eval;
    int wval;
    board() {}  // [*]
    board( const char* name, const char* desc, int n, int s, int e, int w )
       : name(name), desc(desc), nval(n), sval(s), eval(e), wval(w)
    {}
 };
 board fields[10][10];  // [*] this requires the default constructor [*]

 fields[5][6] = board("ExampleName","This is an example",3,4,5,6);

Or through a function:

board create_board( const char* name, const char* desc, ... ) {
   board res = { name, desc, ... };
   return res;
}

Note that in both these cases the elements in the array are initialized during the array initialization, and then a new object is copied on top of them.

Upvotes: 0

Bojan Komazec
Bojan Komazec

Reputation: 9526

If you define constructor that takes parameters you will be able to create temporary and initialize given element with it. You'll need to define and default constructor as well:

struct board
{
   string name;
   string desc;
   int nval;
   int sval;
   int eval;
   int wval;

   board():
     name(""),
     desc(""),
     nval(0),
     sval(0),
     eval(0),
     wval(0){}

   board(
     const string& name,
     const string& desc,
     int nval,
     int sval,
     int eval,
     int wval):
   name(name),
   desc(desc),
   nval(nval),
   sval(sval),
   eval(eval),
   wval(wval){}
};

int main()
{
   board field[10][10];
   field[5][6]= board("ExampleName","This is an example",3,4,5,6);
   return 0;
}

Upvotes: 2

P.P
P.P

Reputation: 121357

What you are trying to do is allowed in C standard. It seems to be working in C++ as well. I verified it in C++11:

struct board
{
string name;
string desc;
int nval;
int sval;
int eval;
int wval;
}field[10][10];

int main()
{    
field[5][6]={"ExampleName","This is an example",3,4,5,6};
cout<<field[5][6].name<<endl;
cout<<field[5][6].sval<<endl;
return 0;
}

It's printing correctly. So you should be able to do that.

Upvotes: 3

Novellizator
Novellizator

Reputation: 14883

I'm afraid you can't do it this way.

But in real life it's not a problem because you don't normally need to fill this kind of fields manually. You usually do it in a loop.

In case you wouldn't mind runtime initialization, I'd do it this way:

    // in the beginning make these arrays
string names[10*10] = {
    "example 1 name"
    "example 2 name"
    "blah blah blah "
};

string descriptions[100] = {

};
//and then just loop through that

int i,j;
for (int k = 0; k != 10*10; ++k) { // 10*10 size of a board
        if (j == 10) {
            j = 0;
            i++
        }

        field[i][j].name = names[k]// get it from names
        field[i][j].desc = // get somehow the description,...
        ++j
    }

}

Upvotes: 2

Steed
Steed

Reputation: 1300

If you really need to define hand-picked values for all of your 100 fields, you could make it easier by writing all the arguments in a text file and then parse the file and fill your array with the extracted values. The file might look like

0 0
Corner field
Here it begins
0 1 2 3

0 1
ExampleName
This is an example
3 4 5 6

and so on. Then when reading the file you can use istream::getline to extract text strings, and istream::operator>> to extract numbers.

But it's still a lot of pain. Are you sure that there is no automatic way to generate at least most of your values?

Upvotes: 1

dialer
dialer

Reputation: 4835

As has been mentioned, C99 as well as C# support a form of that syntax, but standard C++ doesn't. You could do it with by adding a constructor to your struct. Be aware that this will not be ANSI C compatible anymore.

struct board
{
    string name;
    string desc;
    int nval;
    int sval;
    int eval;
    int wval;

    board()
    {
    }

    board(string name, string desc, int nval, int sval, int eval, int wval)
    {
        this->name = name;
        this->desc = desc;
        this->nval = nval;
        this->sval = sval;
        this->eval = eval;
        this->wval = wval;
    }
};

field[1][2] = board("name", "desc", 1, 2, 3, 4);

Upvotes: 2

Related Questions