首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言字串分割利器:strtok 函數深度解析與替代方案

     編輯:關於C語言

前言

在 C 語言中處理字串分割一直是初學者的痛點。標準庫提供的 strtok 雖然功能強大,但存在修改原字串、非執行緒安全等特性,使用時需格外小心。本文將詳細解析其原型、行為、原始碼邏輯,並提供測試範例與現代替代方案 strsep。

一、函數原型與參數說明

char *strtok(char *strToken, const char *strDelimit);
參數說明
strToken待分割的字串。首次呼叫傳入字串指標,後續呼叫必須傳入 NULL。
strDelimit分隔符字元集合。字串中任一字元皆視為分隔點。

回傳值: 指向下一個 token 的指標;若無更多 token 則回傳 NULL。

二、三大關鍵使用規則

  1. 首次與後續呼叫不同: 第一次傳入目標字串,之後皆傳 NULL。
  2. 破壞性修改: 函數會在原字串的分隔符位置寫入 '\0',導致原字串被切斷。
  3. 非執行緒安全: 內部使用靜態全域變數 ___strtok 保存狀態,多執行緒環境下會相互干擾。

三、原始碼邏輯深度剖析(Linux glibc 實作)

核心流程如下:

  1. 維護靜態指標 char * ___strtok 指向下次搜尋起始位置。
  2. 若輸入 strToken != NULL,重置搜尋起點為該字串;否則沿用 ___strtok。
  3. 從起始位置掃描,遇到分隔符字元則將其置為 '\0',更新 ___strtok 指向下一字元,回傳 token 起始位址。
  4. 若掃描至字串末尾仍無分隔符,回傳剩餘子串並將 ___strtok 設為 NULL。

這也解釋了為何連續分隔符會被視為單一分隔(空 token 被跳過)。

四、完整測試程式與輸出

#include <string.h>
#include <stdio.h>
#include <Windows.h>

char string[] = "A string\tof ,,tokens\nand some   more tokens";
char seps[]   = " ,\t\n";
char chinese[] = "中國,吃飯";
char *token;

int main(void) {
    printf("英文測試:\n");
    token = strtok(string, seps);
    while (token != NULL) {
        printf(" %s\n", token);
        token = strtok(NULL, seps);
    }
    printf("原字串: %s\n", string); // 輸出 "A",證明原字串已改變

    printf("\n中文測試:\n");
    token = strtok(chinese, ",");
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, ",");
    }
    system("pause");
    return 0;
}

輸出結果:

英文測試:
 A
 string
 of
 tokens
 and
 some
 more
 tokens
原字串: A

中文測試:
中國
吃飯

測試證明:

  • 中文(多位元組字元)同樣可正確分割,因分隔符為單一位元組 ','。
  • 原字串 string 僅剩首字元 "A",其餘被 '\0' 截斷。

五、現代替代方案:strsep

警告: strtok is deprecated, use strsep instead. —— Linux 2.6.29+ 已棄用 strtok。

strtok vs strsep 差異表

特性strtokstrsep
連續分隔符處理合併視為一個(跳過空 token)保留空 token(回傳空字串)
執行緒安全否(靜態變數)是(狀態由呼叫者傳遞)
修改原字串是是
Windows 支援有無(需自行實作)

Windows 環境自行實作 strsep

若在 Visual Studio 等 Windows 環境開發,可參考開源實作(如 BSD 原始碼)自行加入 strsep,或使用 strtok_s(C11 標準,Microsoft 實作為 strtok_s)作為較安全的替代。

六、最佳實踐建議

  1. 若不需保留原字串且單執行緒,strtok 仍可用但需加註解警示。
  2. 新專案優先考慮 strsep(Linux)或 strtok_s(跨平台/C11)。
  3. 若需高效能、零複製分割,考慮手寫解析器或使用第三方庫(如 libcsv、cJSON 等)。
  4. C++ 專案建議直接用 std::stringstream + std::getline 或 Boost.Tokenizer。

總結

strtok 是 C 語言早期的字串分割利器,理解其「破壞性、狀態保持、非執行緒安全」三大特性至關重要。現代開發應逐步遷移至 strsep 或更安全的替代方案,並在跨平台專案中妥善處理相容性問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved