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


实现如下:

 

//文件类型

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






 

你可能感兴趣的:(字符串处理)