read from specific txt file

Hi guys. I got a problem. I need to read data from a txt file that I wrote.


I have a student, class and school class.
I assign random names and numbers to fields in the student class. I randomly assign the class name to classes.

These random students that I create form a class. I'm writing this class to a txt file.
write to records.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void File::SaveClass(Classroom class) 
{
	string classroomName= class.getClassroomName();
	ofstream file;

	file.open("records.txt", ios::app); 
	file << classroomName << endl;
	file << class.getStudentCount() << endl;
	for (auto student : class.students) 
	{
		file<< student.GetName() << " " << student.GetSurname() 
                << " " << student.getNo() << endl;
	}
	


	file.close();
}



After that, I have to read this file and save it in a school classroom. How do I read this txt file and divide it into separate classes?

records.txt:

1
2
3
4
5
6
7
8
9
10
11
12
1B  
3
Aduriz Gamaneth 112
Lileas Kenderacse 142
Merdo Genco 102
2A
2
John Lascer 125
Yakki Kadraes 172
3H
1
Anotfera Konnes 122

Last edited on
Hello accuracy12,

One function is not enough information to say specifically what you need to do.

You could try making a copy of the "SaveClass" functionand rename it to "ReadClasses" then reverse what is inside.

One difference is when opening a file stream for input it is best to check that it worked.
1
2
3
4
5
6
7
if (!file)
{
    std::cout<< "\n    An error message\n";

    exit(1);  // <--- No need to continue because you can not read anything.
    //return;  // <--- Or return to the main menu.
}

Put this after line 6.

The range based for loop may have to change to a regular for loop.

Not knowing what the class looks like I do not know how well this would work. You can also look at the code and what you did for keyboard input for help.

Hope that helps,

Andy
student.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Student
{
public:

	string getName();
	string getSurname();
	void setNo(int);
	int getNo();
	
	Student();
	~Student();

private:
	string name, surname;
	int studentNo;
};


classroom.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Classroom
{
public:
	
	list<Student> students;
	list<Student>::iterator iter;
	static int TotalClassroomCount;
	void AddStudent(Student);
	void DeleteStudent(int studentNo);
	int getStudentCount();
	string getClassroomName();
	Classroom();
	~Classroom();
private:
	string classroomName;
	
};


school.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class School 
{

public:
	
	list<Classroom> classrooms;
	list<Classroom>::iterator iter;
	void AddClassroom(Classroom);
	void DeleteClassroom(string classroomName);
	School();
	~School();
private:
	

};

I write
I need to read this file and keep the information I read in a school object.
But I didn't understand how to parse this file for classes and students.

no problem writing to file. my problem is that I read this file where I write the information and transfer the class and student information to a school object.

records.txt

1
2
3
4
5
6
7
8
9
10
11
12
1B  			// classroom name
3			// the number of students in 1B
Aduriz Gamaneth 112	// name,surname and number of students	
Lileas Kenderacse 142
Merdo Genco 102
2A			
2
John Lascer 125
Yakki Kadraes 172
3H
1
Anotfera Konnes 122



How can i read this file?

Thanks for help.
Hello accuracy12,

Now that I understand better I will see what I can come up with.

Andy
Hello accuracy12,

This has taken awhile because of the code that is missing. I had to guess at some things to make this work. This is not the best code, I admit it can be better, but for now it does read the file. Because of what is missing I am only guessing at what you are trying to do.

Working off what you first posted and the header files I came up with this first:
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
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

#include <fstream>
#include <chrono>
#include <thread>

#include "File.h"
#include "Classroom.h"
#include "Student.h"
#include "School.h"

void File::ReadClass(Classroom classroom)
{
	const std::string inFileName{ "Records.txt" };

	std::string classroomName, studentName, surName;
	int numOfStudents{}, studNum{};
	Student student;
	School school;

	std::ifstream inFile(inFileName);

	if (!inFile)
	{
		std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread". Optional as is the header files.
		/*return 1;*/  exit(1);  // If not in "main".
	}

	while (inFile >> classroomName >> numOfStudents)
	{
		classroom.students.clear();

		classroom.SetClassroomName(classroomName);

		for (int lc = 0; lc < numOfStudents; lc++)
		{
			inFile >> studentName >> surName >> studNum;
			student.setName(studentName);
			student.setSurName(surName);
			student.setNo(studNum);
			classroom.students.push_back(student);
		}

		school.classroomsList.push_back(classroom);

		TotalClassroomCount++;

		//std::cout << std::endl; // <--- Used as a break point for testing. Delete if not needed.
	}

	//std::cout << std::endl; // <--- Used as a break point for testing. Delete if not needed.
}

This will read the file unfortunately when the function ends so will some of the information.

***** Disregard this as it did not work the way I was thinking. ******
After I worked this out I thought of a better way. This starts with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class School
{
    //code here
}

class Classroom : public School
{
    //code here
}

class Student : public Classroom
{
    //code here
}

By tying all the classed together you only have to define one object of student and it will have access to all the public functions of the other classes.

This makes it a little easier to work with than trying to keep three separate class straight.

This "read" function may need to be revised to work with what you have, but should give you a good starting place.

I still want to try something different. I will let you know when I have finished.

Hope that helps,

Andy

EDIT:
Last edited on
Hello Andy,

I appreciate your help. I'm busy for now, but you thought so well. I kept each line in an array and tried to do it that way, but it didn't. Thanks for your answers. I'il wait for your answer when you try something different.
Hello accuracy12,

You first wrote:

I have a student, class and school class.
I assign random names and numbers to fields in the student class. I randomly assign the class name to classes.

These random students that I create form a class. I'm writing this class to a txt file.
write to records.txt


This is a nice start, but I do not feel as these are the full instructions that you were given.

The header files and input file that you have posted are a help, but not enough. The ".cpp" files are missing and I have to guess at some of the code. The function File::SaveClass() suggests that there is a "File" class that is missing.

I feel like you want me to write a program based on one function and the header files.

Not seeing what you have done so far the code I can write may contain some things that you are not ready for, but work the best.

To do what I believe is best I will have to write the code I have in a new way. It would help to know how the program should work without having to guess at what to do.

After doing some reading the code I showed you with inheritance should work, but I did have some trouble trying to change the code I had first come up with. For this I am trying to start over.

While I am here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Student
{
public:

	string getName();
	string getSurname();
	void setNo(int);
	int getNo();
	
	Student();
	~Student();

private:
	string name, surname;
	int studentNo;
};

Lines 9 and 10 are not needed unless you actually put something in the function body to set the variables. Otherwise the compiler will create a default ctor and dtor for you. If you create an overloaded ctor you will need to include the default ctor, but the compiler will still create the default dtor.

This holds true for all three classes.

I am thinking that the variable TotalClassroomCount should be defined in the "School" header file, but std::list<Classroom> classroomsList along with the ".size()" function would negate the need for "TotalClassroomCount" as long as the input file has no duplicate classrooms. And I did change the name of the list as there are to many "classroom"s used in the program also the name gives a better name of what the "list" is for.

Hope that helps,

Andy
Hello Andy,


First, "names.txt" for the student in the file class
and random from "surname.txt"
I generate names and surnames.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class File
{
public:
	string* ReadFile(string filename); 
	string RandomName();
	string RandomSurname();
	void SaveStudent(Student);  //save records.txt
	void SaveClass(Classroom); //save records.txt
	void clearTxtContext();
        void CreateSchoolFromTxt(); 
	File();
	~File();

};



in this function(createschoolfromtxt), I need to create a school object using class and students from records.txt. I still don't know how to do this, and I have another class called program.

1
2
3
4
5
6
7
8
9
class Program
{
public:

	School school; 
	void Run();  
	Program();
	~Program();
};




the school object in this class is created with the createchoolfromtxt function.
in this function(void Run) the user must be shown a menu. the user should be able to add or remove students with this menu and add or remove classes.
But there is one thing I do not understand.
I have to write data to any line of records.txt file when I add student. I still don't understand how to do this.
I tried to do it using file modes, but it didn't.


Thanks for help.



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
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;

//----------------------------------------------------------

class Student
{
public:
   string firstName;
   string lastName;
   string room;
   string id;
};

//----------------------------------------------------------

class Room
{
public:
   string name;
   vector<Student> students;
};

//----------------------------------------------------------

class School
{
public:
   string name;
   vector<Room> rooms;
   void read( istream &strm );
};


void School::read( istream &in )
{
   for ( string roomName; in >> roomName; )
   {
      Room rm( { roomName } );
      int n;
      in >> n;
      while ( n-- )
      {
         Student s;
         s.room = roomName;
         in >> s.firstName >> s.lastName >> s.id;
         rm.students.push_back( s );
      }
      rooms.push_back( rm );
   }
}


//----------------------------------------------------------


int main()
{
   School school( { "C++ School" } );
// ifstream in( "data.txt" );
   istringstream in( "1B                    \n"
                     "3                     \n"
                     "Aduriz Gamaneth 112   \n"
                     "Lileas Kenderacse 142 \n"
                     "Merdo Genco 102       \n"
                     "2A                    \n"
                     "2                     \n"
                     "John Lascer 125       \n"
                     "Yakki Kadraes 172     \n"
                     "3H                    \n"
                     "1                     \n"
                     "Anotfera Konnes 122   \n" );

   school.read( in );

   cout << "School: " << school.name << '\n';
   for ( auto &rm : school.rooms )
   {
       cout << "\nClassroom " << rm.name << ":\n";
       for ( auto &s : rm.students ) 
       {
          cout << s.firstName << " " << s.lastName 
               << "   (room = " << s.room << ", id = " << s.id << ")\n";
       }
   }
}


School: C++ School

Classroom 1B:
Aduriz Gamaneth   (room = 1B, id = 112)
Lileas Kenderacse   (room = 1B, id = 142)
Merdo Genco   (room = 1B, id = 102)

Classroom 2A:
John Lascer   (room = 2A, id = 125)
Yakki Kadraes   (room = 2A, id = 172)

Classroom 3H:
Anotfera Konnes   (room = 3H, id = 122)

Last edited on
Add these methods to every class :
1
2
    istream &read(istream &is);
    ostream &write(ostream &os);


These are matching pairs: if you write an instance with write() then you should be able to read it with read().

Put the definitions next to each other so you can be sure that they work as a matching pair when you write them.

If you do it this way, the code practically writes itself. I wrote it as fast as I could type it.
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <string>
#include <iostream>
#include <list>

using std::string;
using std::istream;
using std::ostream;
using std::list;
using std::cin;
using std::cout;

class Student
{
  public:

    string getName();
    string getSurname();
    void setNo(int);
    int getNo();

      Student();
    // ~Student();

    istream &read(istream &is);
    ostream &write(ostream &os);
  private:
      string name, surname;
    int studentNo;
};

Student::Student() : studentNo(0) {}

class Classroom
{
  public:

    list < Student > students;
    list < Student >::iterator iter;
    static int TotalClassroomCount;
    void AddStudent(Student);
    void DeleteStudent(int studentNo);
    int getStudentCount();
    string getClassroomName();
    // Classroom();
    // ~Classroom();
    istream &read(istream &is);
    ostream &write(ostream &os);
  private:
      string classroomName;

};

class School
{

  public:

    list < Classroom > classrooms;
    list < Classroom >::iterator iter;
    void AddClassroom(Classroom);
    void DeleteClassroom(string classroomName);
    // School();
    // ~School();
    istream &read(istream &is);
    ostream &write(ostream &os);
  private:

};


istream &
Student::read(istream &is)
{
    is >> name >>  surname >> studentNo;
    is.ignore(1000000, '\n');	// skip the newline
    return is;
}

ostream &
Student::write(ostream &os)
{
    return os << name << ' ' << surname << ' ' << studentNo << '\n';
}

istream &
Classroom::read(istream &is)
{
    students.clear();
    getline(is, classroomName);
    unsigned count;
    is >> count;
    Student tmp;
    while (count--) {
	if (tmp.read(is)) {
	    students.push_back(tmp);
	}
    }
    return is;
}

ostream &
Classroom::write(ostream &os)
{
    os << classroomName << '\n';
    os << students.size() << '\n';
    for (auto &tmp : students) {
	tmp.write(os);
    }
	
    return os;
}

istream &
School::read(istream &is)
{
    Classroom tmp;
    classrooms.clear();
    while (tmp.read(is)) {
	classrooms.push_back(tmp);
    }
    return is;
}

ostream &
School::write(ostream &os)
{
    for (auto &tmp : classrooms) {
	tmp.write(os);
    }
    return os;
}

int main()
{
    School s;
    s.read(cin);
    s.write(cout);
}
Topic archived. No new replies allowed.