0

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?

huza
  • 107
  • 6
  • 1
    C++ doesn't have [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array). If you want a run-time "array" use [`std::vector`](http://en.cppreference.com/w/cpp/container/vector) instead. – Some programmer dude Oct 15 '16 at 22:11
  • 1
    `Student information;` should be something like `std::vector information;` no? – πάντα ῥεῖ Oct 15 '16 at 22:23
  • as @JoachimPileborg said C++ doesn't have variable-length arrays, but there is another problem with your approach, every `School` has only one `Student`, you should declare an array of students inside `School`. – imadhsissou Oct 15 '16 at 22:23
  • @JoachimPileborg which part of this is requiring variable-length arrays? and can you elaborate little more on how to use vector (for example, the c >> line)? – huza Oct 15 '16 at 22:26
  • @7bisso what do you mean? I thought each school[school_number] has [student_number] Students with above approach – huza Oct 15 '16 at 22:28
  • Have you actually tried to compile any of this? Because it appears that you are just throwing out questions (also, you shouldn't ask more than one question per post) without even trying if your code has any chance of working. – UnholySheep Oct 15 '16 at 22:28
  • @UnholySheep thanks, I wasn't awared that I can't ask more than one question per post. And yes, I tried it before I post (except the vector one, because I'm not sure how to apply it this case). When I was doing it with just Student[i].age and Student[i].height, it was working, but when I try to combine it with School, it wasn't working – huza Oct 15 '16 at 22:31
  • 1
    @huza Don't try to learn c++ by guesswork. Get a [good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) in 1st place please. – πάντα ῥεῖ Oct 15 '16 at 22:33
  • @huza `School school[3];` "creates 3 schools with one student in each", you should read about classes if you didn't already ! you will understand this better, if you want to have more than one student in each school do as @πάντα ῥεῖ suggested. – imadhsissou Oct 15 '16 at 22:33
  • Thanks guys, I see what you guys are pointing out. – huza Oct 15 '16 at 22:36

4 Answers4

2

If you wanted to declare an array, that must have a const size. What you probably wanted is std::vector<Student>

lorro
  • 10,687
  • 23
  • 36
0

The way you have declared school it has only one student. You probably want a vector of students instead of one student in your school.

When you declare an array the number that you put inside the bracket is the length of the array. If the length of the array is n you can access elements 0 to n-1 when using the array. When declaring it, you should put n in the brackets though.

Pointers and arrays are very close concepts and in many situations interchangeable. If you have little C experience, sticking with arrays is safer.

esam
  • 580
  • 3
  • 13
  • thanks, now I see that each school has only one student. I look over vector so that I can put more students in it – huza Oct 15 '16 at 22:40
0
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.

tmlen
  • 8,533
  • 5
  • 31
  • 84
  • After reading others comment, I realized what the problems are, and your post cleared the questions I had. Really appreciate it. – huza Oct 15 '16 at 22:44
-1
School *id = new School[school_number-1];

School school[school_number-1];

the first one is declared on heap memory and the second one is declared on stack. You must delete the first one as soon as you done with it to avoid memory leak.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
BraStan
  • 1
  • 1