Hiya. I am attempting to read some data from a text file into an array. I noticed that I can not do it the traditional way as the names are of different lengths and not all the students have all their marks. I want to be able to read the data but I am unsure as to whether it is possible to do so. Any help would be much appreciated.
1 2 3 4 5 6 7 8
struct SStudent
{
int number;
string name;
int mark1 = 0;
int mark2 = 0;
int mark3 = 0;
}
Students marks file:
1 John Higgins
2 Jack Michael Cullen 12 13 15
3 James Morley 41 56 76
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cctype>
usingnamespace std;
struct SStudent
{
int number {};
string name;
int mark[3] {-1,-1,-1}; // -1 means no mark
};
ostream& operator<<(ostream& out, const SStudent& s)
{
return out << s.number << '\n'
<< s.name << '\n'
<< s.mark[0] << ' ' << s.mark[1] << ' ' << s.mark[2] << '\n';
}
int main()
{
// For testing (in actual program: ifstream in("filename"))
istringstream in
{
"1 John Higgins\n""2 Jack Michael Cullen 12 13 15\n""3 James Morley 41 56 76\n"
};
vector<SStudent> studs;
for (string line; getline(in, line); )
{
istringstream sin(line);
SStudent s;
sin >> s.number >> ws; // ws skips whitespace
// Read chars until end-of-line or a digit.
for (char ch; sin.get(ch) && !isdigit(ch); ) s.name += ch;
if (sin) sin.unget(); // if it read a digit, put it back
// Remove extra space(s) from end of name
while (!s.name.empty() && isspace(s.name.back())) s.name.pop_back();
sin >> s.mark[0] >> s.mark[1] >> s.mark[2];
studs.push_back(s);
}
for (constauto& s: studs) cout << s << '\n';
}
An alternative take is to use a vector<int> for the marks so that any number of marks can be present and assume that name can be absent and try to read marks and treat as a name if extraction isn't a number. Consider:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct SStudent
{
int number {};
std::string name;
std::vector<int> marks;
};
std::ostream& operator<<(std::ostream& out, const SStudent& s)
{
out << s.number << '\n' << s.name << '\n';
for (constauto& m : s.marks)
out << m << ' ';
return out;
}
std::istream& operator>>(std::istream& in, SStudent& s)
{
s.name.clear();
s.marks.clear();
std::string line;
if (std::getline(in, line)) {
std::istringstream iss (line);
if (iss >> s.number)
while (iss) {
for (int m; iss >> m; s.marks.push_back(m));
if (!iss.eof()) {
std::string na;
iss.clear();
iss >> na;
if (!s.name.empty())
s.name += ' ';
s.name += na;
}
}
}
return in;
}
int main()
{
// For testing (in actual program: ifstream in("filename"))
std::istringstream in
{
"1 John Higgins\n""2 Jack Michael Cullen 12 13 15\n""3 James Morley 41 56 76\n"
};
std::vector<SStudent> studs;
for (SStudent s; in >> s; studs.push_back(s));
for (constauto& s : studs)
std::cout << s << "\n\n";
}
1
John Higgins
2
Jack Michael Cullen
12 13 15
3
James Morley
41 56 76