输入文件:
S:SvrID=6, User=200, TimeStamp=2013-5-24 07:30:00, Event=Login
S:SvrID=6, User=100, TimeStamp=2013-5-24 07:59:30, Event=Login
S:SvrID=6, User=100, TimeStamp=2013-5-24 07:59:59, Event=Logout
S:SvrID=4, User=100, TimeStamp=2013-5-24 08:00:00, Event=Login
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:02:30, Url=www.taobao.com, Method=Post, Flow=15
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:03:00, Url=www.taobao.com/shop1234, Method=Get, Flow=200
T:SvrID=6, User=200, TimeStamp=2013-5-24 08:05:00, Url=www.sina.com.cn, Method=Get, Flow=200
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:06:00, Url=www.vmall.com, Method=Post, Flow=20
S:SvrID=6, User=200, TimeStamp=2013-5-24 08:08:34, Event=Logout
T:SvrID=4, TimeStamp=2013-5-24 08:08:00, Url=www.vmall.com/mobile/d2, Method=Get, Flow=500, User=100
T:SvrID=8, User=100, TimeStamp=2013-5-24 08:09:10, Url=www.vmall.com/wideband, Method=Post, Flow=50
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:10:20, Url=www.taobao.com/shop5678, Method=Get, Flow=350
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:12:00, Url=www.tudou.com, Method=Post, Flow=43
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:12:15, Url=www.tudou.com/movie4, Method=Get, Flow=2048
T:SID=4, TimeStamp=2013-5-24 08:15:00, Url=www.taobao.com/item982738729374283424, Method=Get, Flow=20
S:SvrID=4, User=100, TimeStamp=2013-5-24 08:19:59, Event=Logout
T:SvrID=4, User=100, TimeStamp=2013-5-24 08:20:15, Url=www.taobao.com/shop86, Method=Post, Flow=35
输出文件:ID,在线时长,url条数
100,1228,3
www.taobao.com,15,550
www.tudou.com,43,2048
www.vmall.com,20,500
200,2314,1
www.sina.com.cn,0,200
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_LINE_LENTH 10240
#define MAX_URL_ROOT 10240
#define TIME_LOW_LEVEL 20080101000000
#define TIME_HIGH_LEVEL 20201231235959
#define MAX_MESSAGE 100000
/************************************************************************/
/* inFile & outFile 有效性由用例保证,请不要在函数中关闭这2个文件 */
/************************************************************************/
enum messageType {state=1,text};
enum mEventType {login=1, logout};
enum mMethodType {post=1, get};
int userAmount = 0;
int messageCount = 0;
struct urlInfo {
char url[1024];
int post;
int get;
struct urlInfo* next;
};
struct userInfo {
int userID;
int duration;
int urlItems;
struct urlInfo* urlInfoList;
};
struct message {
enum messageType type;
int serverID;
int userID;
char timeStamp[128];
enum mEventType mEvent;
char url[1024];
enum mMethodType mMethod;
int flow;
struct message* next;
};
struct userNode {
struct message* messageHead;
int userID;
int serverID;
enum mEventType mEvent;
struct userNode* nextUserNode;
};
int readLine(FILE** fp, char* line)
{
char c;
int i = 0;
c = fgetc(*fp);
while(c!='\n' && !feof(*fp)){
line[i] = c;
i++;
c = fgetc(*fp);
if( i>=MAX_LINE_LENTH ) {
line[i]='\0';
break;
}
}
return i;
}
bool checkKeyword(struct message* pMessage, char* keyword, char* value)
{
char urlRoot[MAX_URL_ROOT] = {0};
if(0 == _stricmp(keyword, "SvrID")) {
pMessage->serverID = atoi(value);
} else if(0 == _stricmp(keyword, "User")) {
pMessage->userID = atoi(value);
} else if(0 == _stricmp(keyword, "TimeStamp")) {
strncpy_s(pMessage->timeStamp, value, sizeof(pMessage->timeStamp)-1);
pMessage->timeStamp[sizeof(pMessage->timeStamp)-1] = '\0';
} else if(pMessage->type == state) {
if(0 == _stricmp(keyword, "Event")) {
if(0 == _stricmp(value, "Login"))
pMessage->mEvent = login;
else if(0 == _stricmp(value, "Logout"))
pMessage->mEvent = logout;
else
return false;
} else
return false;
} else if(pMessage->type == text) {
if(0 == _stricmp(keyword, "Url")) {
sscanf_s(value, "%[^/]", urlRoot, sizeof(pMessage->url)-1);
strncpy_s(pMessage->url, urlRoot, sizeof(pMessage->url)-1);
pMessage->url[sizeof(pMessage->url)-1] = '\0';
} else if(0 == _stricmp(keyword, "Method")) {
if(0 == _stricmp(value, "Post"))
pMessage->mMethod = post;
else if(0 == _stricmp(value, "Get"))
pMessage->mMethod = get;
else
return false;
} else if(0 == _stricmp(keyword, "Flow")) {
pMessage->flow = atoi(value);
} else
return false;
} else
return false;
return true;
}
bool isLegal(struct message* pMessage)
{
char* urlPoint = NULL;
size_t urlLength = 0;
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
__int64 sum = 0;
if(pMessage->serverID<1 || pMessage->serverID>100)
return false;
if(pMessage->userID<1 || pMessage->userID>10000)
return false;
if(*(pMessage->timeStamp) == NULL) {
return false;
} else {
sscanf_s(pMessage->timeStamp, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);
sum = year*10000000000+month*100000000+day*1000000+hour*10000+minute*100+second;
if(sum<TIME_LOW_LEVEL || sum>TIME_HIGH_LEVEL)
return false;
}
if(pMessage->type == state) {
if(pMessage->mEvent == 0)
return false;
} else if (pMessage->type == text) {
if(*(pMessage->url) == NULL) {
return false;
} else {
urlPoint = pMessage->url;
urlLength = strlen(pMessage->url);
if(urlPoint[0]!='w' || urlPoint[1]!='w' ||urlPoint[2]!='w' || urlPoint[3]!='.')
return false;
/*
else {
urlPoint = urlPoint + urlLength - strlen(".com.cn");
if (urlPoint[0]!='.' || urlPoint[1]!='c' ||urlPoint[2]!='o' || urlPoint[3]!='m'||
urlPoint[4]!='.' ||urlPoint[5]!='c' || urlPoint[6]!='n') {
urlPoint = pMessage->url;
urlPoint = urlPoint + urlLength - strlen(".com");
if(urlPoint[0]!='.' || urlPoint[1]!='c' ||urlPoint[2]!='o' || urlPoint[3]!='m')
return false;
}
}*/
}
if(pMessage->mMethod == 0)
return false;
if(pMessage->flow <= 0)
return false;
} else
return false;
return true;
}
struct message* parseLine(char* line)
{
char* pToken = NULL;
char* pNext = NULL;
struct message* pMessage = NULL;
char keyword[128] = {0};
pMessage = (struct message*) malloc(sizeof(struct message));
if(pMessage == NULL)
return NULL;
memset(pMessage, 0, sizeof(struct message));
pToken = strtok_s(line, ":", &pNext);
if(0 == _stricmp(pToken, "s")) {
pMessage->type = state;
} else if (0 == _stricmp(pToken, "t")) {
pMessage->type = text;
} else {
goto parse_error;
}
while((pToken=strtok_s( NULL, ",", &pNext)) != NULL) {
while(pToken[0] == ' ') {
pToken++;
}
sscanf_s(pToken, "%[^=]", keyword, 128) ;
keyword[sizeof(keyword)-1] = '\0';
pToken = pToken+strlen(keyword)+1;
if(pToken!=NULL)
checkKeyword(pMessage, keyword, pToken);
memset(keyword, 0, sizeof(keyword));
}
if(!isLegal(pMessage))
goto parse_error;
return pMessage;
parse_error:
free(pMessage);
return NULL;
}
void addToMessageList(struct message* messageHead, struct message* pMessage) { struct message* messagePoint = NULL; struct message* lastPoint = NULL; messagePoint = messageHead->next; //lastPoint = messageHead; while(messagePoint->next != NULL) { /* if(strcmp(pMessage->url,messagePoint->url) >= 0) { lastPoint->next = pMessage; pMessage->next = messagePoint; return; } else { lastPoint = messagePoint; messagePoint = messagePoint->next; } */ messagePoint = messagePoint->next; } messagePoint->next = pMessage; }
void addToUserList(struct userNode* userNodeHead, struct message* pMessage)
{
struct userNode* userPoint = NULL;
struct userNode* lastUserPoint = NULL;
userPoint = userNodeHead->nextUserNode;
lastUserPoint = userNodeHead;
while(userPoint != NULL) {
if(userPoint->userID == pMessage->userID) {
if((pMessage->type==text) && ((userPoint->serverID!=pMessage->serverID) || (userPoint->mEvent!=login))) {
free(pMessage);
return;
}
if(userPoint->messageHead == NULL) {
userPoint->messageHead = (struct message*) malloc(sizeof(struct message));
if(!userPoint->messageHead)
return;
memset(userPoint->messageHead, 0, sizeof(struct message));
userPoint->messageHead->next = pMessage;
if(pMessage->type == state)
userPoint->mEvent = pMessage->mEvent;
} else {
addToMessageList(userPoint->messageHead, pMessage);
if(pMessage->type == state) {
userPoint->mEvent = pMessage->mEvent;
if(pMessage->mEvent == login) {
userPoint->serverID = pMessage->serverID;
}
}
}
return;
} else if (pMessage->userID > userPoint->userID) {
lastUserPoint = userPoint;
userPoint = userPoint->nextUserNode;
} else if (pMessage->userID < userPoint->userID) {
break;
}
}
lastUserPoint->nextUserNode = (struct userNode*)malloc(sizeof(struct userNode));
if(!lastUserPoint->nextUserNode)
return;
memset(lastUserPoint->nextUserNode, 0, sizeof(struct userNode));
lastUserPoint->nextUserNode->userID = pMessage->userID;
if(pMessage->type == state) {
lastUserPoint->nextUserNode->mEvent = pMessage->mEvent;
if(pMessage->mEvent == login) {
lastUserPoint->nextUserNode->serverID = pMessage->serverID;
}
}
lastUserPoint->nextUserNode->userID = pMessage->userID;
lastUserPoint->nextUserNode->messageHead = (struct message*) malloc(sizeof(struct message));
if(!lastUserPoint->nextUserNode->messageHead)
return;
memset(lastUserPoint->nextUserNode->messageHead, 0, sizeof(struct message));
lastUserPoint->nextUserNode->messageHead->next = pMessage;
lastUserPoint->nextUserNode->nextUserNode = userPoint;
userAmount++;
}
void releaseMessageList(struct message* messageHead)
{
struct message* messagePoint = NULL;
struct message* lastMessagePoint = NULL;
lastMessagePoint = messageHead;
messagePoint = messageHead->next;
while(messagePoint != NULL) {
free(lastMessagePoint);
lastMessagePoint = messagePoint;
messagePoint = messagePoint->next;
}
}
void releaseUserList(struct userNode* userNodeHead)
{
struct userNode* userPoint = NULL;
struct userNode* lastUserPoint = NULL;
lastUserPoint = userNodeHead;
userPoint = userNodeHead->nextUserNode;
while(userPoint != NULL) {
if(lastUserPoint->messageHead!=NULL)
releaseMessageList(lastUserPoint->messageHead);
free(lastUserPoint);
lastUserPoint = userPoint;
userPoint = userPoint->nextUserNode;
}
}
int convertDuration(char* loginTime, char* logoutTime)
{
int loginYear = 0, loginMonth = 0, loginDay = 0, loginHour = 0, loginMinute = 0, loginSecond = 0;
int logoutYear = 0, logoutMonth = 0, logoutDay = 0, logoutHour = 0, logoutMinute = 0, logoutSecond = 0;
int duration = 0;
sscanf_s(loginTime, "%d-%d-%d %d:%d:%d", &loginYear, &loginMonth, &loginDay, &loginHour, &loginMinute, &loginSecond);
sscanf_s(logoutTime, "%d-%d-%d %d:%d:%d", &logoutYear, &logoutMonth, &logoutDay, &logoutHour, &logoutMinute, &logoutSecond);
//TO DO
duration = (logoutYear-loginYear)*365*24*60*60 + (logoutMonth-loginMonth)*30*24*60*60 + (logoutDay-loginDay)*24*60*60 + (logoutHour-loginHour)*60*60 + (logoutMinute-loginMinute)*60 + (logoutSecond-loginSecond);
return duration;
}
int calculateDuration(struct message* messageHead)
{
struct message* messagePoint = NULL;
int duration = 0;
int userState = 0;
char loginTime[64] = {0};
char logoutTime[64] = {0};
messagePoint = messageHead->next;
while(messagePoint != NULL) {
if(messagePoint->type==state && messagePoint->mEvent == login) {
memset(loginTime, 0, sizeof(loginTime));
strncpy_s(loginTime, messagePoint->timeStamp, sizeof(loginTime)-1);
loginTime[sizeof(loginTime)-1] = '\0';
userState++;
} else if(messagePoint->type==state && messagePoint->mEvent == logout) {
memset(logoutTime, 0, sizeof(logoutTime));
strncpy_s(logoutTime, messagePoint->timeStamp, sizeof(logoutTime)-1);
logoutTime[sizeof(logoutTime)-1] = '\0';
if(userState == 1) {
duration += convertDuration(loginTime, logoutTime);
}
userState = 0;
}
messagePoint = messagePoint->next;
}
return duration;
}
int calculateUrlItems(struct urlInfo* urlInfoHead)
{
struct urlInfo* urlInfoPoint;
int urlItems = 0;
urlInfoPoint = urlInfoHead;
while(urlInfoPoint!=NULL) {
urlInfoPoint = urlInfoPoint->next;
urlItems++;
}
/* reduce headPoint */
urlItems--;
return urlItems;
}
void addToUrlInfoList(struct urlInfo* urlInfoHead, struct message* messagePoint)
{
struct urlInfo* urlInfoPoint = NULL;
struct urlInfo* lastUrlInfoPoint = NULL;
urlInfoPoint = urlInfoHead->next;
lastUrlInfoPoint = urlInfoHead;
while(urlInfoPoint != NULL) {
if(_stricmp(urlInfoPoint->url, messagePoint->url) == 0) {
if(messagePoint->mMethod == post) {
urlInfoPoint->post += messagePoint->flow;
} else if(messagePoint->mMethod == get) {
urlInfoPoint->get += messagePoint->flow;
}
return;
} else if(_stricmp(urlInfoPoint->url, messagePoint->url) < 0) {
lastUrlInfoPoint = urlInfoPoint;
urlInfoPoint = urlInfoPoint->next;
} else if(_stricmp(urlInfoPoint->url, messagePoint->url) > 0) {
break;
}
}
lastUrlInfoPoint->next = (struct urlInfo*) malloc(sizeof(struct urlInfo));
if(!lastUrlInfoPoint->next)
return;
memset(lastUrlInfoPoint->next, 0, sizeof(struct urlInfo));
strncpy_s(lastUrlInfoPoint->next->url, messagePoint->url, sizeof(lastUrlInfoPoint->next->url)-1);
lastUrlInfoPoint->next->url[sizeof(lastUrlInfoPoint->next->url)-1] = '\0';
if(messagePoint->mMethod == post) {
lastUrlInfoPoint->next->post = messagePoint->flow;
} else if(messagePoint->mMethod == get) {
lastUrlInfoPoint->next->get = messagePoint->flow;
}
lastUrlInfoPoint->next->next = urlInfoPoint;
}
struct urlInfo* calculateUrlInfoList(struct message* messageHead)
{
struct urlInfo* urlInfoHead = NULL;
struct message* messagePoint = NULL;
messagePoint = messageHead->next;
urlInfoHead = (struct urlInfo*) malloc(sizeof(struct urlInfo));
if(!urlInfoHead)
return NULL;
memset(urlInfoHead, 0, sizeof(struct urlInfo));
while(messagePoint != NULL) {
if(messagePoint->type == text) {
addToUrlInfoList(urlInfoHead, messagePoint);
}
messagePoint = messagePoint->next;
}
return urlInfoHead;
}
void releaseUrlInfoList(struct urlInfo* urlInfoList)
{
struct urlInfo* urlInfoPoint = NULL;
struct urlInfo* lastUrlInfoPoint = NULL;
lastUrlInfoPoint = urlInfoList;
urlInfoPoint = urlInfoList->next;
while(urlInfoPoint != NULL){
free(lastUrlInfoPoint);
lastUrlInfoPoint = urlInfoPoint;
urlInfoPoint = urlInfoPoint->next;
}
}
void releaseUserInfo(struct userInfo* userInfoArray)
{
int i = 0;
while(i<userAmount) {
if(userInfoArray[i].urlInfoList != NULL)
releaseUrlInfoList(userInfoArray[i].urlInfoList);
i++;
}
free(userInfoArray);
}
void writeListToFile(struct urlInfo* urlInfoList, FILE* outFile)
{
struct urlInfo* urlInfoPoint;
urlInfoPoint = urlInfoList->next;
while(urlInfoPoint != NULL) {
fprintf(outFile,"%s,%d,%d\n", urlInfoPoint->url, urlInfoPoint->post, urlInfoPoint->get);
urlInfoPoint = urlInfoPoint->next;
}
}
void writeFile(struct userInfo* userInfoArray, FILE * outFile)
{
int i = 0;
while(i<userAmount) {
fprintf(outFile,"%d,%d,%d\n", userInfoArray[i].userID, userInfoArray[i].duration, userInfoArray[i].urlItems);
writeListToFile(userInfoArray[i].urlInfoList, outFile);
i++;
}
//fputc(EOF, outFile);
}
void calculate(struct userNode* userNodeHead, FILE * outFile)
{
int i = 0;
struct userNode* userPoint = NULL;
struct userInfo* userInfoArray = (struct userInfo*) malloc(sizeof(struct userInfo)*userAmount);
if(!userInfoArray)
return;
memset(userInfoArray, 0, sizeof(struct userInfo)*userAmount);
userPoint = userNodeHead->nextUserNode;
while(i<userAmount) {
userInfoArray[i].userID = userPoint->userID;
userInfoArray[i].duration = calculateDuration(userPoint->messageHead);
userInfoArray[i].urlInfoList = calculateUrlInfoList(userPoint->messageHead);
userInfoArray[i].urlItems = calculateUrlItems(userInfoArray[i].urlInfoList);
userPoint = userPoint->nextUserNode;
i++;
}
writeFile(userInfoArray, outFile);
if( userInfoArray!= NULL)
releaseUserInfo(userInfoArray);
}
统计函数的入口:
void staticNetworkFlow(FILE * inFile, FILE * outFile)
{
char* line = NULL;
int lineLength = 0;
struct userNode* userNodeHead = NULL;
struct userNode* userListPoint = NULL;
struct message* pMessage = NULL;
userAmount = 0;
messageCount = 0;
while(!feof(inFile)) {
line = (char*) malloc(sizeof(char)*MAX_LINE_LENTH);
if(!line)
return;
memset(line, 0, sizeof(char)*MAX_LINE_LENTH);
lineLength = readLine(&inFile, line);
if(0 != lineLength) {
pMessage = parseLine(line);
if(pMessage != NULL) {
if(userNodeHead == NULL) {
userNodeHead = (struct userNode*)malloc(sizeof(struct userNode));
if(!userNodeHead)
return;
memset(userNodeHead, 0, sizeof(struct userNode));
userNodeHead->userID = 0;
userNodeHead->nextUserNode = (struct userNode*)malloc(sizeof(struct userNode));
if(!userNodeHead->nextUserNode)
return;
memset(userNodeHead->nextUserNode, 0, sizeof(struct userNode));
userNodeHead->nextUserNode->userID = pMessage->userID;
if(pMessage->type == state) {
userNodeHead->nextUserNode->mEvent = pMessage->mEvent;
if(pMessage->mEvent == login) {
userNodeHead->nextUserNode->serverID = pMessage->serverID;
}
}
userAmount++;
}
addToUserList(userNodeHead, pMessage);
}
messageCount++;
}
free(line);
if(messageCount >= MAX_MESSAGE)
break;
}
calculate(userNodeHead, outFile);
if(userNodeHead)
releaseUserList(userNodeHead);
return;
}
2013年5月27日上传