Is there any way to read from file containing student records but delimited by different characters? My text is as below:
125 {John_BROWN_Biology} {100_81}
245 {Amanda_SMITH_Chemistry} {83_74}
436 {Michael_CLARK_Calculus} {35_48}
I have to store the in separate arrays so that I can calculate their average and put in ascending order. I have written the code in C++ in this way:
int rank;
char st_info[SIZE];
int grades[SIZE];
bool success1 = false;
bool success2 = false;
bool success3 = false;
ifstream inFile;
inFile.open("records.txt");
string line;
int i=0, j=0;
while (!inFile.getline(rank, 30, '{').eof){
inFile.getline(st_info, SIZE, '_');
inFile.getline(words_array, SIZE, '_');
}
while (!success1)
{
getline(inFile,Line,'{'); // get values for info array
stringstream iss1;
iss1 << Line; //Put the string into a stream
iss1 >> rank; //To send data as an int.
cout << "STUDENT NUMBER:" << rank << " ";
while (!success2){
// for the info in {} part
getline(inFile,Line,'_');
stringstream iss;
iss << Line;
iss >> st_info[i];
cout <<"STUDENT INFO:" << st_info[i] << " ";
i++;
if (getline(inFile,Line,'}')){
stringstream iss2;
iss2 << Line;
iss2 >> st_info[i];
cout << st_info[i] << " ";
i=0;
success2 = true;
}
}
getline(inFile,Line,'{');
stringstream iss3;
iss3 << Line;
iss3 >> grades[j];
cout << "GRADES: "<< grades[i] << " ";
j++;
while (!success3){
getline(inFile,Line,'_');
stringstream iss4;
iss4 << Line;
iss4 >> grades[j];
cout << grades[i] << " ";
j++;
if (getline(inFile,Line,'}')){
stringstream iss5;
iss5 << Line;
iss5 >> grades[j];
cout << grades[i] << " ";
j=0;
success3 = true;
}
}
}
However, as an output I am getting:
1 J 100
2 A 100
4 M 100
Tried to fix, but it get worse. Anybody who can help? Thanks in advance.
There are several issues with your approach and your code:
istream::getline()
can't read integers. It can only read into an array of char array. eof
is a function and not a property<<
>>
to parse data with stringstream
is not optimal. >>st_info[i]
you extract a single char from the stringstream, that will overwrite existing information. I propose you therefore to use the following skeleton, that reads the file line by line, and parses each line separately using a stringstream. Note that I only use the non-member variant of getline()
to read strings instead of arrays of char (this frees me from thinking of buffer overflows):
...
char delim;
int rank;
string names, grades;
string line;
while (getline(inFile, line)) // read line by line
{
stringstream sst{line}; // then parse the line using a string stream
sst>>rank; // read an integer
sst>>delim; // skip white and read a single char
if (delim!='{') {
cout<<"Error on line: { expected for name instead of "<<delim<<endl;
continue; // next line, please !!
}
getline(sst,names, '}'); // TO DO: error handling
sst>>delim;
if (delim!='{') {
cout<<"Error on line: { expected for grades instead of "<<delim<<endl;
continue; // next line, please !!
}
getline(sst,grades, '}'); // TO DO: additional error handling
cout << rank<<" "<<names<<" "<<grades<<endl; // temporary:
// TO DO: parse names and grades by using further stringstreams
}
Note that I used a simple parsing approach: read a char and check it matches the expected opening character, and use getline()
to read until the closing character (the latter being consumed but excluded from the string). This doesn't allow for nested {...}
in your format.