- Consider that we have a text file
"last.txt, which is the output generated by
running the command "last -w" on lilina.
- For each record, we are only interested in the login name and
duration between login/logout, so we define a class
CLogin
:
class CLogin {
public:
string name;
int minute;
CLogin(string s, int m): name(s), minute(m) {}
CLogin(string s, string m): name(s) {
// minute = stoi(m.substr(0,2))*60 + stoi(m.substr(3,2));
// g++ on lilina is too old, otherwise you should have stoi().
minute = atoi(m.substr(0,2).c_str())*60 + atoi(m.substr(3,2).c_str());
}
friend ostream& operator<<(ostream& output, const CLogin& a) {
output << a.name << ' ' << a.minute;
return output;
}
};
- Assume that we have a function
getLogin()
which reads data from a text file and returns a vector of CLogin objects.
Each CLogin object consists of two data members: a login name and the minutes of the login session.
vector<CLogin> getLogin(const char* fn = "last.txt") {
ifstream infile(fn);
string line;
vector<CLogin> logins;
while (getline(infile, line)) {
string name;
string duration;
int nStart, nLength;
name = line.substr(0, line.find(" "));
nStart = line.find("(")+1;
nLength = line.find(")") - nStart;
duration = line.substr(nStart, nLength);
#ifdef _DEBUG
cout << name << duration << endl;
#endif
logins.push_back( CLogin(name, duration) );
}
return logins;
};
- You may test
getLogin()
with the following main program:
int main()
{
vector<CLogin> logins = getLogin();
for (size_t i=0; i<logins.size(); ++i) {
cout << logins[i] << endl;
}
return 0;
}
- The output may look like:
solomon 44
s109321059 8
s109321059 7
s109321059 0
s110321005 12
solomon 30
solomon 20
klim 8
s108321022 251
s108321022 5
- The above output is not good, because the same user has several login records. We want to aggregate them into a single record. Now you are requested to develop a
loginCount()
function, which will return a vector of CCount.
CCount is similar to CLogin, but
the second data member, which is
an integer, will store the login counts instead of durations.
class CCount {
public:
string name;
int count;
CCount(string s, int c=0): name(s), count(c) {}
friend ostream& operator<<(ostream& output, const CCount& a) {
output << a.name << ' ' << a.count;
return output;
}
};
- This vector will be shorter than the previous one, because each user
will only have a corresponding record.
- To generate a new vector which accumulates the occurrence of each user,
you may check whether a login name exists in the vector or not.
- If it already exists, simply increment the corresponding count by 1.
- If not, append a new entry with this name, and initialize the count as 1.
- You may test your
loginCount()
with the following main program:
vector<CLogin> loginCount(vector<CLogin>& logins);
int main()
{
vector<CLogin> logins = getLogin("/home/solomon/CPP/last.txt");
vector<CCount> counts = loginCount(logins);
for (size_t i=0; i<counts.size(); ++i) {
cout << counts[i] << endl;
}
return 0;
}
- The output may look like:
solomon 133
s109321059 27
s110321005 36
klim 20
s108321022 36
s110321529 21
s110321063 77
s107321058 60
s109321020 15
s110321071 12