Reading from file and inserting into existing linked list node

Hi, so I have a linked list with nodes storing student names, course, id, phone number and so on. In the function below, i am trying to read from a file and add exam information to the existing nodes according to student id.

For context, In my Node, I stored
Student stu;
, which contains student id, name, course, phone number, currentcgpa, exam_cnt and an exam struct array.
Within the exam struct array, im storing trimester, year, numofsubjects and Subject sub; struct array.
Within the sub struct array, im storing subject code, name, credit hours and marks


From what i have done, the exam information is stored correctly according to student id, but the problem is the student name, course and phone number of my last node replaced all the other nodes (the student id and exam results were not replaced)

eg. Student 1 : 1200233 Tom Hills CS 790-3223
//some exam struct that belonged to the student with stu.id 1200233
Student2: 1201237 Tom Hills CS 790-3223
//some exam struct that belonged to the student with stu.id 1201237

(Tom Hills CS 790-3223 was stored in the last node of my linked list)

Can someone tell me what I have done wrong in my code below? Because Ive looked over it again and again and I thought it was supposed to working fine

exam.txt contents:
1201237 5 2012 2 UCCD1024 DATA_STRUCTURES_AND_ALGORITHMIC_PROBLEM_SOLVING 4 80 UCCD2502 INTRODUCTION_TO_INVENTIVE_PROBLEM_SOLVING_AND_PROPOSAL_WRITING 3 78

1300899 10 2012 2 UCCD1004 PROGRAMMING_CONCEPTS_AND_DESIGN 4 70 UCCD1024 DATA_STRUCTURES_AND_ALGORITHMIC_PROBLEM_SOLVING 4 80

1200233 5 2012 1 UCCD2502 INTRODUCTION_TO_INVENTIVE_PROBLEM_SOLVING_AND_PROPOSAL_WRITING 3 70

1541359 5 2015 2 UCCD3248 INTRODUCTION_TO_FASHION 4 90 UCCN7894 COLOUR_PSYCHOLOGY 3 75

1687432 1 2016 3 UCCD1004 PROGRAMMING_CONCEPTS_AND_DESIGN 4 38 UCCD1024 DATA_STRUCTURES_AND_ALGORITHMIC_PROBLEM_SOLVING 4 60 UCCD2502 INTRODUCTION_TO_INVENTIVE_PROBLEM_SOLVING_AND_PROPOSAL_WRITING 3 52

2162486 5 2021 2 UCCD2502 INTRODUCTION_TO_INVENTIVE_PROBLEM_SOLVING_AND_PROPOSAL_WRITING 3 85 UCCS1234 INTRODUCTION_TO_THEATRE 4 86

1900648 10 2020 1 UCCD1024 DATA_STRUCTURES_AND_ALGORITHMIC_PROBLEM_SOLVING 4 52

1200233 1 2013 3 UCCD1004 PROGRAMMING_CONCEPTS_AND_DESIGN 4 70 UCCD1024 DATA_STRUCTURES_AND_ALGORITHMIC_PROBLEM_SOLVING 4 80 UCCD2502 INTRODUCTION_TO_INVENTIVE_PROBLEM_SOLVING_AND_PROPOSAL_WRITING 3 78



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
bool List::set(int position, type newItem) {
	if (position > count) return false;
	find(position)->item = newItem;
	return true;
} //this is in another cpp file
[\code]


[code]
  bool InsertExamResult(char *filename, List *list)
{	
	ifstream e;
	e.open("exam.txt");

	if (!e)
	{
		cout << "Could not open exam.txt.\n";
		return false;
	}
	else
	{
		while (e >> stu.id)
		{
			Node *current = list->head;
			int position = 1;
			while (current != NULL)
			{
				if (strcmp(current->item.id, stu.id) == 0) //traverse list and find the node with matching student id to insert
				{
					e >> stu.exam->trimester >> stu.exam->year >> stu.exam->numOfSubjects;
					cout << stu.id << stu.exam->trimester << stu.exam->year << stu.exam->numOfSubjects << endl; //to check if read correctly
					stu.exam_cnt = current->item.exam_cnt;
					
					for (int j = 0; j < stu.exam[stu.exam_cnt]->numOfSubjects; j++)
					{
						
						e >> stu.exam[stu.exam_cnt].sub[j].subject_code >> stu.exam[stu.exam_cnt].sub[j].subject_name >> stu.exam[stu.exam_cnt].sub[j].credit_hours >> stu.exam[stu.exam_cnt].sub[j].marks;

						cout << stu.exam[stu.exam_cnt].sub[j].subject_code << stu.exam[stu.exam_cnt].sub[j].subject_name << stu.exam[stu.exam_cnt].sub[j].credit_hours << stu.exam[stu.exam_cnt].sub[j].marks << endl;
						
					}
					
					stu.exam[stu.exam_cnt].calculateGPA(); //this is a funtion in exam struct array
					cout << stu.exam[stu.exam_cnt].gpa << endl;

					stu.exam_cnt++;
					cout << stu.exam_cnt << endl;

					stu.calculateCurrentCGPA(); //this is a function in student struct
					cout << stu.current_cgpa << endl;
					
					list->set(position, stu); //did i use this set function correctly?
				}
				
				current = current->next; 
				position++;
			} 

			
		}
		e.close();
		return true;
	}
}
Last edited on
1
2
3
4
5
if (strcmp(current->item.id, stu.id) == 0) //traverse list and find the node with matching student id to insert
{
  // ...
  list->set( position, stu );
}
Insert to list usually means add new node to list.

What you seem to be doing is modifying an existing node. If you only modify and never insert, then the list never has any nodes that you could modify.

EDIT: Ah, the name of function is a red herring. You update scores of existing students with it.

What is stu? Where is it defined? What data does it contain at start?
You do overwrite one value in it with current student: stu.exam_cnt = current->item.exam_cnt;
What about the rest?


1
2
3
4
while (e >> stu.id) {

  if (strcmp(current->item.id, stu.id) == 0) {
    e >> 

You read stu.id from file. If that id is not found from the list, then the next value that you read into stu.id is not an id and this function is off the rails.

Perhaps:
1
2
3
if ( strcmp(current->item.id, stu.id) == 0 ) {
  stu = current->item;
  e >> 
Last edited on
hi @keskiverto, thanks for replying

i forgot to mention that I already have 7 nodes that contains student id, name and course, there is also an exam struct array with variables like trimester year etc.

My intention is to modify the existing nodes after matching the student id with the student id i read from file

In this case, i should use set function right?

Last edited on
Added stuff to previous post ...
1
2
3
if ( strcmp(current->item.id, stu.id) == 0 ) {
  stu = current->item;
  e >> 


hmm but i would need to read the stu.id from file and only traverse the list and find matching "current->item.id" then insert the other info
Update: I used
1
2
3
4
while(e.peek()!=EOF)
{
...
}


instead of

1
2
3
4
while(e >> stu.id)
{
...
}


but i still encountered the same error ( the student name and course in the original nodes keep getting replaced by one of the student (last student), the student ids and exam results are already placed correctly in the list), so i guess the problem is not there?
There is an issue with L30, 37. These are only executed when the id's match. When these lines aren't executed then this data isn't read from the file and the next time round the while loop L22 the file position isn't correct to read the next student id.

I'd suggest that you have a routine to read a record from the file into an appropriate struct - which returns a type istream&. Then L22 becomes something like:

 
for (eStruct es; eread(e, es); )


Then you use the contents of the eStruct.

Usually you'd overload operator>> to read a record from the file. You'd have a function like:

1
2
3
4
5
istream& operator>>(istream& is, eStruct& es)
{
    // Read one record from is into es
    return is;
}


then L22 would be:

 
for (eStruct es; e >> es; )
Last edited on
Note, is the list->set( position, stu ); supposed to do the same as current->item = stu;? If you can use the latter, then the set() is waste of time.

You have stu. Don't know where it comes from. I guess a global, that has data of last read student.
You update some fields of stu (id, exam) based of file data. Then you replace current->item with stu. Obviously, that replaces all fields including name, with whatever the stu has. That is the error.

If you first replace stu with current->item and then update some fields with file data, and then replace current->item with stu, then the unmodified fields of current->item stay unmodified, as they should.


Different approach:
1
2
3
4
5
6
7
ExamRecord ex;
while ( e >> ex ) {
  Node* current = list->find( ex.id );
  if ( current ) {
    // add to current->item data from ex
  }
}
@seeplus
@keskiverto
thank you both for your different approaches to my codes
i will go and take a look into it
i appreciate it
the problem is the student name, course and phone number of my last node replaced all the other nodes
You haven't shown any of the code that stores the student name, course or phone number. How are we supposed to find a bug in code that you haven't shown?

I suspect that the real problem is in the class that represents stu. Please show us the declaration of stu and it's class. My guess is that stu has a pointer to the name and all items in the list point to the same name.

Use Keskiverto's "different approach" above. Basically, you want to separate the logic into:
1: Something that reads a line from the file.
2. Something that finds a record in the list from student ID.
3. Something that adds exam info to a record.
Topic archived. No new replies allowed.