整理者: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; }
文件夹情况如下:
其中破旧电脑的子文件夹下面还有文件:
此部分给出两种方法。
方法一(修改来自同学刘洋的代码)
用此方法要先将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 继续循环 }
结果如下:
方法二(来自网友茅柳野)
此版本无需改变工程字符集,默认为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; } }
运行结果如下: