起因:前段時間寫命令行解析函數(字符串分割比較通用的例子),沒有經過深入思考和分析引起了程序死循環,就想了下是否有對應的系統函數可以使用。經過一番搜索之后發現還是有幾個可用的字符串分割函數,這里整理下,以作總結及后續查詢使用。
當然,如果你覺得自己的字符串處理可以做的很好,可以考慮直接使用字符串查找函數做字符串分割,比如c中的字符串查找函數、CString字符查找函數、string字符查找函數等,更原始點可以直接操作內存。
windows下有以下幾種可用的字符串分割方法。
CString::Tokenize()
用法如下。
// 按照token分割source字符串,結果通過cout輸出
// 使用MFC的CString::Tokenize
void SplitUseTokenize(const char * source, char token)
{
CString strSource = source;
CString strToken(token);
int pos = 0;
while (-1 != pos)
{
CString strCur = strSource.Tokenize(strToken, pos);
if (!strCur.IsEmpty())
{
cout << strCur << endl;
}
}
cout << endl << endl;
}
Tokenize函數將分割好的字串放到返回值中,同時將對應的掃描位置放到第二個參數中,如果第二個參數返回-1,表示分割完成。
AfxExtractSubString()函數
// 按照token分割source字符串,結果通過cout輸出
// 使用MFC中的AfxExtractSubString函數
void SplitUseExtract(const char * source, char token)
{
int pos = 0;
CString strCur = "";
while(AfxExtractSubString(strCur, source, pos, token))
{
++pos;
cout << strCur << endl;
}
cout << endl << endl;
}
AfxExtractSubString函數返回值表示是否提取子串成功,還有幾個重載函數,可以參考msdn上的說明。
提取得到子串放到第一個參數中。
c語言的strtok()函數
// 按照token分割source字符串,結果通過cout輸出
// 使用crt的strtok函數
void SplitUseStrtok(char * source, char token)
{
char * ptr = strtok(source, &token);
while(NULL != ptr)
{
cout << ptr << endl;
ptr = strtok(NULL, &token);
}
}
strtok函數不是線程安全的,不是可重入的,需要線程安全的函數,建議使用strtok_r函數。具體用法可參考c語言用戶手冊。
這里需要說明的是:
CString::Tokenize()中的PCXSTR pszTokens為分隔字符的組合,可為多個字符。
AfxExtractSubString()中的分隔字符,只能是一個字符。
另外有一點要注意:
CString::Tokenize()碰到連續多個分隔字符是作為一個處理的,AfxExtractSubString()中多個分隔符可區分處理。
strtok/strtok_r函數的處理邏輯跟CString::Tokenize()類似。
如果使用下面測試程序,輸出如下:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 並在失敗時顯示錯誤
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改錯誤代碼以符合您的需要
_tprintf(_T("錯誤: MFC 初始化失敗\n"));
nRetCode = 1;
}
else
{
// TODO: 在此處為應用程序的行為編寫代碼。
char source[] = "123\n\n456\n789";
char token = '\n';
SplitUseTokenize(source, token);
SplitUseExtract(source, token);
SplitUseStrtok(source, token);
system("pause");
}
return nRetCode;
}

這個輸出也說明了本文中提及的注意事項問題。
注:本文涉及所有代碼可使用Git直接下載:https://git.oschina.net/Tocy/SampleCode.git。實際代碼位於Console目錄下,名稱為“20150709_StringSplit.cpp”。
