Yassine Jdair
Yassine Jdair

Reputation: 19

C++ Initialize an array of structs with a preassigned value for one of the members

I have a car struct that has a car_reg member. I want to initialize an array of car structures by assigning the string "Empty" to car_reg. How should I do this?

My program code is as follows:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <conio.h>
#include <iomanip>

using namespace std;

int main() {
    struct car {
        string car_reg = 0;
        char car_manuf[30];
        char car_model[30];
        double price;
        string car_reg{};
    };
}

Upvotes: 0

Views: 671

Answers (3)

M.M
M.M

Reputation: 141648

Example of correct code as per your request:

#include <string>
#include <array>

struct Car {
    std::string car_reg;
    std::string car_manuf;
    std::string car_model;
    double price{};
};

int main()
{
    std::array<Car, 10> cars;

    for (auto& car : cars)
        car.car_reg = "EMPTY";
}

Some points:

  • The struct Car definition should be outside of main
  • Removed unused includes, and added ones that were used.
  • Use std::string instead of C-style arrays in all cases to make the code simpler.
  • Initialize price to avoid accidentally using an uninitialized value.
  • Consider whether setting this string "EMPTY" is a good idea; perhaps your program could just treat the blank string as meaning empty registration.

It's possible to have car_reg automatically assigned a value on creation of any Car (instead of what you actually asked - only assigning to the Cars in a specific array). To do this, change std::string car_reg; to std::string car_reg{"EMPTY"};

Upvotes: 0

Yassine Jdair
Yassine Jdair

Reputation: 19

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <conio.h>
#include <iomanip>

using namespace std;

int main()
{
    struct car
    {
        string car_reg = {"Empty"};
        
        char car_manuf[30];
        char car_model[30];
        car(const char* manuf,
            const char* model)

        {
            strcpy(car_manuf, manuf);
            strcpy(car_model, model);
        }
    };
        
    
}

Upvotes: -1

user4581301
user4581301

Reputation: 33982

Explanation inline.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <conio.h>
#include <iomanip>

using namespace std;

int main()
{
    struct car // removed ; the ; terminates the definition, cutting it off
               // and leaving you with a declaration. Everything in the braces
               // that follow would be seen as a block of code defining two
               // automatic variables scoped inside the block. Useless in this 
               // case.
    {
        string car_reg = 0; // this is actually NASTY! More on it later
        char car_manuf[30] = "EMPTY"; // assigns default value. But only if your 
                                      // compiler comes from this decade.
                                      // If you are rocking an antique you can't 
                                      // do this. Will cover what you can do  below.
        char car_model[30] = "EMPTY";

        string car_reg{}; // cannot reuse the car_reg identifier in the same scope
                          // car_reg is either a variable or a function.
    }; // ; goes here

    car c; // for testing purposes
    cout << c.car_manuf << ',' << c.car_model; // for testing
}

string car_reg = 0; is nasty. What it does is defines a member variable car_reg and uses 0 as the default. The 0 is converted to a null pointer to a char array. The string constructor attempts to initialize from a null pointer and blows up at runtime. The compiler is just fine with this bit of stupidity because in the old days NULL could be #define NULL 0 and we don't want to break decades of old code by fixing this problem.

Since we can't do default initializations in pre C++11 code we need a constructor to do the work. Yup. structs can have constructors. This is because a struct and a class are almost identical. The only difference you're ever likely to see between the two is class defaults to private access and structs default to public access.

struct car
{
    char car_manuf[30];
    char car_model[30];
    car (): car_manuf("EMPTY"), car_model("EMPTY")
    {

    }
};

Note that his isn't as groovy as it looks. You're usually better off with something like

struct car
{
    string car_manuf;
    string car_model;
    car (const string & manuf,
         const string & model): car_manuf(manuf), car_model(model)
    {
        
    }
};

and not allowing the empty case at all. When possible force users to initialize a class into a fully initialized state. And use std::string. Very handy tool, std::string.

Note that

struct car
{
    char car_manuf[30];
    char car_model[30];
    car (const char * manuf,
         const char * model): 
            car_manuf(manuf), car_model(model) // fails to compile
    {

    }
};

is not possible. You can't initialize a char array with a pointer to char. I'm not entirely certain why the language doesn't have a rule to handle this, but it doesn't. If forced to use char arrays,

struct car
{
    char car_manuf[30];
    char car_model[30];
    car (const char * manuf,
         const char * model)
    {
        strcpy(car_manuf, manuf);
        strcpy(car_model, model);
    }
};

and make dang sure that manuf and model will fit in 29 characters or less.

Upvotes: 4

Related Questions