Arrays and vectors really aren’t very different.
1 2 3 4
|
// instead of:
std::vector <Student> students;
|
// use:
constexpr int MAX_STUDENTS = 100;
Student students[ MAX_STUDENTS ];
int num_students = 0; |
1 2
|
// instead of:
students.push_back( student );
|
// use:
students[ num_students++ ] = student; |
The trick is that you cannot directly edit stuff in a file (unless that file is a fixed-length record, which yours is not).
So you need to read the entire file into an array (or vector, or any kind of list).
Then make the modifications to your array.
Then write the array back to file.
I admit I am not familiar with Vietnamese naming conventions. Is Nguyen usable as a given name?
In any case, the list of student names seem to totally ignore the header line, and have two or three words each. Complicating that is that the Vietnamese names seem to (mostly?) listed in traditional family-middle-first name order, while Western names are listed in the traditional first-family order.
This is
really hard to parse into something like first/last name. Typically, software systems will list family name(s) first, followed by a comma, then given name(s) in first-middle order:
Pence, Mike
Tran, Van A (I’m presuming Van is her first name)
This removes ambiguities (the important ones, anyway) and makes parsing
much simpler. For example, I can unambiguously list:
Hernandez Herrerra de Seville, Nayeli Rosa
From that I can get her primary surname (Hernandez) but also the complete one, and also her first given name (Nayeli).
For your input file, all I can say is that I know where the name begins (after the Student ID) and where it ends (before the word "Male" or "Female").
So, yeah, names are much more complicated than people realize...
So if you want to keep it simple, just stick to ONE family name and ONE given name in the student list:
No Student ID Last name First name Gender DoB
1 18127221 Nguyen Tuan Male 4/11/2000
2 18127222 Tran Van Female 9/6/2000
3 18127223 Le Ngoc Female 8/1/2000
4 18127224 Trump Donald Male 12/5/2000
5 18127225 Pence Mike Male 21/4/2000
6 18127226 Nguyen Phuc Male 2/9/2000
7 18127227 Nguyen Trong Male 12/12/2000
8 18127228 Pham Minh Male 13/3/2000
9 18127229 Vu Dam Male 3/2/2000
10 18127230 To Lam Male 4/6/2000 |
If you can do that, it makes parsing into family name and given name much easier.
Remember that
std::getline() reads an
entire line. But you have multiple things on a line. So...
Use getline() to read the entire record, then repack it into an
istringstream, and
then use the
>>
operator to get the pieces:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
Student read_student( std::istream& in )
{
// First, get the WHOLE line
std::string s;
getline( in, s );
// Next, repack it into a stringstream
std::istringstream ss( s );
// Now get the parts
Student student;
ss
>> student.no
>> student.id
>> student.last_name
>> student.first_name
>> student.gender
>> student.dob;
return student;
}
|
If you cannot fix the input file format, though, you will have to do extra work:
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
|
Student read_student( std::istream& in )
{
// First, get the WHOLE line
std::string s;
getline( in, s );
// Next, repack it into a stringstream
std::istringstream ss( s );
// Now get the parts
Student student;
// (first the listing number and the Student ID)
ss
>> student.no
>> student.id;
// (the Name ends when we find the Gender)
ss >> student.name;
while (ss)
{
ss >> s;
if ((s == "Male") || (s == "Female")) break;
student.name += " " + s;
}
student.gender = s;
// (after Gender is just DOB)
ss >> dob;
return student;
}
|
Fortunately,
writing a Student to file is really, really easy.
Hope this helps.