MOOC清华《程序设计基础》第7章:统计在线时长

来源:互联网 发布:java怎么调用外部接口 编辑:程序博客网 时间:2024/05/17 22:08
#include <iostream>#include <fstream>    //包含文件操作的头文件 #include <cstring>    //字符串操作头文件 using namespace std;//added in 3.0, 时间类型的结构定义struct Time_t{int year, month, day;int hour, minute, second;};//added in 3.0, 计算时长的函数声明int TimeDifference(Time_t, Time_t); int main(){//ifstream fin("log.txt");  //ifstream表示input file stream//上面这一行也可以写成如下两行:ifstream fin;fin.open("log.txt"); int user_count = 0;  char ids[600][20];  //记录所有的编号 bool online[600];   //added in 3.0, 记录在线状态Time_t last_on[600];  //added in 3.0, 记录上次登录时间int secs[600];     //added in 3.0, 累计在线秒数 while(!fin.eof())     //eof表示end of file{Time_t t;char tmp, id[20], operation[10];//added in 3.0, 获取文本文件中的一行(结构体版本) fin >> t.year >> tmp >> t.month >> tmp >> t.day;    // 2015/4/21fin >> t.hour >> tmp >> t.minute >> tmp >> t.second;  // 11:16:16fin >> id;    // 40dbae14f777cddfin >> operation;   // LOGINint found = -1;//判断是否是新用户 for(int i = 0; i < user_count; i++)if(strcmp(id, ids[i]) == 0){found = i;break;}//如果是新用户,记录新用户的登录状态,并记录上次登录时间 if(found == -1)  //debug记录:千万不要写掉了一个等号 {strcpy(ids[user_count], id);  //added in 3.0, 记录新用户的登录状态 if(strcmp(operation, "LOGIN") == 0){online[user_count] = true;  //登录状态改为“在线” last_on[user_count] = t;  //记录上次登录时间//特别注意:这里t为结构类型,它与普通类型一样,也是能赋值给一个数组元素的! }elseonline[user_count] = false;user_count++;}//如果不是新用户,修改登录状态,记录在线时长 else{if(strcmp(operation, "LOGIN") == 0)  //如果当前操作是登录操作 {if(!online[found])  //而且当前的状态是不在线 {online[found] = true;  //就把当前状态改为在线 last_on[found] = t;   //并把登录时间记下来 }}else  //否则就是登出操作{if(online[found])  //并且当前状态是在线 {online[found] = false;  //就把当前状态改为不在线 //并调用函数,计算两个时刻之差secs[found] += TimeDifference(last_on[found], t); }} }} fin.close();  //关闭文件//added in 3.0, 输出每一个用户的在线时长for(int i = 0; i < user_count; i++) cout << ids[i] << " " << secs[i] << endl;  return 0; }//added in 3.0, 计算时间差,已知只会出现2015年内的时间//若要计算位于不同年的时刻之间的时间差,则还需考虑int型数据的最大容量,防止溢出 int TimeDifference(Time_t s, Time_t t) {int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int day_count = t.day - s.day;for(int i = s.month; i < t.month; i++)day_count += days[i - 1];  //减1的目的是数组下标与实际的月份数相一致 int result = day_count * 60 * 60 * 24;result += (t.hour - s.hour) * 60 * 60;result += (t.minute - s.minute) * 60;result += (t.second - s.second);return result;}

运行结果:


可以估计出,整个控制台缓冲区并没有500多行,有一些靠前面的输出结果被掐掉了。为解决这个问题,可以把输出结果输出到另一个文件中。

#include <iostream>#include <fstream>    //包含文件操作的头文件 #include <cstring>    //字符串操作头文件 using namespace std;//added in 3.0, 时间类型的结构定义struct Time_t{int year, month, day;int hour, minute, second;};//added in 3.0, 计算时长的函数声明int TimeDifference(Time_t, Time_t); int main(){//ifstream fin("log.txt");  //ifstream表示input file stream//上面这一行也可以写成如下两行:ifstream fin;fin.open("log.txt"); int user_count = 0;  char ids[600][20];  //记录所有的编号 bool online[600];   //added in 3.0, 记录在线状态Time_t last_on[600];  //added in 3.0, 记录上次登录时间int secs[600];     //added in 3.0, 累计在线秒数 while(!fin.eof())     //eof表示end of file{Time_t t;char tmp, id[20], operation[10];//added in 3.0, 获取文本文件中的一行(结构体版本) fin >> t.year >> tmp >> t.month >> tmp >> t.day;    // 2015/4/21fin >> t.hour >> tmp >> t.minute >> tmp >> t.second;  // 11:16:16fin >> id;    // 40dbae14f777cddfin >> operation;   // LOGINint found = -1;//判断是否是新用户 for(int i = 0; i < user_count; i++)if(strcmp(id, ids[i]) == 0){found = i;break;}//如果是新用户,记录新用户的登录状态,并记录上次登录时间 if(found == -1)  //debug记录:千万不要写掉了一个等号 {strcpy(ids[user_count], id);  //added in 3.0, 记录新用户的登录状态 if(strcmp(operation, "LOGIN") == 0){online[user_count] = true;  //登录状态改为“在线” last_on[user_count] = t;  //记录上次登录时间//特别注意:这里t为结构类型,它与普通类型一样,也是能赋值给一个数组元素的! }elseonline[user_count] = false;user_count++;}//如果不是新用户,修改登录状态,记录在线时长 else{if(strcmp(operation, "LOGIN") == 0)  //如果当前操作是登录操作 {if(!online[found])  //而且当前的状态是不在线 {online[found] = true;  //就把当前状态改为在线 last_on[found] = t;   //并把登录时间记下来 }}else  //否则就是登出操作{if(online[found])  //并且当前状态是在线 {online[found] = false;  //就把当前状态改为不在线 //并调用函数,计算两个时刻之差secs[found] += TimeDifference(last_on[found], t); }} }} fin.close();  //关闭文件//added in 3.1, 把每一个用户的在线时长输出到文件ofstream fout;fout.open("times.txt"); for(int i = 0; i < user_count; i++) fout << ids[i] << " " << secs[i] << endl;  fout.close();return 0; }//added in 3.0, 计算时间差,已知只会出现2015年内的时间//若要计算位于不同年的时刻之间的时间差,则还需考虑int型数据的最大容量,防止溢出 int TimeDifference(Time_t s, Time_t t) {int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int day_count = t.day - s.day;for(int i = s.month; i < t.month; i++)day_count += days[i - 1];  //减1的目的是数组下标与实际的月份数相一致 int result = day_count * 60 * 60 * 24;result += (t.hour - s.hour) * 60 * 60;result += (t.minute - s.minute) * 60;result += (t.second - s.second);return result;}

可见控制台窗口已经没有输出了,输出到了exe文件根目录下的文本文件中。


写入文件的核心代码是这几行:

//added in 3.1, 把每一个用户的在线时长输出到文件ofstream fout;fout.open("times.txt"); for(int i = 0; i < user_count; i++) fout << ids[i] << " " << secs[i] << endl;  fout.close();
经测试,文件名不能命名为带路径名的形式,否则无法输出。不过,也许需要包含某个头文件也未可知,以后学到再说吧。

阅读全文
0 0
原创粉丝点击