Need help reading .txt file data into array of structs

I'm working on a project where I need to read a .txt file that consists of a name(first and last, or just first) and 8 grades delimited by a comma (6 project grades, 2 exam grades), with up to 20 students. We just started learning about structs so I'm still trying to figure them out. The text file is formatted as such:

John Doe,95,84,67,78,85,92,100,76
Susan,83,56... etc..

I thought this program would be a breeze but I've been stuck for hours trying to figure why it won't work. I can get the name to read into the array using the getline function, but I can't figure out how to read in the grades. Here's what I have right now, not working of course, but just to show what I'm trying to do.

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

const int SIZE = 20;
const int gradeSize = 4; 
fstream gradeFile;
string fileName; 

struct studentInfo
{
	char studentName[SIZE];
	char letterGade[gradeSize];      //not used at this point
	int projectOneGrade[gradeSize];
	int projectTwoGrade[gradeSize]; 
	int projectThreeGrade[gradeSize];
	int projectFourGrade[gradeSize]; 
	int projectFiveGrade[gradeSize];
	int projectSixGrade[gradeSize];
	int examOneGrade[gradeSize];
	int examTwoGrade[gradeSize]; 
	double finalWeightedAvg;         //not used at this point
};

// prototypes
void ProcessTextFile(string&, studentInfo[]);  
bool OpenFile (fstream&, string);              //simply opens input file

int main ()
{ 
studentInfo student[SIZE]; 

ProcessTextFile(fileName, student); 

return 0; 
}

void ProcessTextFile(string& fileName, studentInfo student[])
{	
int i = 0; 

// no issues with this function, so I left out the definition
OpenFile(gradeFile, GRADE_FILE); 

while(!gradeFile.eof())	
{
	for(i = 0; i < SIZE; i++)
	{
         // this reads in fine
	gradeFile.getline(student[i].studentName,SIZE, ',');

         /* these are what I'm having trouble with, how can I read each 
            grade into each member?
         */
	gradeFile >> student[i].projectOneGrade;  
	gradeFile >> student[i].projectTwoGrade;  
	gradeFile >> student[i].projectThreeGrade;  
	gradeFile >> student[i].projectFourGrade;  
	gradeFile >> student[i].projectFiveGrade;  
	gradeFile >> student[i].projectSixGrade;  
	gradeFile >> student[i].examOneGrade;  
	gradeFile >> student[i].examTwoGrade;  
	}
}
}


The grades have to be integer arrays. I've tried different methods such as reading the grade into an int variable, and then trying to set the array equal to that, like student[i].projectOneGrade = grade1; but I got an error saying
"cannot convert from 'int' to 'int [4]'." Perhaps I'm skipping a step? I'm at a complete loss, any help would be welcome!



I've made a simple example, it loads/saves one person and an array of people as a structure.

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
#include <string>
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <fstream>

using namespace std;

class Person {
public:
   char name[20];
   int age;

   Person(){}
   Person(const char* n, int age): age(age)
   {
      strcpy(name, n);
   }
};

int main ()
{
   const char* FILENAME = "Z:\\Temp\\file.txt";
   const int NUM = 10;
   ofstream outfile;
   ifstream infile;

   //Save person
   Person* person1 = new Person("Joe", 10);
   outfile.open(FILENAME, ofstream::trunc);
   outfile.write((char*)person1, sizeof(Person));
   outfile.close();

   //Load person
   Person* person2 = new Person();
   infile.open(FILENAME);
   infile.read((char*)person2, sizeof(Person));
   infile.close();

   cout << person2->name << endl;

   //Save array
   Person* persons = new Person[NUM];

   for(int i = 0; i < NUM; i++)
      itoa(i, &persons[i].name[0], 10);  //Just assign number as each person's name

   outfile.open(FILENAME, ofstream::trunc);
   outfile.write((char*)persons, sizeof(Person) * NUM);
   outfile.close();

   //Load array
   Person* persons2 = new Person[NUM];
   infile.open(FILENAME);
   infile.read((char*)persons2, sizeof(Person) * NUM);
   infile.close();

   cout << persons2[5].name << endl;

   return 0;
}


Or you can do as you have done above, I suggest you use read rather than input stream.
Last edited on
HI,Turbine ,
Why not enter your examples that I run the code again. Now where are my IDE garbled.
I have a suggestion: Use the list to complete these functions.
I think so: students with a structure to write the attributes, then enter each information; then saved the information for completion of these, in order to ensure data integrity is best viewed in the document data. This knowledge will be used to read the file.
Here is my proposal that, if I thought wrong, I welcome you to comment, thank you. (My English is not very good, here are to be translated)
deeburt, you are currently studying the structure it?
closed account (DSLq5Di1)
1
2
3
struct studentInfo
{
    int projectOneGrade[gradeSize];

gradeFile >> student[i].projectOneGrade;

You cannot read directly into an array as you are trying to do here.

gradeFile >> student[i].projectOneGrade[0]; // first element

deeburt wrote:
The grades have to be integer arrays.

Why if you are not using them as arrays? perhaps your structure should be defined as,

1
2
3
4
5
6
7
8
struct studentInfo
{
    char studentName[SIZE];
    ...
    int projectGrades[6]; // instead of maintaining a dozen individual variables
    int examGrades[2];
    ...
};


1
2
3
4
5
6
7
gradeFile.getline(student[i].studentName,SIZE, ',');

for (int n = 0; n < 6; n++)
{
    gradeFile >> student[i].projectGrades[n];
}
// etc. 
fstream gradeFile;
This is a mistake
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
  #include<iostream>
#include<fstream>
#include<conio.h>
using namespace std;
const char Address[]= "d:\\DB\\DATABASE.txt"; 
const int size      = 20;
int       count     = 1; //Counter
struct StudentInfo
{
	int StudentID;
	char StudentName[size];
	int ProjectOneGrade;
	int ProjectTwoGrade;
	int ProjectThreeGrade;
	int ExamOneGrade;
	int ExamTwoGrade;
	StudentInfo *next;      //Here is a pointer pointing to itself, its role is to point to the next structure.
};
StudentInfo *CreateLink()
{
	StudentInfo *head,*stu,*stud;
	head = 0;
	stud = stu  = new StudentInfo; 
	do
	{
		cout<< "Please enter student information(Enter 0 to exit)\n";
		cout<< "StudentID:\t";
		cin>> stu->StudentID;
		if(stu->StudentID == 0)
			break;
	                 cout<< "StudentName:\t";
	                 cin>> stu->StudentName;
	                 cout<< "ProjectOneGrade:\t";
		cin >>stu->ProjectOneGrade;
		cout<< "ProjectTwoGrade:\t";
		cin>> stu->ProjectTwoGrade;
		cout<< "ProjectThreeGrade:\t";
		cin>>stu->ProjectThreeGrade;
		cout<< "ExamOneGrade:\t";
		cin>> stu->ExamOneGrade;
		cout<< "ExamTwoGrade;\t";
		cin>> stu->ExamTwoGrade;
		if((count++) == 1)
			head = stu;
		else
		{
			stud->next = stu;
			stud = stu;
		}
		
		stu = new StudentInfo;
	}while(1);
	stud->next = 0;
	delete stu;
	return head;
}
void Save(StudentInfo *head)
{
	StudentInfo *stu;
	stu = head;
	ofstream ofile;
	ofile.open(Address,ios::trunc);
	if (! ofile)
		cout<< "open failed\n";
	else
	{
		ofile<< "StudentName\t"<< "POneGrade\t"<< "PTwoGrade\t"<< "PThreeGrade\t"<<"ExOneGrade\t"<<"ExTwoGrade\n";
	    while(stu != 0)
	   {
		   ofile<< stu->StudentName<<"\t\t"<<stu->ProjectOneGrade<<"\t\t"<<stu->ProjectTwoGrade<<"\t\t"<<stu->ProjectThreeGrade<<"\t\t"<<stu->ExamOneGrade<<"\t\t"<<stu->ExamTwoGrade;
		   stu = stu->next;
	   }
		cout<< "Save successfully\n";
		ofile.close();
	}

}
void Load(void)
{
	char disp;
	ifstream ifile(Address);
	if(! ifile)
		cout<< "open failed\n";
	else
	{
		while(! ifile.eof())
		{
		                ifile.get(disp);     
			cout << disp;

		}
		cout<< "Load successfully\n";
		ifile.close();
	}
}
void Delete(StudentInfo *head)
{
	StudentInfo *stu;
	stu = head; 
	while(stu != 0)
	{
		delete stu;
		stu = stu->next;
	}
}
int main(void)
{
	StudentInfo *head;
	head = CreateLink();
	Save(head);
	Load();
	Delete(head);
}

Please point out the error, thank you!
Last edited on
Thanks for all the suggestions, sloppy9's reply made the most sense to me as I'm not too familiar with pointers yet either lol, still really new to C++. I tried creating a for loop to get the grades within the original loop. When I run it, it seems to never reach the end of the file, and just prints random numbers, nothing from the file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

const int NUM_PROJECTS = 6;
const int NUM_EXAMS = 2; 

while(!gradeFile.eof())	
{
for(i = 0; i < SIZE; i++)
{
     gradeFile.getline(student[i].studentName, SIZE, ',');
     gradeFile.ignore(',');
			
     for(j = 0; j < NUM_PROJECTS; j++)
     {
	gradeFile >> student[i].projectGrade[j];
	cout << student[i].projectGrade[j]; 
     }
     for(j = 0; j < NUM_EXAMS; j++)
     {
	gradeFile >> student[i].examGrade[j];
	cout << student[i].examGrade[j]; 
     }
}
}
I'm sorry not to give your help, your reply made ​​me realize that my way some bold, I would change
Haha no worries MrShenYaYa, I appreciate your help all the same! Some of the things you did were a bit over my head for me at this point, but perhaps they won't be in the not too far future :). But this is what I ended up doing with the program:

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
void ProcessTextFile(string& fileName, studentInfo student[])
{ 
int i = 0; 
int j = 0; 
int n = 0; 

if (OpenFile(gradeFile, GRADE_FILE)) 
{
while(!gradeFile.eof())	
{
gradeFile.getline(student[i].studentName, SIZE, ',');
gradeFile.ignore(0, ','); 

     for( j = 0; j < NUM_PROJECTS; j++)
     { 
     gradeFile >> student[i].projectGrade[j];
     gradeFile.ignore(1, ','); 
     }
     for( n = 0; n < NUM_EXAMS; n++)
     {
     gradeFile >> student[i].examGrade[n];
     gradeFile.ignore(1, ' '); 
     }
cout << endl << endl;
i++;

gradeFile.close(); 
}
}     


That first For loop within the While loop was causing the problem, once I removed it and corrected my usage of the ignore fucntion everything worked perfect :)
Last edited on
Topic archived. No new replies allowed.