huza huza - 1 month ago 7
C++ Question

C++ struct questions

I've googled relates to struct and I was able to see how they are used; however, I couldn't clearly figure out some of them.

Let's say I have 2 structs

struct Student {
int age;
int height;
};

struct School {
Student information;
};


and let's say I want to handle information School[i].Student[j].age or height based on input file.

int main() {
int school_number = 20;
int student_number = 50;

School school[school_number-1]; // is this the correct way to create it? since [0] is the first school

for (int i=0; i < school_number; i++) {
for (int j=0; j < student_number; j++) {
getline(file, line); // let's say the line has student's age and height.
istringstream c(line);
c >> school[i].information[j].age >> school[i].information[j].height;
}
}
}


I thought this would do the job, but I'm getting no match for 'operator[]' (operand types are 'Student' and 'int') compile error.

What am I missing?

when it's just student,

Student info[student_number-1];

for (int i=0; i < student_number; i++) {
getline(file, line);
istringstream c(line);
c >> information[i].age >> information[i].height;
}


this one works without problem, but I am still not sure what I need to do for 2 structs, where one is calling other one.

One more question,

while I was searching, I see lots of

School *id = new School[school_number-1];


something like this. How does this different from

School school[school_number-1];


this one?

I see a pointer, so I'm pretty sure it does something, but based on how they are used, they look pretty much same.

edit : I've tried little bit, but still not sure how to use vector in this case.

for the above case,

int main() {
vector[Student] student;

int school_number = 20;
int student_number = 50;

School school[school_number-1]; // is this the correct way to create it? since [0] is the first school

for (int i=0; i < school_number; i++) {
for (int j=0; j < student_number; j++) {
getline(file, line); // let's say the line has student's age and height.
istringstream c(line);
c >> school[i].information[j].age >> school[i].information[j].height;
}
}
}


if I call

vector[Student] student;


how can I modify the line

c >> school[i].information[j].age >> school[i].information[j].height;


with the variable student I just created?

Answer
struct School {
    Student information;
};

In this code struct School would contain only one Student object, so school[i].information[j] fails. (It attempts to call operator[] on the Student object school[i].information, which is not defined.)


School school[school_number];

(a C-style array) is not valid C++, because school_number is a variable, and C-style arrays can only have a constant number of items. They are also not recommended in modern C++.

std::array<School, 20> school;

is the recommended way to create an array of 20 School objects.

Because in this code school_number has a fixed value, it could instead be defined as

constexpr int school_number = 20;

and then it can be used with std::array or the C-style array. Also the array would need to have school_number items, and not school_number-1. school_number-1 is however the index of its last item (because they are counted from 0, when indexing).


For an array with a variable number of items, std::vector can be used:

std::vector<School> school(school_number);

Or alternately, an empty vector is created with

std::vector<School> school;

and then School objects are inserted into it with

school.push_back(sch);

So the program could be written like this:

struct Student {
    int age;
    int height;
};

struct School {
    std::vector<Student> information; // School has array of students
};

int main() {
    int school_number = 20;
    int student_number = 50;

    std::vector<School> schools;
    for(int i = 0; i < school_number; i++) {
        School school;  // first create School object, and then insert it into schools array
        for(int j = 0; j < student_number; j++) {
            Student student;  // same for Student object
            getline(file, line);
            istringstream c(line); 
            c >> student.age >> student.height;
            school.information.push_back(student);
        }
        schools.push_back(school);
    }
}

School *id = new School[school_number-1];

creates an array of school_number-1, and returns a pointer to it. The pointer needs to be manually freed after use with

delete[] id;

It returns a pointer because the memory gets allocated on the heap.

std::vector<School> does this automatically, and can also increase/decrease the size of the allocated memory when items are inserted/removed from the array.

Comments