A management system program - Difficulty in Data Reading and Data Saving

I am creating a Library Management System in which I am required to make four different type of users,
- Admin
- System User
- Librarian
- Student

I made Admin class a base class and inherited all the other users from the Admin class.
Now, my next task was to define the member functions of classes and their functionalities. Just for an example, following is the header file for my Student Class,

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
class Student:public Admin
{
public:
	Student(); 
	Student(string, string);
	void addStudent();
	void editStudent();
	void deleteStudent();
	void updateStudent();
	void saveStudent();
	void searchStudent();
	void CheckStudentSave();
	void DisplayRecord(); 
	void Set_Student_Id(string);
	void Set_Student_College_Id(string);
	void Set_Student_Name(string);
	void Set_Student_Mobile(string);
	void Set_Student_Email(string);
	void Set_Student_Username(string);
	void Set_Student_Password(string);
	void Set_Student_Address(string); 
private:
	string student_id;
	string student_college_id;
	string student_name;
	string student_mobile;
	string student_email;
	string student_username;
	string student_password;
	string student_address;
};


So, basically, this program will involve lots of file handling. For now, I have defined functionalities of different functions and have made a function for the Admin account from which the admin will be able to add a new student and display the data of existing students.

I made a 2D dynamic array for Student data members, by this way,
1
2
3
4
Admin **student = NULL;
int studentsize = 0 // This will be used to control the size of student
student = new Admin*[1];
student[0] = NULL; 


So, basically, the studentsize will control the size of this array and it will add a new pointer of Admin with every new addition of Student. That pointer will then point to one Student Datatype variable.

- I have taken in the inputs of all the data members of Student Class in addstudent() function and then saved them by using the saveStudent() function, which is as below,
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

void Student::saveStudent()
{
	ofstream WriteStudent;
	try
	{
		WriteStudent.open("Student Data.FILE", ios::out | ios::app);
		WriteStudent << student_id << "\n";
		WriteStudent << student_college_id << "\n";
		WriteStudent << student_name << "\n";
		WriteStudent << student_mobile << "\n";
		WriteStudent << student_email << "\n";
		WriteStudent << student_username << "\n";
		WriteStudent << student_password << "\n";
		WriteStudent << student_address << "\n";
		WriteStudent.close();
		cout << "Success! Data has been Saved!\n";
	}
	catch (exception X)
	{
		cout << "File Failed to load. \n";
	}
	cout << "Press Enter to Continue..."; 
	getchar(); 
}


- Following is the admin menu code,

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

void AdminMenu()
{
	system("cls");
	cout << setw(50) << "****ADMINISTRATION ACCOUNT****"; 
	cout << endl << endl << endl; 
	cout << "1) Add a new Student\n"
		<< "2) Display All Students Record\n"
		<< "3) Log out\n\n"
		<< "Your choice: "; 
	int choice;
	cin >> choice;
	cin.ignore();
	switch (choice)
	{
	case 1:
		student = resizeuser(student, studentsize);
		student[studentsize - 1] = new Student; 
		student[studentsize - 1]->addStudent(); 
		break;
	case 2:
		LoadStudent(); 
		for (int i = 0; i < studentsize-1; i++)
			student[i]->DisplayRecord(); 
		break;
	case 3:
		return; 
	}
	cout << "Press Enter to Continue..."; 
	getchar();
	AdminMenu(); 
}


- As you can see, in "case 1", I am resizing the array and then calling the addstudent function with the resized array. The SaveStudent function will be itself called in the addStudent function. This function works perfectly for me.
Here is my resize function,
1
2
3
4
5
6
7
8
9
Admin **resizeuser(Admin **arr, int &size)
{
	Admin **temp = new Admin*[size + 1];
	for (int i = 0; i < size; i++)
		temp[i] = arr[i]; 
	delete[]arr;
	size++;
	return temp; 
}

(Please note, I can't use vectors in this because we aren't allowed to use anything we haven't studied yet)

- Now, for the displaying of the function, I first call LoadStudent function which will store all the data from the file into the pointer of student and then I am using it to display the record one by one. (Just to be clear, the loadstudent function somehow gives studentsize a size of one bigger than the actual size and that's why I am running the loop until (i - < studentsize-1))
Here is the code for Load Student Function

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

void LoadStudent()
{
	ifstream LoadStuff;
	LoadStuff.open("Student Data.FILE", ios::in);
	Admin **ptr = new Admin*[1];
	string temp;
	while (1)
	{
		ptr = resizeuser(ptr, studentsize);
		ptr[studentsize - 1] = new Student;
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Id(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_College_Id(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Name(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Mobile(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Email(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Username(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Password(temp);
		getline(LoadStuff, temp);
		ptr[studentsize - 1]->Set_Student_Address(temp);
		if (LoadStuff.eof())
			break;
	}
	student = new Admin*[studentsize];
	for (int i = 0; i < studentsize; i++)
	{
		student[i] = new Student;
		student[i] = ptr[i];
	}
	delete[]ptr;
	LoadStuff.close(); 
}


- This also apparently works perfectly. But I am facing some difficulties..

- If you add a student record and then close the program and then again log back into your program and ask the program to display all the records, the program works ok and it also displays the record.

- HOWEVER, if you add a student record and then "without closing the program" ask it to display the record, it gives error on this 2nd line,
1
2
for (int i = 0; i < studentsize-1; i++)
	student[i]->DisplayRecord(); 


- I don't know why is it so and I am unable to figure out the problem as well. It breaks the program here. Can anyone please help me out and possibly tell the issue I am facing here?

(Note: I can share all the codes of all Header/CPP Files as well if anybody wants. I didn't add all of them because that would have made it too long of a post to read, which it actually has already become)
Thank you very much!
You haven't shown the addStudent() method, but I suspect it does NOT add the student to the "Student Data.FILE" file. Then when you select option 2, you throw away the old contents of the student array and repopulate from the file. Since the file doesn't contain the last added student, it doesn't display it.

I think you can do several things to simplify the design of this program:

1. Change the inheritance. A student is not an administrator so why should class student inherit from class administrator? You should make a Person base class with things like a name, ID, email, username, password and address. The other classes should inherit from Person.

2. Don't put "student" in the names of the class Student members. It's redundant.

3. Create a method to read a student from a stream. This should call a method in class Person that reads the Person members. Create matching methods to write a person to a stream. The return value is a bool and you should return stream.good() which will indicate whether the reads/writes succeeded.

Note that in the real world, these would be >> and << operators, but since you haven't learned about vectors, I assume you haven't learned about overloaded operations either.

4. Have you learned about any of the standard library containers yet? Lists maybe? If so then you should use then to keep track of your students.

Make the student array a dynamic array pointers to Person. That way you can use the same dynamic array to track admins, teachers etc. In fact, consider making a class to handle the dynamic array of Persons.

5. When reading records from a file, the eof() flag won't be true until you try to read past the end of the file. This makes reading the last record a little tricky. Fortunately, if you have those methods I mentioned, it becomes easier:
1
2
3
4
5
6
7
8
9
10
11
12
void LoadStudents()
{
	ifstream LoadStuff;
	LoadStuff.open("Student Data.FILE", ios::in);
	delete[] students;
	studentSize = 0;
	Student tmp;
	while (tmp.read(LoadStuff)) {
		students = resizeStudents(students, studentSize);
		students[studentSize-1] = tmp;
	}
}

Topic archived. No new replies allowed.