Student Records - Reading & Displaying from Input

I'm currently writing a program that needs to read a input file and populate a set of Student objects. Then it will display the objects, and perform some basic loop and function-based processing.

How do I read each record in the input file, and dynamically allocate and populate each Student variable so I can display the students' records in a organized format?

Input file:

The data file is named "Students.txt". Copy and paste the content below into a text file. The file has the following format:


10 characters - first name
10 characters - middle name
20 characters - last name
9 characters - Student ID
3 characters - age, in years (3 digits)


(Copy this)
 
John      Daniel    Fuller              E23123456034Malic     Stephen   Browscent           W03023142039Richard   E.        Pollidence          E02782635021Frank     William   Lomo                E09912376022Colin               Frankson            R23234556023James     Theodore  Jackson             D02323245059Dave      Gerald    Mungbean            F12333221042Jim       Waymo     Hilbert             W02785634055Barb      C         Bowie               W02833546030Jim       D         Carlo               S22876543033


struct Student:

Student has the following members:

1
2
3
4
5
6
string - first name
char - middle initial
string - last name
char - campus code
string - Student ID
short int - age


Note the differences between the input file and the format of the Student members.

The student ID field in the input is an example of a coded key. It may look like a 9-character ID, but in reality it contains two distinct fields. The first character is a campus code. The next eight characters are student IDs. The last three characters is the students' age. Note that the 5th student (Colin Frankson) doesn't have a middle initial.

Example: D > (campus code), 02323245 > (student ID), 059 > (age)

Processing the input:

1. Open the input file. Check for successful open. If the open failed, display an error message and return with value 1.

2. Use a properly-structured loop to read the input file until EOF.

3. Use the read function to read each record into a character array large enough to hold the entire record.

4. For each input file record, dynamically allocate and populate a Student variable. Note that to populate some of the Student fields, you'll need to perform some type of conversion. Use a pointer array to manage all the created student variables.

5. Assume that there will not be more than 99 input records, so the size of the student variable pointer array will be 100. Use a "global" variable to define the size of the pointer array. Example: const int SIZE = 100;

Using pointer array:

1. Initialize each element in the array of pointers to nullptr.

2. As you read input records and create new student variables, point the next element in the pointer array at the new student. Later, when you loop through the pointer array to process the student variables, you'll know that there are no more students when you come across a pointer with a null value.

Display the Student objects:

When you hit EOF on the input file, close it, and display the entire list of students. Go through the student objects - do not create the report while you're reading input records. Expected output attached below.

1
2
3
4
5
Last Name	MI	First Name	Campus Code	Student ID	Age
============================================================================
Fuller	        D	John	        E	        12345678        034

Hilbert	        W	Jim	        Q	        98765432	055


My code so far
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
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#ifndef Student_h
#define Student_h

struct Student
{
    string firstName;
    char middleInitial;
    string lastName;
    char campusCode;
    string studentID;
    short int age;
};

#endif

int main()
{
    ifstream inputFile;
    inputFile.open("Students.txt");
        
    if(!inputFile.is_open())
    {
        cout << "File successfully opened!";
        return 1;
    }
    else
    {
        cout << "Failed to open file!";
        exit(1);
    }

        // pseudocode:

        // read the first input record
        // while  (not eof)
        // dynamically allocate space for new student variables
        // populate the student variables from the input 
        // read the next input record
        // end while
        
        // Display the student variables with appropriate column headers and 
        // formatting to make it readable

    return 0;
}
Last edited on
read each record into a character array large enough to hold the entire record


Each record is 52 chars (10 + 10 + 20 + 9 + 3)

So you need a char array of 52 chars.

To read a record of a fixed size, use the .read() function. See http://www.cplusplus.com/reference/istream/istream/read/

So something like:

1
2
3
4
5
const size_t recsz = 52;

for (char record[recsz]; inputFile.read(record, recsz); ) {
  /// Process record
}

Last edited on
One 'simple' way of doing this is to use a union to break a record into its parts - which can then be set into the required Student structure. This gives an 'easy' way of reading and extracting the file data.

Consider:

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
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <charconv>

int main()
{
	union record {
		struct _student {
			char first[10];
			char middle[10];
			char last[20];
			char code;
			char id[8];
			char age[3];
		} student;
		char charrec[sizeof(_student)];
	};

	struct Student {
		std::string first;
		char midinit;
		std::string last;
		char campus;
		std::string id;
		short int age;

		void rtrim(std::string& str)
		{
			const auto s = str.find_last_not_of(' ');
			str.resize(s != std::string::npos ? s + 1: str.size());
		}

		Student(const record& r) : first(std::begin(r.student.first), std::end(r.student.first)),
			last(std::begin(r.student.last), std::end(r.student.last)), midinit(r.student.middle[0]),
		 campus(r.student.code), id(std::begin(r.student.id), std::end(r.student.id)) {
			std::from_chars(std::begin(r.student.age), std::end(r.student.age), age);

			rtrim(first);
			rtrim(last);
		}
	};

	std::ifstream inputFile("students.txt", std::ios::binary);

	if (!inputFile.is_open())
		return (std::cout << "Cannot open students file\n"), 1;

	for (record r; inputFile.read(r.charrec, sizeof(r)); ) {
		Student s(r);

		std::cout << std::left << std::setw(12) << s.first << s.midinit << "  " << std::setw(22) << s.last << s.campus << " " << s.id << " " << s.age << "\n";

		/// Process record
	}
}


which displays:


John        D  Fuller                E 23123456 34
Malic       S  Browscent             W 03023142 39
Richard     E  Pollidence            E 02782635 21
Frank       W  Lomo                  E 09912376 22
Colin          Frankson              R 23234556 23
James       T  Jackson               D 02323245 59
Dave        G  Mungbean              F 12333221 42
Jim         W  Hilbert               W 02785634 55
Barb        C  Bowie                 W 02833546 30
Jim         D  Carlo                 S 22876543 33


Now there's just the pointer bit (why??)

Last edited on
Hello Orion98,

I have been looking at and thinking about the program for awhile. I find that there are several problems.

Lines 6 - 19. This would work great if they were contained in a header file, but not in the only ".cpp" that makes up the program.

The header guard is to prevent the code from being compiled more than once in a program.

Since the struct is in only 1 file it is compiled only once. The header guard, lines 6,7 and 19, have no real use. You can do away with them.

Lines 23 and 24 are fine if you want to keep them, but the more common way is to use
ifstream inputFile("Students.txt"/*, std::ios::binary*/);. This will define the file stream variable and open the file at the same time. Testing both ways with MSVS2017 opening the file in "binary" mode did not seem to make any difference when using the ".read()" function. Although I have always seen the ".read()" function used with a file opened in "binary" mode.

The if/else statement is backwards and wrong. The only way to say that the file opened is if it did not open. Otherwise you will be saying that the file did not open when it actually did.

Also the "return" and "exit()" will not let you past line 35. "exit()" is a C function that you should avoid using in a C++ program. "exit90" is an immediate termination of the program and it does not know about C++ classes or how to clean them up before leaving the program.

The code would work better as:
1
2
3
4
5
6
7
8
9
10
if (!inputFile)
{
    cout << "\n    Failed to open file!";

    return 1;
}
else
{
    cout << "\n     File successfully opened!";
}

The if condition will catch more problems with the file stream than the ".is_open()" function. The "return 1" not only follows the instructions, but will clean up any classes that were created, like the string class.

You will need to correct this before you can read the file and do anything.

The else part is not needed. You could easily say:
1
2
3
4
5
6
7
8
if (!inputFile)
{
    cout << "\n    Failed to open file!";

    return 1;
}

cout << "\n     File successfully opened!";

If you wanted to say that the file did open, but even this is not necessary for the program, but useful in testing.

After I fixed this I added the code:
1
2
3
4
Student* students[SIZE]{ nullptr };
char record[RECSIZE]{};

inputFile.read(record, RECSIZE);

"RECSIZE" is like "SIZE", Defined as a constant variable. constexpr int SIZE{ 100 }, RECSIZE{ 52 };

I have only worked to this point of just reading the file for 1 record. From you will need to break up the variable "record" to store it in the struct. Remember this struct is part of the array and not a separate object.

Something else to keep in mind. The input file has age as 3 characters, but the struct defines as a numerical variable. Numeric variables do not store leading zeros, so when it comes time for output to the screen, or file, you will need to code for the leading zero before you output the short.

Another point: short int age; is fine, but you only need short age;. "short", "long" and "long long" are all considered to be of type "int".

That should be enough to read 1 record. From there you need to decide how you can break up the variable "record" and put the information into the struct in the array. This is based on what you have learned so far, which no one has any idea what that is.

When you do get to the point of using "new" to create the dynamic memory needed DO NOT forget to use "delete" to free the memory created or you will have a memory leak.

Andy
My code so far:
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
#include <iostream>
#include <fstream>
using namespace std;

const int SIZE = 100;

#ifndef Student_h
#define Student_h

struct Student
{
     char first_name[10];
     char middle_int;
     char last_name[20];
     char campus_code;
     char student_ID[8];
     char age[3];
};

#endif

int main()
{
	ifstream inFile;
	inFile.open("Students.txt", ios::binary);

	if(!inFile.fail())
	{
              cout << "Unable to open file!";
              return 1;
	}

	Student s[SIZE];
	int total_st = 0;
	inFile.read(reinterpret_cast<char *> (&s[total_st++]), sizeof (Student));

	while(!inFile.eof())
	{
             // dynamically allocate space for new student variable
	     Student *st = new Student();
             
             // populate the student variables from the input 
             // read the input record
	}

         inputFile.close();         
         
        // Display the student variables with appropriate column headers and 
        // formatting to make it readable
 
        for(int i = 0; i < total_st; i++)
        {
             delete s;
        }

        return 0;
}
Last edited on
Are the arrays in your structures going to be populated with strings, or will they always be used as just arrays of characters?

The sizes of those arrays are not large enough to be used as strings when the input has the maximum number of characters.

You need to verify how the file was written, if the file has end of string terminations you need make sure there is room for that character in the array as well.

@jlb; Can you show me how to do that?
Can I show you how to do what, exactly? And before I can show you anything you will need to answer my questions as well.

If the arrays will be used as C-strings you must increase the size of the arrays to accommodate the end of string character.

Reading a file with the istream.read() function requires you to know exactly how the file was written, and if the file was written in binary mode or text mode. Trying to read a in binary mode if it was written in text mode can be problematic/

You can also view the file with a hex editor/dump program to try to see the structure of the file.

It would also be helpful to know what operating system and compiler you are using as well.


You need to verify how the file was written


The test file is as in the first post. It is a fixed sized 52 byte record file as specified in the format spec in the first post. The record fields are left justified padded with spaces.

struct Student is also defined in the first post. Note that struct Student doesn't map to the fie record layout.

See my previous posts.
Last edited on
1
2
3
4
5
	if(!inFile.fail())
	{
              cout << "Unable to open file!";
              return 1;
	}

In English, this says "if it didn't fail then say 'unable to open file' and return." Does that seem right?

This entire assignment is an exercise in translating the input format to the structure format.

As always, I strongly recommend copying the full assignment into your code as comments. Then you can move the comments around to the places that implement the different parts. This is a great way to ensure that you're doing everything exactly as requested. Below, I copied the assignment to the end of your latest code, turned it into comments and then moved the comments to the places where your code should handle them. I've addd "TODO" to the places where you have work 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
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <iostream>
#include <fstream>
using namespace std;

// 5. Assume that there will not be more than 99 input records, so the
// size of the student variable pointer array will be 100. Use a
// "global" variable to define the size of the pointer array. Example:
// const int SIZE = 100;
const int SIZE = 100;

#ifndef Student_h
#define Student_h

// struct Student:

// Student has the following members:
// string - first name
// char - middle initial
// string - last name
// char - campus code
// string - Student ID
// short int - age

// TODO: max the struct match the requirement
struct Student
{
     char first_name[10];
     char middle_int;
     char last_name[20];
     char campus_code;
     char student_ID[8];
     char age[3];
};

#endif

int main()
{
    // Input file:

    // The data file is named "Students.txt". Copy and paste the content
    // below into a text file.
    ifstream inFile;
    inFile.open("Students.txt", ios::binary);

    // Processing the input:

    // 1. Open the input file. Check for successful open. If the open
    //    failed, display an error message and return with value 1.
    // TODO: Fix this if statement
    if(!inFile.fail())
    {
	cout << "Unable to open file!";
	return 1;
    }

    // Use a pointer array
    // to manage all the created student variables.
    // TODO: change this to a pointer array
    Student s[SIZE];

    // TODO:
    // 1. Initialize each element in the array of pointers to nullptr.

	int total_st = 0;

	// TODO: Get rid of this read statment
	inFile.read(reinterpret_cast<char *> (&s[total_st++]), sizeof (Student));

	// 2. Use a properly-structured loop to read the input file until EOF.

	while(!inFile.eof())
	{
	    // TODO:
	    // 3. Use the read function to read each record into a character array
	    //    large enough to hold the entire record.

	    // 4. For each input file record, dynamically allocate and populate a
	    // Student variable. Note that to populate some of the Student fields,
	    // you'll need to perform some type of conversion.

	    // dynamically allocate space for new student variable
	     Student *st = new Student();
             
	     // 2. As you read input records and create new student variables,
	     // point the next element in the pointer array at the new
	     // student.

	     // TODO: point the next element in the pointer array at the new student.
	     // I think this means you should have a separate Student * variable that points
	     // to the current element in the array.

	     // The file has the following format:

	     // 10 characters - first name
	     // 10 characters - middle name
	     // 20 characters - last name
	     // 9 characters - Student ID
	     // 3 characters - age, in years (3 digits)

	     // TODO: Do this
             // populate the student variables from the input 
             // read the input record

	     // Note the differences between the input file and the format of the Student members.

	     // The student ID field in the input is an example of a coded key. It
	     // may look like a 9-character ID, but in reality it contains two
	     // distinct fields. The first character is a campus code. The next
	     // eight characters are student IDs. The last three characters is the
	     // students' age. Note that the 5th student (Colin Frankson) doesn't
	     // have a middle initial.

	     // Example: D > (campus code), 02323245 > (student ID), 059 > (age)
	}

	// When you hit EOF on the input file, close it
         inputFile.close();         
         
	 // TODO:
	 // ... and display the
	// entire list of students. Go through the student objects - do not
	// create the report while you're reading input records. Expected
	// output attached below.

	 // Later, when you loop through the pointer array to process
	 // the student variables, you'll know that there are no more students
	 // when you come across a pointer with a null value.
        for(int i = 0; i < total_st; i++)
        {
	    // TODO:
	    // Display the Student objects:
	    // Display the student variables with appropriate column headers and 
	    // formatting to make it readable
 


	    // Last Name	MI	First Name	Campus Code	Student ID	Age
	    // ============================================================================
	    // Fuller	        D	John	        E	        12345678        034

	    // Hilbert	        W	Jim	        Q	        98765432	055
             delete s;
        }

        return 0;
}


// (Copy this)

// John      Daniel    Fuller              E23123456034Malic     Stephen   Browscent           W03023142039Richard   E.        Pollidence          E02782635021Frank     William   Lomo                E09912376022Colin               Frankson            R23234556023James     Theodore  Jackson             D02323245059Dave      Gerald    Mungbean            F12333221042Jim       Waymo     Hilbert             W02785634055Barb      C         Bowie               W02833546030Jim       D         Carlo               S22876543033 


A few things pop out immediately:
Lines 25-33: Your structure isn't what's required.
Line 68: You're read is outside the loop. Also you're supposed to read it into a char array. Like I said, the whole point of this assignment is to convert the input format to the structure format. You need to read the record into a char array, and then copy the data from the char array into a Student struct.

Also, note at lines 57 & 58 (from point #4 of the assignment) "Use a pointer array to manage all the created student variables." That means an array of pointers, just like what Handy Andy did:
Student* students[SIZE]{ nullptr };

I hope this helps.
I finally managed to output the student records. This is what I have so far.

main.cpp
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
#include <iostream>
#include <fstream>
#include <iomanip>
#include "Student1.h"
#include "Student2.h"
using namespace std;

const int SIZE = 100;

int main()
{
	ifstream inFile;
	inFile.open("Students.txt", ios::in|ios::binary);

	// Open the input file – if it fails to open, display an error message and terminate
	if(!inFile.is_open())
	{
		cout << "Unable to open file!";
		return 1;
	}
	else
	{
		cout << "File successfully open!\n\n";
	}

	// Use a pointer array to manage all the created student variables.
	Student1 **ptrArr = new Student1 *[SIZE];

	for(int i = 0; i < SIZE; i++)
	{
		ptrArr[i] = nullptr;
	}

	Student1 s;
	int total = 0;
	// read the first input record
	inFile.read(reinterpret_cast<char *> (&s), sizeof(s));

	while(!inFile.eof())
	{
		// dynamically allocate space for new student variable
		ptrArr[total] = new Student1;

		// populate the student variable from the input
		*ptrArr[total] = s;
		total++;

		// read the next input record
		inFile.read(reinterpret_cast<char *> (&s), sizeof(s));
	}

	inFile.close();

	Student2 *st = new Student2[SIZE];
	for(int i = 0; ptrArr[i]; i++)
	{
		for(char fn: ptrArr[i]->first_name)
			st[i].fn += fn;

		st[i].mi = ptrArr[i]->middle_int[0];

		for(char ln: ptrArr[i]->last_name)
			st[i].ln += ln;

		st[i].cc = ptrArr[i]->campus_code;

		for(char sID: ptrArr[i]->student_ID)
			st[i].sID += sID;

		st[i].age = atoi(ptrArr[i]->age);
	}

	cout << "First Name" << setw(9)
		 << "MI" << setw(15)
		 << "Last Name" << setw(17)
		 << "Campus Code" << setw(16)
		 << "Student ID" << setw(15)
		 << "Age" << endl;
	cout << "===================================================================================" << endl;

	for(int j = 0; st[j].age != 0; j++)
	{
		cout << st[j].fn << setw(8);
		cout << st[j].mi << "       ";
		cout << st[j].ln << setw(2);
		cout << st[j].cc << "          ";
		cout << st[j].sID << setw(16);
		cout << st[j].age << " " << endl;
 	}

	for(int x = 0; ptrArr[x]; x++)
	{
		delete [] ptrArr;
		delete [] st;
	}

	return 0;
}


Student1.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef STUDENT1_H_
#define STUDENT1_H_
#include <iostream>
using namespace std;

struct Student1
{
	char first_name[10];
	char middle_int[10];
	char last_name[20];
	char campus_code;
	char student_ID[8];
	char age[3];
};

#endif 


Student2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef STUDENT2_H_
#define STUDENT2_H_
#include <iostream>
#include <string>
using namespace std;

struct Student2
{
	string fn;
	char mi;
	string ln;
	char cc;
	string sID;
	short int age;
};

#endif 


Current Output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
File successfully open!

First Name       MI      Last Name      Campus Code      Student ID            Age
===================================================================================
John             D       Fuller               E          23123456              34 
Malic            S       Browscent            W          03023142              39 
Richard          E       Pollidence           E          02782635              21 
Frank            W       Lomo                 E          09912376              22 
Colin                    Frankson             R          23234556              23 
James            T       Jackson              D          02323245              59 
Dave             G       Mungbean             F          12333221              42 
Jim              W       Hilbert              W          02785634              55 
Barb             C       Bowie                W          02833546              30 
Jim              D       Carlo                S          22876543              33 



Last edited on
You're getting the right output, but you will probably lose points for failing to do this things:

3. Use the read function to read each record into a character array large enough to hold the entire record.


struct Student:
You have Student1 and Student2

4. For each input file record, dynamically allocate and populate a Student variable.
You dynamically allocate your Student1 structs, but for the one that matters, the Student2 struct, you allocate a fixed length array at line 54.

I think the idea of the assignment is that you can reuse the char buffer to read the input records. So the input loop should be something like
1
2
3
4
while (read 52 bytes into a char buffer) {
    allocate a new Student record and add it to the array of pointers
    copy the data from the char buffer into the new student record.
}


General point. Putting using namespace std in an include file is not regarded as good practice. At some point this will cause problems - so it's best to get into the habit of not doing it now.

Why have a seperate .h file for each structure? Is this a requirement? For this exercise using separate .h files is not really justified. The used structures could be part of main.cpp. If you really want to use a .h file, why not put both into one?

1
2
3
4
5
for(int x = 0; ptrArr[x]; x++)
	{
		delete [] ptrArr;
		delete [] st;
	}


This is incorrect. Shouldn't it be:

1
2
3
4
5
for (int x = 0; ptrArr[x]; ++x)
    delete ptrArr[x];

delete [] ptrArr;
delete [] st;


As ptrArr is a pointer to pointer.

Last edited on
Hello Orion98,

I am glad this works for you, but it did not work for me in VS2017. As dhayden has pointed out you did not follow the instructions properly.

I had to make a couple of changes to get it to compile, but it did produce this output;

File successfully open!

First Name       MI      Last Name      Campus Code      Student ID            Age
===================================================================================
John             D       Fuller               E          23123456              34
Malic            S       Browscent            W          03023142              39
Richard          E       Pollidence           E          02782635              21
Frank            W       Lomo                 E          09912376              22
Colin                    Frankson             R          23234556              23
James            T       Jackson              D          02323245              59
Dave             G       Mungbean             F          12333221              42
Jim              W       Hilbert              W          02785634              55
Barb             C       Bowie                W          02833546              30
Jim              D       Carlo                S          22876543              33
       ═        ═                    -12851
       ═        ═                    -12851

The last 2 lines actually printed out 89 lines before a run time error crashed the program. Also the "age " is wrong according to your original example "age" should print as 3 digits not 2. As I told you converting the characters "034" into a numeric variable the leading zeros are dropped. When it comes to the output YOU will need to put the leading zero back.

As seeplus pointed out you could do something like this:

Structs.hpp
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
#ifndef STUDENT1_H_
#define STUDENT1_H_
//#include <iostream>
//using namespace std;
// Worth reading.
// http://www.lonecpluspluscoder.com/2012/09/22/i-dont-want-to-see-another-using-namespace-xxx-in-a-header-file-ever-again/

struct Student1
{
	char first_name[10];
	char middle_int[10];
	char last_name[20];
	char campus_code;
	char student_ID[8];
	char age[3];
};

#endif 

#ifndef STUDENT2_H_
#define STUDENT2_H_
//#include <iostream>
//#include <string>
//using namespace std;

struct Student2
{
	string fn;
	char mi;
	string ln;
	char cc;
	string sID;
	short int age;
};

#endif  

And in the main file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <iomanip>
#include <string>

#include <fstream>

using namespace std;

#include "Student1.h"
#include "Student2.h"
// or #include "Structs.hpp"

const int SIZE = 100;

int main()

By the time you have included the normal header files those that are in double quotes will be covered by everything above.

In "main":
1
2
ifstream inFile;
inFile.open("Students.txt", ios::in | ios::binary);

Line 1 already defines "inFile" as an input file, so in line 2 the "ios::in" is not needed and is ignored.

jlb wrote:
Reading a file with the istream.read() function requires you to know exactly how the file was written, and if the file was written in binary mode or text mode. Trying to read a in binary mode if it was written in text mode can be problematic.


I tried opening the file in text mode and in binary mode using VS2017 and did not see any difference this time.

When you look at the file name "Students.txt" this tends to imply a text file. And when I looked at the file with a HEX editor all the characters in the file are text characters. On my side everything I have seen leads me to believe that the file, "Students.txt", is a text file.

You need to reread the instructions and see if they match the code you have written.

You did make proper use of the include gards with the header files.

Andy
See continuation of this at http://www.cplusplus.com/forum/beginner/272981/

When using .read() as opposed to getline() or >>, the file is usually opened as binary as you normally don't want 'cooked' data but the 'raw' data. In this case it makes no difference.
Last edited on
Topic archived. No new replies allowed.