Как мне распечатать из набора указателей на объекты в C ++? - PullRequest
1 голос
/ 25 марта 2012

У меня есть класс студентов, который я сохраняю в набор в моем файле cpp. Проблема, которую я имею, распечатывает фактический объект Студента. Я перепробовал все, что мог придумать, и все, что я получил, это либо адрес указателя, либо ошибка компиляции. У меня в классе ученика есть метод display, который распечатывает всю информацию в том формате, в котором я хочу.

Вот что у меня есть.

.cpp файл

#include "Name.h"
#include "Student.h"
#include<iostream>
#include<string>
#include<set>
using namespace std;

int main()
{
    Student s1;
    set<Student *> s;
    while(cin>>s1)
    {
        s.insert(new Student(s1));
    }
    for(set<Student *>::const_iterator it = s.begin(); it != s.end(); ++it)
    {
        &(*it).display(cout);
    }
}

Student.h

#ifndef STUDENT_H
#define STUDENT_H
#include<string>
#include<iostream>
#include<map>
#include "Name.h"
typedef std::map<std::string, int> GradeMap;

class Student {
public:
    Student(const std::string id="", const Name& name = Name(),const GradeMap & grades = GradeMap()):id_(id),name_(name),grades_(grades){}
    Student(const Student& s):id_(s.id_),name_(s.name_),grades_(s.grades_){}
    virtual ~Student(){}
    friend std::istream& operator>>(std::istream& is, Student& s);

    virtual void display(std::ostream& os) const{
        os << "ID: " << id_ <<std::endl<< "Name: " << name_ << std::endl;

        for(std::map<std::string, int>::const_iterator it = grades_.begin(); it != grades_.end(); ++it)
            os<<it->first<<' '<<it->second<<std::endl;
    }

private:
  std::string id_;
  Name name_;
  GradeMap grades_;

};

inline std::istream& operator>>(std::istream& is, Student& s)
{
    std::string id;
    std::string key;
    int grade;
    int count = 0;
    Name name;

    if(is>>id>>name>>count){
        s.id_ = id;
        s.name_ = name;
    }
    else {
        is.setstate(std::ios_base::failbit);
    }


    for(int i = 0; i < count; i++)
    {
        if(is>>key>>grade)
        {
            s.grades_[key] = grade;
        }
    }
    return is;
}
#endif

Name.h

#ifndef NAME_H
#define NAME_H
#include <string>
#include <iostream>
class Name{
    public:
        explicit Name(const std::string& first = "",const std:: string& last = ""):first_(first),last_(last){}
        friend std::ostream& operator<<(std::ostream&, const Name&);
        friend std::istream& operator>>(std::istream&, Name&);
private:
        std::string first_;
        std::string last_;
};

inline std::ostream& operator<<(std::ostream& os, const Name& n){
    return os << n.first_<< " " << n.last_;
}
inline std::istream& operator>>(std::istream& is, Name& n){
    std::string first,last;
    if(is >> first >> last ){
        n.first_ = first;
        n.last_ = last;
    }
    else
        is.setstate(std::ios_base::failbit);
    return is;
}
#endif

также вот файл, который я использую для проверки

111111111
john smith
3
comp2510 25
eng2525 60
bio3512 45
222222222
jane doe
2
elex1510 90
comp2510 85

Файл организован так. Сначала указывается идентификатор студента, затем его имя, а затем число пройденных ими курсов, за которым следует столько курсов, а также оценка, которую они получили в этом курсе.

Мой вопрос: как бы вы распечатали фактический объект студента?

Ответы [ 3 ]

4 голосов
/ 25 марта 2012

В цикле for:

for(set<Student *>::const_iterator it = s.begin(); it != s.end(); ++it)
{
    &(*it).display(cout);
}

(*it) - это Student*:

(*it)->display(cout);
1 голос
/ 25 марта 2012

Итератор ведет себя как указатель на фактический элемент set, поэтому разыменование итератора дает вам элемент set. Этот элемент сам по себе является указателем на Student объект. Так что вам нужно разыменовать дважды:

(**it).display(cout);

Что лучше записать как:

(*it)->display(cout);

Еще лучше, перегрузить оператор << аналогично >>, и вы можете написать:

cout << (**it);

(Скобки только для ясности.)


Еще лучше, вообще не возиться с указателями, и объявить s как set<Student>. Конечно, будет немного больше копирования, но вы прекратите утечку памяти и получите взамен более чистый, простой, безопасный и более обслуживаемый код. (Вам понадобится перегрузка < для сравнения Student с.)

0 голосов
/ 26 марта 2012
#include <string>
#include <iostream>

class Student
{
    std::string m_name;

public:
    Student(const std::string& name) :
    m_name(name)
    {
    }

    std::ostream& display(std::ostream& os) const
    {
        return os << m_name;
    }

    bool operator<(const Student& other) const
    {
        return m_name < other.m_name;
    }
};

Определить operator<< для Student:

std::ostream& operator<<(std::ostream& os, const Student& student)
{
    return student.display(os);
}

Используя его:

#include <set>
#include <algorithm>
#include <iterator>

int main()
{
    std::set<Student> students;

    students.insert(Student("Alan"));
    students.insert(Student("Rudy"));

    std::copy(students.begin(), students.end(),
              std::ostream_iterator<Student>(std::cout, ", "));

    return 0;
}

Выход:

Alan, Rudy, 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...