#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/21
fin >> t.hour >> tmp >> t.minute >> tmp >> t.second; // 11:16:16
fin >> id; // 40dbae14f777cdd
fin >> operation; // LOGIN
int 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为结构类型,它与普通类型一样,也是能赋值给一个数组元素的!
}
else
online[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/21
fin >> t.hour >> tmp >> t.minute >> tmp >> t.second; // 11:16:16
fin >> id; // 40dbae14f777cdd
fin >> operation; // LOGIN
int 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为结构类型,它与普通类型一样,也是能赋值给一个数组元素的!
}
else
online[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();
经测试,文件名不能命名为带路径名的形式,否则无法输出。不过,也许需要包含某个头文件也未可知,以后学到再说吧。