字符串处理算法(五)多线程实现代码行数统计。[风林火山]
实现如下:
//文件类型 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[n]; 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[n] = 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; }
有兴趣的朋友可以自己试试,仅供参考。
转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/12586589