整理者: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;
}
}
运行结果如下:
浙公网安备 33010602011771号