简体   繁体   English

从.txt 文件读取并将它们存储到向量中,其中 class 对象作为 c++ 中的值

[英]reading from .txt file and storing them to vector with class objects as values in c++

    vector<Person*> people;
ifstream in_stream;
string line;
string name;
int age;

in_stream.open("people.txt");
getline(in_stream, line);
stringstream sline(line);
sline >> name >> age;
Person a(name, age);
people.push_back(&a);


for (auto x : people)
    cout << *x << endl;

So i have this piece of code right here and im trying to read from a.txt file which is formed like that所以我在这里有这段代码,我试图从一个像这样形成的.txt文件中读取

Nick 23
Peter 27
Tom 42
Sofia 28
Daniel 39
Jonas 28

And save these people(name and age) in a vector which contains pointers to a class called Person.并将这些人(姓名和年龄)保存在一个向量中,该向量包含指向名为 Person 的 class 的指针。 The code above works fine but when i put the getline in a while loop so i can get all lines of the txt is bugging out and the vector will be like that上面的代码工作正常,但是当我将 getline 放在一个 while 循环中时,我可以得到 txt 的所有行都在窃听,向量将是这样的

28
28
28
28
28
28

No names just the age of the last person.没有名字只是最后一个人的年龄。 Any ideas what im doing wrong here?有什么想法我在这里做错了吗? Person.h人.h

#pragma once
#include <ostream>
#include <istream>
#include <iostream>
using namespace std;

class Person {
protected:
    string name;
    size_t age;
    virtual void print(ostream& out)  const;
public:
    Person(const Person& p);
    Person(string n, size_t a);
    Person();
    friend bool operator==(const Person& lhs, const Person& rhs);
    friend ostream& operator<<(ostream& out, const Person& rhs);
    friend istream& operator>>(istream& in, Person& rhs);

};

Person.cpp个人.cpp

#include "Person.h"

Person::Person(const Person& p) : name{p.name}, age {p.age}
{
}

Person::Person(string n, size_t a) : name{ n }, age{ a }
{
}

Person::Person() : name{"default"}, age {0}
{
}

bool operator==(const Person& lhs, const Person& rhs)
{
    if (lhs.name == rhs.name && lhs.age == rhs.age) {
        return true;
    }
    else {
        return false;
    }

}

void Person::print(ostream& out) const
{
    out << name << " " << age;
}

ostream& operator<<(ostream& out, const Person& rhs)
{
    rhs.print(out);
    return out;
}

istream& operator>>(istream& in, Person& rhs)
{
    string x;
    int y;
    in >> x >> y;
    rhs.name = x;
    rhs.age = y;
    return in;
}

Any help is highly appreciated.非常感谢任何帮助。

Let's say we have假设我们有

struct Person {
  std::string name;
  unsigned age;
};

I imagine that the teacher wants you to allocate each object with new , store its pointer, and then manually delete it later, but that's just because the teacher is teaching the wrong thing.我想老师希望你用new分配每个 object ,存储它的指针,然后稍后手动delete它,但这只是因为老师教错了。 You're not supposed to write new code like that.你不应该写这样的新代码。 Hold things by value (without any explicit pointers), or use smart pointers like std::unique_ptr .按值保存事物(没有任何显式指针),或使用诸如std::unique_ptr类的智能指针。

What the teacher probably wants (or, mistaken, thinks he should be wanting):老师可能想要什么(或者,错误地认为他应该想要什么):

Person *addPerson(std::vector<Person*> &people, std::string &&name, int age)
{ 
  auto *person = new Person(std::move(name), age);
  people.push_back(person);
  return person;
}

// optional
void removePerson(Person *person, std::vector<Person*> &people)
{
  auto where = std::find(people.begin(), people.end(), person);
  if (where != people.end())
  {
    delete *where; // * dereferences the iterator, giving the pointer back
    std::erase(where);
  }
}

void removeAllPeople(std::vector<Person*> &people)
{
  for (auto *person : people)
    delete person;
  people.clear();
}

int main()
{
  std::vector<Person*> people;

  //... add people, modify people, etc

  removeAllPeople(); // free the memory
}

What the teacher should be teaching instead:老师应该教的是什么:

// Hold people by value
std::vector<Person> people;

or maybe (even though it's unnecessary)或者也许(即使没有必要)

// Hold people using owning pointers
std::vector<std::unique_ptr<Person>> people;

What you could do instead is to generate the vector of pointers after the file has been read, ie您可以做的是在读取文件生成指针向量,即

std::istream &operator>>(std::istream &is, Person &person)
{
  return is >> person.name >> person.age;
} 

std::ostream &operator<<(std::ostream &os, const Person &person)
{
  return os << person.name << ' ' << person.age << '\n';
}

std::vector<Person> readPeople(std::istream &from)
{
  std::vector<Person> people;
  Person person;

  while (from >> person) // while the read had succeeded
    people.push_back(std::move(person));

  return people;
}

std::vector<Person*> makePointersTo(std::vector<Person> &people)
{
  std::vector<Person*> pointers;
  pointers.reserve(people.size()); // since we know exactly how many items we need

  for (auto &person : people)
    pointers.push_back(&person);

  return pointers;
}

int main()
{
#if 1
  std::ifstream input;
  input.open("people.txt");
  if (!input.is_open()) abort();
#else
  // we could also be reading from standard input
  std::istream &input = std::cin;
#endif

  std::vector<Person> const peopleValues = readPeople(input);
  std::vector<const Person*> const people = makePointersTo(peopleValues);

  for (auto *person : people)
    std::cout << *person << '\n';

  // The memory will be freed by the vector destructors, automatically
}

It's unnecessary to overload the comparison operators etc. - you don't need to be comparing people, unless the assignment explicitly asks for it.没有必要重载比较运算符等 - 你不需要比较人,除非任务明确要求它。

And also: the assignment is so small (a hundred lines or so) that it's just absurd to demand splitting it into multiple files.而且:作业是如此之小(一百行左右)以至于要求将其分成多个文件是荒谬的。 It's mind-bogglingly ridiculous.这是令人难以置信的荒谬。 Separation of concerns is very important aspect of teaching.关注点分离是教学中非常重要的方面。 If you're introducing stream I/O, you shouldn't be mixing it with how to split a program into logical modules that expose interfaces ( .h files), but are implemented elsewhere ( .cpp files).如果您要引入 stream I/O,则不应将其与如何将程序拆分为公开接口( .h文件)但在其他地方实现( .cpp文件)的逻辑模块混为一谈。 And in fact, you shouldn't be encouraging anyone writing such small programs (<1000 lines) to be split into multiple files.事实上,你不应该鼓励任何人编写这样的小程序(<1000 行)被拆分成多个文件。 It's counterproductive, always.总是适得其反。 It helps with nothing, just adds boilerplate, as if there was some boilerplate deity, whose priests' advice you had to follow or else.它没有任何帮助,只是添加样板,好像有一些样板神,你必须遵循他的牧师的建议,否则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM