整理者:finallyliuyu
NLP研究者或者開發人員如果選用C++語言作為開發工具。那麼首先需要克服兩個難題。
第一個難題是:學會在C++中使用Regex。鑒於C++本身並不支援Regex,所以我們需要藉助第三方庫boost.中的regex子庫。網路上有很多關於boost的安裝方法,比如有的方法介紹如何部分安裝boost庫,我這裡也整理了一個如何完整安裝boost庫的方法:《C++安裝boost》這個我實驗過,上面的方法是可行的。但是安裝boost庫之前,需要安裝python26。
第二個難題是:寬窄字串轉換問題,這個問題目前我只是整理了部分解決方案。日後有新的總結會增加進來。此篇博文給出針對第二個難題的一些知識整理。以下博文將分為兩個部分:第一個部分講解:利用boost正則庫進行字串處理的時候需要進行的字串轉換;第二個部分講解:遍曆路徑中含有漢字的檔案夾時的路徑字串轉換問題。
第一部分:利用boost正則庫進行字串處理的時候需要進行的字串轉換
如果字串中含有漢字,應該使用的Regex類型為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);}//elseif(((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; } }
運行結果如下: