-2

Attempting to read from a source file to store person objects into a container.

A person object is initialized with a random age, id and a categories vector of five assorted chars.

person.hpp

class person 
{
    protected :
    int age; // 0 - 99
    int id;  // 20181104 eight numeric characters 
    std::vector<char> categories = {'A', 'B', 'C', 'D', 'E'}

    person()
    {
    ...
    std::shuffle(categories.begin(), categories.end(), 
      random_generator::instance().gen);
    }
}; 

random_generator.hpp

Used to shuffle the person class member categories with std::shuffle

class random_generator
{
    public :
        static random_generator& instance()
        {
            static random_generator instance;
            return instance;
        }
        random_generator(random_generator const&)            = delete;
        random_generator& operator=(random_generator const&) = delete;
    private :
        random_generator(){}
        std::random_device rd;
        std::mt19937 gen{rd()};

    ...
    friend class person;
};

person.cpp

std::ostream& operator<<(std::ostream& output, const person& p)
{
  output << p.id <<  ' ' << p.age; 

  for(char c : p.categories)
    output << c << ' ';

  return output;
}
std::istream& operator>>(std::istream& input, person& p)
{
  input >> p.id >> p.age;

  // how can I implement this; suggested alternatives are most welcome

  return input;
}

person.txt source file

19850319 33 A C E B D
06111990 28 B E C A D

andres
  • 301
  • 6
  • 21
  • 1
    Did you write person.txt yourself, or generate it using your `operator<<`? They look slightly mismatched. – aschepler Aug 01 '18 at 21:21
  • 1
    Option 2 of Answer 1 in [Read file line by line](https://stackoverflow.com/questions/7868936/read-file-line-by-line) should get you going. Read in the line, pop the line in a stringstream, parse the stringstream until you run out of tokens. – user4581301 Aug 01 '18 at 21:23
  • 1
    Unrelated: `random_generator`'s constructor should be private to prevent silly buggers and the copy and move constructors and assignment operators deleted.id you want it to be a proper singleton. – user4581301 Aug 01 '18 at 21:27
  • My favorite thing about this 'community' is seeing down-votes with no justification – andres Aug 01 '18 at 21:45
  • I'm afraid the bad behaviour goes both ways. As often than not when I justify my downvoting, or try to justify someone else's, I get nonsense that makes it not worth the time I spent explaining. As a result, I only drop comments where I think the recipient will take the comment as intended, improve the post, and give me some chance at getting the reputation I invested in the downvote back. – user4581301 Aug 01 '18 at 22:13

1 Answers1

1

I guess I don't see where the difficulty would be. Reading them in will be a mirror image of writing them out. If you can count on there always being five of them, then you'd basically just do something like this:

std::istream& operator>>(std::istream& input, person& p)
{
  input >> p.id >> p.age;

  p.categories.clear();
  for (int i=0; i<5; i++) {
     char ch;
     input >> ch;
     p.categories.push_back(ch);
  }

  return input;
}

If it's basically a matter of reading categories until you reach the end of the line, then it'll probably be easiest to read the line into a string, shove the string into a stringstream, then read characters until you reach the end of the stringstream:

while (input >> ch)
    p.categories.push_back(ch);

That's not generally the fastest way to do things (creating a stringstream is somewhat slow), but given that you're dealing with I/O, parsing speed is only rarely much of a consideration.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111