Read From Text File To An Object Array

Hi. I would like to know if there is a way to directly store contents from a text file to an object array. This is my code:

This is the text file:

ID lname fname age phone
s111 Chand Kay 22 12345
s222 Dev Ron 19 12346
s333 Tom John 20 12456
s444 Timothy Jacob 22 12486

So as you can see, when I'm populating the arrays, I have declared separate varibles e.g string id; then I store the ids from the file into that variable, then I pass it as a parameter to the setter function to populate the array. So my question is: Is there any direct way for this? I feel like I'm wasting space by creating those variables. Or is it right?

Thanks
Last edited on
If I'm understanding your question correctly, just create one variable; manipulate; store; repeat; manipulate; store; repeat; etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <fstream>
#include <vector>

int main()
{
	std::ifstream input("input.txt");
	std::ofstream output("output.txt");

	std::vector<int> ivec;

	int val;
	while (!input.eof())
	{
		input >> val;
		ivec.push_back(val);
	}

	input.close();
	output.close();

	system("PAUSE");
	return 0;
}
Last edited on
Reading the input into temporary variables before assigning them to the class in the array is actually common practice. However your code has another problem
while(!Studentfile.eof()) eof() will not work the way to expect it.
https://softwareengineering.stackexchange.com/questions/318081/why-does-ifstream-eof-not-return-true-after-reading-the-last-line-of-a-file
You also need to check that to don't read more data than your array can hold.

A better way is
 
while (index  < MAX_SIZE && Studentfile >> id >> lname >> fname >> age >> phone)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

const int MAX_SIZE = 100;

class Student
{
private:
  string id;
  string lname;
  string fname;
  int age;
  int phone;
public:
  void setId(string);
  void setLname(string);
  void setFname(string);
  void setAge(int age);
  void setPhone(int);
  string getId();
  string getLname();
  string getFname();
  int getAge();
  int getPhone();
};
//Student setter methods
void Student::setId(string student_id)
{
  id = student_id;
}
void Student::setLname(string last_name)
{
  lname = last_name;
}
void Student::setFname(string first_name)
{
  fname = first_name;
}
void Student::setAge(int student_age)
{
  age = student_age;
}
void Student::setPhone(int student_phone)
{
  phone = student_phone;
}
//Student getter methods
string Student::getId()
{
  return id;
}
string Student::getLname()
{
  return lname;
}
string Student::getFname()
{
  return fname;
}
int Student::getAge()
{
  return age;
}
int Student::getPhone()
{
  return phone;
}

int main()
{
  Student student_array[MAX_SIZE];
  int index;
  string discard;
  ifstream Studentfile;
  //populate student_array
  Studentfile.open("Student.txt", ios::in);
  if (Studentfile.fail())
  {
    cout << "File was not found\n";
    system("PAUSE");
    exit(1);
  }
  getline(Studentfile, discard);
  index = 0;
  string id, lname, fname;
  int age, phone;

  while (index  < MAX_SIZE && Studentfile >> id >> lname >> fname >> age >> phone)
  {
    student_array[index].setId(id);
    student_array[index].setLname(lname);
    student_array[index].setFname(fname);
    student_array[index].setAge(age);
    student_array[index].setPhone(phone);
    index++;
  }
  cout << "Number of students read: " << index << "\n\n";
  // Studentfile.close(); not needed
  system("PAUSE");
  return 0;
}
So as you can see, when I'm populating the arrays, I have declared separate varibles e.g string id; then I store the ids from the file into that variable, then I pass it as a parameter to the setter function to populate the array. So my question is: Is there any direct way for this? I feel like I'm wasting space by creating those variables. Or is it right?

There are different ways of considering this. At the moment your setter functions don't do anything interesting, for example validating that the name does not contain digits, or validating that the phone contains digits only, or whatever checks you might need. But those functions might do some things like that, in which case directly inputting to the object's own variables might bypass those checks which could break the encapsulation of the data inside the class.

But, out of interest, you might indeed read directly from the file to the object, by overriding the input operator >> for the input stream.

example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <fstream>

using namespace std;

const int MAX_SIZE = 100;

// Student class
class Student {
    
private:
    string id;
    string lname;
    string fname;
    int    age;
    int    phone;

public:
    void setId(string);
    void setLname(string);
    void setFname(string);
    void setAge(int age);
    void setPhone(int);
    
    string getId() const;
    string getLname() const;
    string getFname() const;
    int    getAge() const;
    int    getPhone() const;
    
    friend std::istream & operator >> (std::istream & is, Student & s);
    
};

// Student setter methods
void Student::setId(string student_id)    { id    = student_id;    }
void Student::setLname(string last_name)  { lname = last_name;     }
void Student::setFname(string first_name) { fname = first_name;    }
void Student::setAge(int student_age)     { age   = student_age;   }
void Student::setPhone(int student_phone) { phone = student_phone; }

// Student getter methods
string Student::getId()    const { return id;    }
string Student::getLname() const { return lname; }
string Student::getFname() const { return fname; }
int    Student::getAge()   const { return age;   }
int    Student::getPhone() const { return phone; }

std::ostream & operator << (std::ostream & os, const Student & s)
{
    os << s.getId()    << ' '
       << s.getLname() << ' '
       << s.getFname() << ' '
       << s.getAge()   << ' '
       << s.getPhone();   
    return os; 
}

std::istream & operator >> (std::istream & is, Student & s)
{
    is >> s.id >> s.lname >> s.fname >> s.age >> s.phone;
    return is;
}

int main ()
{
    Student student_array[MAX_SIZE];

    // populate student_array
    ifstream Studentfile("Student.txt");
    if (Studentfile.fail())
    {
        cout << "File was not found\n";
        system ("PAUSE");
        exit(1);
    }
        
    Studentfile.ignore(100,'\n');
    int index = 0;
    
    while ( index < MAX_SIZE && Studentfile >> student_array[index] )
    {
        index++;
    }
    
    Studentfile.close();
    
    for (int i=0; i<index; ++i)
    {
        cout << student_array[i] << '\n';
    }
    
    system("PAUSE");
    return 0;
}


edit: Notice at line 31 the declaration friend std::istream & operator >>(

The input stream operator is made a friend of the Student class, giving it direct access to the member variables. In this case that wasn't necessary for the output stream operator as I used the proper getter functions.

Also note the use of const in the declarations of functions and parameters which will not modify the object.
Last edited on
Thank you all :) Really appreciate it.
Last edited on
Topic archived. No new replies allowed.