整理者:finallyliuyu

    NLP研究者或者开发人员如果选用C++语言作为开发工具。那么首先需要克服两个难题。

    第一个难题是:学会在C++中使用正则表达式。鉴于C++本身并不支持正则表达式,所以我们需要借助第三方库boost.中的regex子库。网络上有很多关于boost的安装方法,比如有的方法介绍如何部分安装boost库,我这里也整理了一个如何完全安装boost库的方法:《C++安装boost》这个我试验过,上面的方法是可行的。但是安装boost库之前,需要安装python26

    第二个难题是:宽窄字符串转换问题,这个问题目前我只是整理了部分解决方案。日后有新的总结会增加进来。此篇博文给出针对第二个难题的一些知识整理。以下博文将分为两个部分:第一个部分讲解:利用boost正则库进行字符串处理的时候需要进行的字符串转换;第二个部分讲解:遍历路径中含有汉字的文件夹时的路径字符串转换问题。

第一部分:利用boost正则库进行字符串处理的时候需要进行的字符串转换

如果字符串中含有汉字,应该使用的正则表达式类型为boost::wregex;

还要将字符串从string转换为wstring

string->wstring:的大概思路是将string用c_str()转换成c格式的字符串,然后将char 型的字符串转化成 wchar_t型的字符串,然后wchart_t的字符串转化成wstring

string->wstring代码如下:

************************************************************************/
/*  功能:将窄字符转化成宽字符,string->wstring                         */
/************************************************************************/
wstring myMultibyteToWideChar(string sResult)
{
	int iWLen=MultiByteToWideChar( CP_ACP, 0, sResult.c_str(), sResult.size(), 0, 0 );// 计算转换后宽字符串的长度。(不包含字符串结束符)
	wchar_t *lpwsz= new wchar_t [iWLen+1];
	MultiByteToWideChar( CP_ACP, 0, sResult.c_str(), sResult.size(), lpwsz, iWLen ); // 正式转换。
	lpwsz[iWLen] = L'\0'; 
	wstring wsResult(lpwsz);
	delete []lpwsz;
	return wsResult;
}

函数中调用了windows.h中的函数MultiByteToWideChar函数将char型字符串转化成wchar_t型的字符串。

为了让经过正则处理后的字符串在控制台正常显示,还有将wstring->string

代码如下(代码中也用到了windows.h中的函数):

/************************************************************************/
/* 将宽字符串转化成窄字符串用于输出                                     */
/************************************************************************/
string myWideCharToMultibyte(wstring wsResult)
{	string sResult;
	int iLen= WideCharToMultiByte( CP_ACP, NULL, wsResult.c_str(), -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
	char *lpsz= new char[iLen];
	WideCharToMultiByte( CP_OEMCP, NULL, wsResult.c_str(), -1, lpsz, iLen, NULL, FALSE); // 正式转换。
	sResult.assign( lpsz, iLen-1 ); // 对string对象进行赋值。
	delete []lpsz;
	return sResult;




}

第二部分:

遍历路径中含有汉字的文件夹时的路径字符串转换问题。

首先给出测试代码:

int _tmain(int argc, _TCHAR* argv[])
{
 	int end;
		
	FindFile("E:\\旧电脑");
   cout<<"finish"<<endl;
	
	cin>>end;


}
 
 
 
 
 
 
 
 
 
 
 
文件夹情况如下:
QQ截图未命名 
 
其中破旧电脑的子文件夹下面还有文件:
QQ截图未命名 

此部分给出两种方法。

方法一(修改来自同学刘洋的代码)

用此方法要先将VS2008项目属性设置为Multibyte。显示的字符串将会出现乱码

void FindFile(char * filePath)
{  
	WIN32_FIND_DATA  FileData;   //这两个是系统参数,hFile是句柄 ,FileData是一些标志
	HANDLE   hFile; 
	char dir[1000];
	memset(dir,0,1000);
	sprintf_s(dir,1000,"%s%s",filePath,"\\*.*");
	hFile=FindFirstFile(dir,&FileData);
	
	if (hFile == INVALID_HANDLE_VALUE) //FindFirstFile()如果没找到进行这一步
	{
		printf ("%s\n", "没有找到文件");
		return ;
	} 
	bool bFinish=false;
	while(!bFinish)
	{	
		   char *temp= FileData.cFileName;//这个就是FindFirstFile()返回的文件的名字
			if((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)&&strcmp(temp,".")&&strcmp(temp,"..") )//判断返回的东西是不是目录或者"." "..",因为一个目录下都有"." ,".."两个文件夹
			{
				char  dirassist[3000];
				memset(dirassist,0,3000);
				sprintf_s(dirassist,3000,"%s%s%s",filePath,"\\",temp);
				FindFile(dirassist);
			


			}
			//	else
			if(((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0))//判断是不是ClassList.txt这个文件
			{
				cout<<FileData.cFileName<<endl;
			
			}

			bFinish = (FindNextFile(hFile, &FileData) == false);//看目录下还有没有文件,有的话bFinish=flase 继续循环
	}
 
结果如下:

LDSBSYZW`(~0IK(9U2KYIDR

 
方法二(来自网友茅柳野)
此版本无需改变工程字符集,默认为unicode即可
/************************************************************************/
/* 遍历文件夹                                                                     */
/************************************************************************/
 void FindFile(wchar_t *pFilePath) {
	 WIN32_FIND_DATA FindFileData;
	 HANDLE hFind = INVALID_HANDLE_VALUE;
	 wchar_t  DirSpec[MAX_PATH + 1];// 指定路径 
	 DWORD dwError;
	 wcsncpy (DirSpec, pFilePath, wcslen(pFilePath) + 1);
	 wcsncat (DirSpec, L"\\\*", 3);
	 hFind = FindFirstFile(DirSpec, &FindFileData);
	 if (hFind == INVALID_HANDLE_VALUE) {
		 wprintf(L"Invalid file handle. Error is %u ", GetLastError());
		 return ;
	 } 
	 else if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
		 {
			 wchar_t temp[3000];
			 memset(temp,0,3000*sizeof(wchar_t));
		    wprintf_s(temp,L"%s\\%s\n",pFilePath,FindFileData.cFileName);
			int iLen= WideCharToMultiByte( CP_ACP, NULL, temp, -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
			char *lpsz= new char[iLen];
			WideCharToMultiByte( CP_OEMCP, NULL, temp, -1, lpsz, iLen, NULL, FALSE); // 正式转换。
			cout<<lpsz<<endl;
			delete []lpsz;
	     } 
	 else if(FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
		 && wcscmp(FindFileData.cFileName, L".") != 0
		 && wcscmp(FindFileData.cFileName, L"..") != 0) 
			{   //找到目录
			 wchar_t Dir[MAX_PATH + 1];
			 wcscpy(Dir, pFilePath);
			 wcsncat(Dir, L"\\", 2);
			 wcscat(Dir, FindFileData.cFileName);

			 FindFile(Dir);
			 }

		while (FindNextFile(hFind, &FindFileData) != 0) 
		{
		 if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) 
		 {   //找到文件
			 //fwprintf(fp, L"%s\\", pFilePath);
			 //fwprintf(fp, L"%s\n", FindFileData.cFileName);
			 wchar_t temp[3000];
			 memset(temp,0,3000*sizeof(wchar_t));
			 wcscpy(temp,pFilePath);
			 wcscat(temp,FindFileData.cFileName);
			
			 int iLen= WideCharToMultiByte( CP_ACP, NULL, temp, -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
			 char *lpsz= new char[iLen];
			 WideCharToMultiByte( CP_OEMCP, NULL, temp, -1, lpsz, iLen, NULL, FALSE); // 正式转换。
			 cout<<lpsz<<endl;
			 delete []lpsz;
			 
		 } 
		 else if(FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
			 && wcscmp(FindFileData.cFileName, L".") != 0
			 && wcscmp(FindFileData.cFileName, L"..") != 0) 
		 { //找到目录
				 wchar_t Dir[MAX_PATH + 1];
				 wcscpy(Dir, pFilePath);
				 wcsncat(Dir, L"\\", 2);
				 wcscat(Dir, FindFileData.cFileName);
				 FindFile(Dir);
		 }
	 }

	 dwError = GetLastError();
	 FindClose(hFind);
	 if (dwError != ERROR_NO_MORE_FILES)
	 {
		 wprintf (L"FindNextFile error. Error is %u ", dwError);
		 return;
	 }
 }
 
运行结果如下:

%2S7~}Y1ZPP`_Y3AOLF0IE1

posted on 2010-09-18 15:45  finallyly  阅读(3685)  评论(0编辑  收藏  举报