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



    实现如下:

    //文件类型
    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退出
    ");
    			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=='	')) 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=='	')) 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=='	')) 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("搜索失败!
    ");
    		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("
    %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






  • 相关阅读:
    大牛总结的Linux提权Exp合集
    CTF中图片隐藏文件分离方法总结
    解压报错gzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now的解决方法
    CTF中常见Web源码泄露总结
    解决“当前扩展缓存策略没有进行注册”的错误
    【红色警报】XXE 高危漏洞将大面积影响微信支付安全,可能导致系统沦陷,请升级你的系统!
    Senparc.Weixin SDK v5.0 升级公告
    使用 VSTS 进行 CI 的过程中,无法识别 .NET Core 2.x 的情况处理
    .net core DI 注册 Lazy<> 类型
    【备忘】ASP.NET MVC 5 升级到 ASP.NET Core MVC 的部分变化
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3363646.html
Copyright © 2020-2023  润新知