您的位置:首页 > 编程语言

字符串处理算法(五)多线程实现代码行数统计。[风林火山]

2013-10-11 16:00 701 查看
实现如下:

//文件类型
enum E_FILETYPE
{
E_C,
E_JAVA
};

//文件行数信息
struct T_CodeFileMsg
{
int nTaskId;				//任务Id
string FileName;			//文件名称
E_FILETYPE eFiletype;		//文件类型
int nTotalLine;				//总行数
int nEmptyLine;				//空行数
int nCodeLine;				//代码行数
int nNoteLine;				//注释行数
T_CodeFileMsg()
{
nTotalLine = 0;
nEmptyLine = 0;
nCodeLine = 0;
nNoteLine = 0;
}
};

#define	MAX_WORKTHREAD		5		//线程最大数
#define	MAX_LEN				1024	//路径最大长度
#define MAX_CHAR			1024	//一行最大字符数


//线程函数
DWORD WINAPI ReadFileThread(LPVOID lpParam);
DWORD WINAPI WorkThread(LPVOID lpParam);

//线程句柄
DWORD g_dwReadFileThreadID;
DWORD g_dwTaskThread;
DWORD g_dwWorkThread[MAX_WORKTHREAD];

//事件句柄
HANDLE g_EventReadFileHandle;
HANDLE g_EventReadFinishHandle;

//临界区
CRITICAL_SECTION g_cs;
CRITICAL_SECTION g_MsgQueue;
CRITICAL_SECTION g_task;
CRITICAL_SECTION g_MsgMap;

//数据
map<int, int>m_task;
std::deque<int> m_MsgQueue;
std::deque<int> m_FileQueue;//任务队列
std::map<int, T_CodeFileMsg*> m_FileMsgMap;//处理文件与文件行数信息

int WorkThreadCout = 0;
int nTotalTaskCount =0;
int nWorkTaslCount=0;
int nTaskBeginTime;
int nReadFileFinish=0;
int nInitCount= 0;
int nWorkFlag = 0;
bool bRunFlag = TRUE;
char g_workPath[MAX_LEN];

bool bReadFileFlag=TRUE;

int g_nTaskId=0;

int main()
{
int i;
cout << "#####代码行数统计测试开始#####" <<endl;

cout << "Main thread is running." << endl;

//初始化临界区
InitializeCriticalSection(&g_cs);
InitializeCriticalSection(&g_MsgQueue);
InitializeCriticalSection(&g_MsgMap);

g_EventReadFileHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);
g_EventReadFinishHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);

//创建线程
HANDLE hRFTHandle = CreateThread(NULL, 0, ReadFileThread, NULL, 0, &g_dwReadFileThreadID);

HANDLE hWTHandle[MAX_WORKTHREAD];

for (i=0; i<MAX_WORKTHREAD; i++)
{
int* nTemp = new int;//如果不new,最后打印出来的WorkThread(LPVOID lpParam)的都是10
//nTemp = &i;和*nTemp = i;区别。
*nTemp = i;
hWTHandle[i] = CreateThread(NULL, 0, WorkThread, nTemp, 0, &g_dwWorkThread[i]);
WorkThreadCout ++;
m_task[i] = 0;
Sleep(100);
}

while (TRUE)
{

if (nWorkFlag == 0)
{
printf("输入要统计文件的路径或end退出\n");
scanf("%s", g_workPath);

DeleteMap();
g_nTaskId = 0;
nWorkTaslCount = 0;

if (strcmp(g_workPath, "end") == 0)
{
bReadFileFlag = FALSE;//读文件线程标志
SetEvent(g_EventReadFileHandle);//读事件
bRunFlag = FALSE;//让线程退出
break;
}

SetEvent(g_EventReadFileHandle);//读事件

nWorkFlag = 1;
}

ResetEvent(g_EventReadFinishHandle);
WaitForSingleObject(g_EventReadFinishHandle, INFINITE);

if (nReadFileFinish == 1)
{
PrintMsg();
}
}

Sleep(3000);

DeleteMap();

CloseHandle(hRFTHandle);
for (i=0; i<MAX_WORKTHREAD; i++)
{
CloseHandle(hWTHandle[i]);
}

CloseHandle(g_EventReadFileHandle);
CloseHandle(g_EventReadFinishHandle);

DeleteCriticalSection(&g_cs);
DeleteCriticalSection(&g_MsgQueue);
DeleteCriticalSection(&g_MsgMap);

cout << "Main thread is end." << endl;

cout << "#####代码行数统计测试结束#####" <<endl;
//system("pause");
return 0;
}

int InitData()
{
return 0;
}

int DeleteMap()
{
std::map<int, T_CodeFileMsg*>::iterator IterFile;
for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++)
{
T_CodeFileMsg* file = (*IterFile).second;

delete file;
file = NULL;
}

m_FileMsgMap.clear();

return 0;
}

DWORD WINAPI ReadFileThread(LPVOID lpParam)
{
// cout << "No." << g_dwThreadID << " thread is running." << endl;
while (bRunFlag)
{
EnterCriticalSection(&g_cs);
cout << "ReadFileThread " << g_dwReadFileThreadID << " thread is running." << endl;
LeaveCriticalSection(&g_cs);

ResetEvent(g_EventReadFileHandle);
WaitForSingleObject(g_EventReadFileHandle, INFINITE);
if (bReadFileFlag)
{
int nTemp = DirectoryList(g_workPath);//nReadFileFinish
nReadFileFinish = nTemp;
if (nTemp == 1)
{
PrintFile();
nWorkFlag = 0;
nTotalTaskCount = g_nTaskId;
}
else
{
nWorkFlag = 0;
}

SetEvent(g_EventReadFinishHandle);
}

Sleep(1000);
}

cout << "ReadFileThread " << g_dwReadFileThreadID << " end" << endl;

return 0;
}

DWORD WINAPI WorkThread(LPVOID lpParam)
{
// cout << "No." << g_dwThreadID << " thread is running." << endl;

int* nRemp = (int*)lpParam;
while (bRunFlag)
{
int n = -1;
T_CodeFileMsg* pCFMsg=NULL;

EnterCriticalSection(&g_cs);
//cout << "No " << *nRemp << ", " << g_dwWorkThread[*nRemp] << " thread is running." << endl;
LeaveCriticalSection(&g_cs);

EnterCriticalSection(&g_MsgQueue);
if (!m_FileQueue.empty())
{
n = m_FileQueue.front();
m_FileQueue.pop_front();
if (nWorkTaslCount == 0)
{
nTaskBeginTime = GetTickCount();
}
nWorkTaslCount++;

m_task[*nRemp]++;
}

LeaveCriticalSection(&g_MsgQueue);

EnterCriticalSection(&g_MsgMap);
if ( n>= 0)//没有这个,在开始的时候n=-1会造成溢出。
pCFMsg = m_FileMsgMap
;
LeaveCriticalSection(&g_MsgMap);

EnterCriticalSection(&g_cs);
//cout << "No:" << *nRemp << ", " << n << endl;
if (pCFMsg!=NULL)
{
cout << pCFMsg->FileName.c_str() << endl;
}
LeaveCriticalSection(&g_cs);

if (pCFMsg!=NULL && n>=0)
{
ProcessFile(pCFMsg, n);
Sleep(20);
}
else
Sleep(2000);
}

delete nRemp;
nRemp = NULL;

cout << "No " << lpParam << " end" << endl;

return 0;
}

//根据文件类型处理
int ProcessFile(T_CodeFileMsg* pTCFMsg, int n)
{
EnterCriticalSection(&g_MsgMap);
string tempFile = pTCFMsg->FileName;
E_FILETYPE c_type = pTCFMsg->eFiletype;
LeaveCriticalSection(&g_MsgMap);

switch(c_type)
{
case E_C:
ProcessCFile(pTCFMsg, tempFile.c_str(), n);
break;
case E_JAVA:
ProcessJavaFile(pTCFMsg, tempFile.c_str(), n);
break;
default:
break;
}

return 0;
}

int ProcessCFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n)
{
ifstream in;
char buf[MAX_CHAR] = {0};
bool bNoteFlag = FALSE;
int nNoteLine = 0;
int nEmptyLine = 0;
int nCodeLine = 0;
int nTotalLine = 0;

in.open(strFile);
while(in.getline(buf, sizeof(buf)))
{
nTotalLine++;
char* p = buf;
while((*p ==' ' || *p=='\t')) p++;

if (!bNoteFlag)
{
if (*p == 0)
{
nEmptyLine++;
cout << nTotalLine <<endl;

}
else if (strncmp(p, "/*", 2)==0)
{
char* q = buf+strlen(buf)-1;
while((*q ==' ' || *q=='\t')) q--;

q--;

//判断是不是/*AAA*/
if (strncmp(q, "*/", 2)==0)
{
}
else
bNoteFlag = TRUE;

nNoteLine++;
cout << nTotalLine <<endl;
}
else if (strncmp(p, "//", 2)==0)
{
nNoteLine++;
cout << nTotalLine <<endl;
}
else
{
nCodeLine++;
}
}
else
{
if (*p == 0)
{
nNoteLine++;
cout << nTotalLine <<endl;
}
else if (strncmp(p, "*/", 2)==0)
{
bNoteFlag = FALSE;
nNoteLine++;
cout << nTotalLine <<endl;
}
else
{
nNoteLine++;
cout << nTotalLine <<endl;

char* q = buf+strlen(buf)-1;
while((*q ==' ' || *q=='\t')) q--;

q--;

if (strncmp(q, "*/", 2)==0)
{
bNoteFlag = FALSE;
}
}
}

memset(buf, 0, MAX_CHAR);
}

EnterCriticalSection(&g_MsgMap);
pTCFMsg->nCodeLine = nCodeLine;
pTCFMsg->nEmptyLine = nEmptyLine;
pTCFMsg->nNoteLine = nNoteLine;
pTCFMsg->nTotalLine = nTotalLine;
m_FileMsgMap
= pTCFMsg;
LeaveCriticalSection(&g_MsgMap);

return 0;
}

int ProcessJavaFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n)
{
return 0;
}

int AddFile2Map(char* pFile)
{
string strFile = strlwr(pFile);

int nRet = strFile.find(".", 0);

if (nRet>0)
{
string Temp;
int nLen = strFile.size();
Temp = strFile.substr(nRet, strFile.size()-nRet);

if (strcmp(Temp.c_str(),".c")==0 || strcmp(Temp.c_str(),".cpp")==0 || strcmp(Temp.c_str(),".h")==0)
{
T_CodeFileMsg* pTemp = new T_CodeFileMsg;
m_FileMsgMap[g_nTaskId] = pTemp;

//m_FileMsgMap[g_nTaskId] = new T_CodeFileMsg;
//T_CodeFileMsg* pTemp = m_FileMsgMap[g_nTaskId];
pTemp->eFiletype = E_C;
pTemp->nTaskId = g_nTaskId;
pTemp->FileName = pFile;
//pTemp->FileName = new char[nLen+1];
//memcpy(pTemp->FileName, strFile.c_str(), nLen);

//m_FileMsgMap[g_nTaskId] = pTemp;
//m_FileMsgMap.insert(pair <int, T_CodeFileMsg* >(g_nTaskId, pTemp));
m_FileQueue.push_back(g_nTaskId);
g_nTaskId++;
}

}
return 0;
}

int DirectoryList(LPCSTR Path)
{
WIN32_FIND_DATA FindData;
HANDLE hError;
int FileCount = 0;
char FilePathName[MAX_LEN];
// 构造路径
char FullPathName[MAX_LEN];
strcpy(FilePathName, Path);
strcat(FilePathName, "\\*.*");
hError = FindFirstFile(FilePathName, &FindData);
if (hError == INVALID_HANDLE_VALUE)
{
printf("搜索失败!\n");
return 0;
}

while(::FindNextFile(hError, &FindData))
{
// 过虑.和..
if (strcmp(FindData.cFileName, ".") == 0
|| strcmp(FindData.cFileName, "..") == 0 )
{
continue;
}

// 构造完整路径
wsprintf(FullPathName, "%s\\%s", Path,FindData.cFileName);
FileCount++;

AddFile2Map(FullPathName);

// 输出本级的文件
//printf("\n%d  %s  ", FileCount, FullPathName);

if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//printf("<Dir>");
DirectoryList(FullPathName);
}
}

return 1;

}

int PrintFile()
{
EnterCriticalSection(&g_MsgMap);
std::map<int, T_CodeFileMsg*>::iterator IterFile;
for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++)
{
T_CodeFileMsg* file = (*IterFile).second;

//EnterCriticalSection(&g_cs);
cout << endl;
cout << file->FileName.c_str();
cout << ", id:" << file->nTaskId;
cout << ", nCodeLine:"<< file->nCodeLine;
cout << ", nEmptyLine:"<< file->nEmptyLine;
cout << ", nNoteLine:"<< file->nNoteLine;
cout << ", nTotalLine:"<< file->nTotalLine;
//LeaveCriticalSection(&g_cs);

}
LeaveCriticalSection(&g_MsgMap);

return 0;
}

int PrintMsg()
{
while (TRUE)
{
if (nWorkTaslCount == nTotalTaskCount)
{
std::map<int, int>::iterator IterCount;
for(IterCount=m_task.begin(); IterCount!=m_task.end();IterCount++)
{
int nThreadId= (*IterCount).first;
int nCount = (*IterCount).second;

EnterCriticalSection(&g_cs);
cout << "nThreadId:" << nThreadId << ", nCount:" << nCount<<endl;
LeaveCriticalSection(&g_cs);

(*IterCount).second = 0;
}

nWorkFlag = 0;

PrintFile();

break;
}

cout << "nWorkTaslCount:" << nWorkTaslCount << ", nTotalTaskCount:" << nTotalTaskCount <<endl;

Sleep(1000);
}

return 0;
}


有兴趣的朋友可以自己试试,仅供参考。

转载请注明原创链接:/article/1385453.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐