VC中字符串取子串總結
------------------
一。前言
程序中經常會遇到要處理用某些符號(如空格,或“, ; . | /t”等)分隔的字符串的問題,我在此做了一些總結和比較。
二。處理方法
1. 用MFC CString之Find處理字符串
// 以下方法將一個字符串分解後放到一個CStringArray中:
void ExtractString(CStringArray& arr, const CString strSrc, const CString sep = "/r/n" )
{
// 預處理: 可根據需要決定是否需要Trim,以及是Trim掉空格/還是分隔符/還是其它
CString str(strSrc);
str.TrimLeft();
str.TrimRight();
{
// 預處理: 可根據需要決定是否需要Trim,以及是Trim掉空格/還是分隔符/還是其它
CString str(strSrc);
str.TrimLeft();
str.TrimRight();
if(str.IsEmpty())
return;
return;
// 開始分解
int pos = str.Find(sep);
while (pos != -1)
{
//if(!str.Left(pos).IsEmpty()) // 如有必要也可在此Trim後再判斷是否爲空,爲空則捨棄
arr.Add(str.Left(pos));
int pos = str.Find(sep);
while (pos != -1)
{
//if(!str.Left(pos).IsEmpty()) // 如有必要也可在此Trim後再判斷是否爲空,爲空則捨棄
arr.Add(str.Left(pos));
str = str.Mid(pos + sep.GetLength());
pos = str.Find(sep);
}
pos = str.Find(sep);
}
arr.Add(str); // think
}
// BTW,CString提供了TrimLeft和TrimRight,卻不能一次TrimAll,並返回Trim後的字符串,我寫了一個:
CString TrimAll(CString str, CString strTrim = " ")
{
str.TrimLeft(strTrim);
str.TrimRight(strTrim);
return CString(str);
}
{
str.TrimLeft(strTrim);
str.TrimRight(strTrim);
return CString(str);
}
// 同樣是用Find處理字符串,和以上處理方式稍有不同,試比較:
void ExtractString2(CStringArray& arr, const CString strSrc, const CString sep = "/r/n" )
{
CString str(strSrc);
if(TrimAll(str).IsEmpty())
return;
{
CString str(strSrc);
if(TrimAll(str).IsEmpty())
return;
// 開始分解
int pos = str.Find(sep);
if(pos == -1) // 未找到分隔符
arr.Add(str);
else // 找到分隔符
{
str += sep; // think
int pos = str.Find(sep);
if(pos == -1) // 未找到分隔符
arr.Add(str);
else // 找到分隔符
{
str += sep; // think
CString s;
while (pos != -1)
{
s = str.Left(pos);
if(!TrimAll(s).IsEmpty())
arr.Add(s);
while (pos != -1)
{
s = str.Left(pos);
if(!TrimAll(s).IsEmpty())
arr.Add(s);
str = str.Mid(pos + sep.GetLength());
pos = str.Find(sep);
}
}
}
pos = str.Find(sep);
}
}
}
2. 用MFC未公開函數AfxExtractSubString 處理
// 以下爲函數定義及說明:
// AfxExtractSubString 從一個字符(chSep)分隔的字符串(lpszFullString)中取出第iSubString個子串,輸出到rString
BOOL AFXAPI AfxExtractSubString (
CString& rString, // 用於輸出子串
LPCTSTR lpszFullString, // 被分隔的字符串
int iSubString, // zero-based substring index
TCHAR chSep = '/n' // 分隔符
)
CString& rString, // 用於輸出子串
LPCTSTR lpszFullString, // 被分隔的字符串
int iSubString, // zero-based substring index
TCHAR chSep = '/n' // 分隔符
)
// eg:
CString sDesc= "張三|男|28|醫生";
CString sOccupation;
if(AfxExtractSubString ( sOccupation, sDesc, 3, '|'))
cout << "職業:" << sOccupation << endl;
3. 用C語言之strtok函數處理
#include <assert.h>
#include <assert.h>
void test()
{
char* str = "06317377244|13805871280|20040210105049|193|NBGW1|040C|0017|8";
char seps[] = ",;|";
{
char* str = "06317377244|13805871280|20040210105049|193|NBGW1|040C|0017|8";
char seps[] = ",;|";
char* temp = (char*)malloc(sizeof(char) * (strlen(str)+1));
strcpy(temp, str);
char* token = strtok(temp, seps);
while (NULL != token)
{
printf("%s/t", token);
token = strtok(NULL, seps);
}
strcpy(temp, str);
char* token = strtok(temp, seps);
while (NULL != token)
{
printf("%s/t", token);
token = strtok(NULL, seps);
}
free(temp);
}
}
4. 其它方法
當然既然能用MFC的Find函數進行處理,也可能string的find處理,甚至可用最原始的字符比較,再配合一些字串處理函數進行處理。
但我覺得我提供的使用Find類函數處理字串的2種方法非常常用,可供參考。
三。比較
處理方法
|
優
|
劣
|
用MFC CString之Find處理字符串 | 分隔符可是是字符或字串; 在MFC中是最常用的方法。 |
僅限於MFC中使用 |
用AfxExtractSubString 處理 | 完全封裝,調用簡單; 分隔符可是是字符或字串。 |
僅限於MFC中使用,且未公開; 一般用於取其中某個子串。 |
用C語言之strtok函數處理 | 分隔符可以同時指定多個字符,可用於分隔符不是很確定的情況。 | 分隔符只能是字符; C庫函數,在C兼容開發環境中通用。 |
四。後記
以上只是我從個人的角度做的一個小結(我用MFC/C++多一些),難免有失偏頗,在BCB/Delphi中肯定也有對應的方式方法,不在本文的討論範圍內,這裏就不再贅述。