程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 字符串分割函數strtok

字符串分割函數strtok

編輯:關於C語言

前天晚上和 xiaofazhen 看程序, 突然間看到他的代碼裡有 strtok 這麼一個函數, 網上查了一下, 居然是用來做字符串分割的;
原來 C 下還是有這函數的, 以前還一直抱怨 C 下沒有字符串分割函數, 很不方便, 看來還是自己孤陋寡聞胃(如果是 C++ 的話, 參照 這裡, 使用 copy+istringstream 來實現); 不多說, 既然看到了, 就要好好學習一下.
以下代碼測試環境為:  Windows7 + Visual Studio 2010
函數原型:
1 char *strtok(
2    char *strToken,
3    const char *strDelimit
4 );

參數說明:
    strToken:   包含 token 的字符串, 即待分割串

    strDelimit: token 的集合, strToken 會根據這裡的每個字符進行分割
 
返回值:
    返回指向第一段被截取出來的字符串的指針(根據 strDelimit 內的字符進行截取). 如果沒有找到, 那麼就返回 NULL.
 
調用說明:
    (1). 第一次調用 strtok 時, 第一個參數是 strToken, 以後再調用時, 第一個參數必須是 NULL;

    (2). 調用 strtok 後, 原字符串會被修改;

    (3). strtok 不是一個線程安全的函數.
 
源代碼分析:
    從 這裡 貼出的 Linux 下的 string.h 的實現可以看出:

    (1). strtok 使用一個全局定義的 char * ___strtok; 來指向截取後的剩余字符串, 所以從第二次開始調用 strtok 後, 第一個參數就只需要設為 NULL 就可以了;

    (2). strtok 函數會在一開始就判斷其第一個參數, 若不為 NULL, 就取其第一個參數進行截取, 並將 ___strtok 指向截取後的字符串; 若為NULL, 則使用 ___strtok 進行截取, 並將 ___strtok 指向截取後的字符串;

    (3). strtok 使用 sbegin 指向待截取的字符串, 當找到 strDelimit 裡的字符時, 就在這個字符前面插入 '\0', 這樣就相當於從 sbegin 指向的字符串裡截取出前面一段了. 而後面一段, 則由 ___strtok 指向, 等待下一次截取.
 
測試代碼:
原始代碼摘自 msdn, 有擴改.
01 // crt_strtok.c
02 // compile with: /W3
03 // In this program, a loop uses strtok
04 // to print all the tokens (separated by commas
05 // or blanks) in the string named "string".
06 //
07 #include <string.h>
08 #include <stdio.h>
09 #include <Windows.h>
10 
11 char string[] = "A string\tof ,,tokens\nand some  more tokens";
12 char seps[]   = " ,\t\n";
13 char chinese[] = "中國,吃飯";
14 char *token;
15 
16 int main( void )
17 {
18     printf( "英文測試:\n" );
19 
20     // Establish string and get the first token:
21     token = strtok( string, seps ); // C4996
22     // Note: strtok is deprecated; consider using strtok_s instead
23     while( token != NULL )
24     {
25         // While there are tokens in "string"
26         printf( " %s\n", token );
27 
28         // Get next token:
29         token = strtok( NULL, seps ); // C4996
30     }
31 
32 
33     printf("原字符串: %s\n", string);   // 結果為 A, 說明原字符串已發生改變
34 
35 
36     printf( "\n中文測試:\n");
37 
38     token = strtok( chinese, ",");
39     while(token != NULL )
40     {
41         printf( "%s\n", token);
42 
43         token = strtok( NULL, ",");
44     }
45 
46     printf("\n");
47     system("pause");
48 
49 }

運行結果:
可以看到, 即使是全中文組成的字符串, 也是能正確分割的; 還要注意的一點是, 調用 strtok 後, 原字符串會被修改.
 
 
 
最後, 百度百科說明在新的 Linux 2.6.29 下, 不再使用 strtok 函數, 而是改為使用更快的 strsep 替代. 但是在 windows 環境下(當前版本 Visual Studio 2010), 並未提供 strsep 函數.
在 這裡 可以看到 strsep 的函數實現, 所以可以自己寫一個 strsep, 然後再調用即可. 在 strtok 函數定義處也可以看到以下說明"WARNING: strtok is deprecated, use strsep instead.".
作者: Sailtseng 
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved