Как сохранить экземпляр класса в векторе?

#c #loops #class #vector #instance

#c #циклы #класс #вектор #экземпляр

Вопрос:

Я создал класс для ученика с курсом и оценкой, программа продолжает запрашивать нового ученика, пока не будет указано имя stop . Для хранения этих экземпляров я хочу использовать вектор, но я не нашел другого способа их хранения, кроме как сначала создать массив для экземпляров, а затем поместить их обратно в вектор. Возможно ли выделить место для одного экземпляра и удалить значения, сохраненные в Student student после использования, чтобы его можно было использовать повторно?

 int i=0;
Student student[20];
vector<Student> students;


cout << "Name?" << endl;
getline(cin,student[i].name);
while((student[i].name) != "stop")
{
    student[i].addcoursegrade();
    students.push_back(student[i]);
    i  ;
    cout << "Name?" << endl;
    getline(cin,student[i].name);
    if((student[i].name) == "stop")
        break;

};
 

Я также использую векторы внутри класса для хранения значений для курса и оценки, поскольку они также должны расти. Код для класса находится здесь:

 class Student {
public:
    string name;

void print() {
    cout << name ;

    for (int i = 0; i < course.size(); i  )
        cout << " - " << course[i] << " - " << grade[i];
    cout<<endl;
}

void addcoursegrade() {
    string coursee;
    string gradee;

    cout << "Course?" << endl;
    getline(cin, coursee);
    course.push_back(coursee);
    while (coursee != "stop") {
        cout << "Grade?" << endl;
        getline(cin, gradee);
        grade.push_back(gradee);
        cout << "Course?" << endl;
        getline(cin, coursee);
        if (coursee != "stop")
            course.push_back(coursee);
        else if(coursee == "stop")
            break;
    }
};

private:
   vector<string> course;
   vector<string> grade;
};
 

Комментарии:

1. Просто используйте один Student экземпляр, а не массив. Для чистоты поместите его в цикл. .push_back копирует объект, поэтому вам не нужны отдельные экземпляры для начала.

2. «но я не нашел другого способа их хранения, кроме» Как именно вы пытались «найти» способы сделать это? Например, вы пробовали использовать поисковую систему для поиска примеров использования .push_back ?

3. Обратите внимание, что использование массива здесь почти сводит на нет смысл использования a vector . Как только Student будет введен 21-й, Ка-бла-бла!

4. Посмотрите это . Нет проблем с помещением a Student в вектор. Итак, возьмите этот код, добавьте к нему и продублируйте проблему, которую, как вы утверждаете, вы видите. Или просто примите код по ссылке как хороший и работайте оттуда.

Ответ №1:

Вместо того, чтобы создавать массив, а затем возвращать его обратно, просто сохраните один экземпляр и переназначьте его:

 Student student;
vector<Student> students;

cout << "Name?" << endl;
getline(cin,student.name);
while((student.name) != "stop")
{
    student.addcoursegrade();

    // this line copies the student in the vector
    students.push_back(student);

    // then, reassign the temp student to default values
    student = {};

    cout << "Name?" << endl;
    getline(cin,student.name);
    if((student.name) == "stop")
        break;
};
 

Комментарии:

1. Ключевым моментом здесь и, возможно, причиной путаницы OP является то, что vector в нем хранятся типы значений, поэтому содержимое student копируется students.push_back(student) , оставляя student его доступным для повторного использования.

2. student = {} было именно тем, что я искал. Большое спасибо!: D

3. С удовольствием! Кроме того, помните, что = {} это не создание student другого ученика, а просто переназначение значений по умолчанию. И это нормально, поскольку, когда вы нажимаете назад, он создает копию в векторе.

Ответ №2:

Меня беспокоило несколько вещей:

  • То, как были структурированы ваши циклы, дублируя getline . Я предпочитаю массив while(true) с разрывом при появлении завершающего ввода.
  • Нет необходимости в массиве в стиле C. std::vector это путь!
  • отдельные массивы для курса и оценки. Вместо этого я предпочитаю одну запись, в которой хранятся как курс, так и оценка
  • индексы в ваших циклах, которые используются только для доступа к элементам в коллекции. (Просто используйте цикл for на основе диапазона)
  • Не создавайте Student объект, пока вам не понадобится. Используйте локальные переменные для ввода строк.

Как и во всем, что есть в C , можно сделать гораздо больше, чтобы улучшить его: например, добавить конструкторы для ваших объектов, инициализировать с помощью современного синтаксиса, использовать семантику перемещения и т. Д. Но я просто вношу минимальные изменения.

Я бы решил это так:

 #include <vector>
#include <string>
#include <iostream>

using namespace std;

struct CourseGrade {
    string course;
    string grade;
};

class Student {
public:
    string name;

    void print() {
        cout << name;

        for (autoamp; courseGrade : courseGrades) {
            cout << " - " << courseGrade.course << " - " << courseGrade.grade;
        }
        cout << endl;
    }

    void addcoursegrades() {
        while (true) {
            cout << "Course?" << endl;
            string course;
            getline(cin, course);
            if (course == "stop") break;

            cout << "Grade?" << endl;
            string grade;
            getline(cin, grade);

            CourseGrade courseGrade;
            courseGrade.course = course;
            courseGrade.grade = grade;
            courseGrades.push_back(courseGrade);
        }
    }

private:
    vector<CourseGrade> courseGrades;
};


int main() {
    vector<Student> students;

    while (true) {
        cout << "Name?" << endl;
        std::string name;
        getline(cin, name);
        if (name == "stop") break;

        Student student;
        student.name = name;
        student.addcoursegrades();
        students.push_back(student);
    };

    for (autoamp; student : students) {
        student.print();
    }
}