起因:前段時間寫命令行解析函數(字符串分割比較通用的例子),沒有經過深入思考和分析引起了程序死循環,就想了下是否有對應的系統函數可以使用。經過一番搜索之后發現還是有幾個可用的字符串分割函數,這里整理下,以作總結及后續查詢使用。
當然,如果你覺得自己的字符串處理可以做的很好,可以考慮直接使用字符串查找函數做字符串分割,比如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”。