名稱空間
變體
操作

strtok, strtok_s

來自 cppreference.com
< c‎ | string‎ | byte
定義於標頭檔案 <string.h>
(1)
char* strtok( char* str, const char* delim );
(直到 C99)
char* strtok( char* restrict str, const char* restrict delim );
(C99 起)
char* strtok_s( char* restrict str, rsize_t* restrict strmax,
                const char* restrict delim, char** restrict ptr );
(2) (C11 起)

標記化一個以空字元結尾的位元組字串。

1)strtok 的一系列呼叫會將 str 所指向的字串分解為一系列標記,每個標記都由 delim 所指向的字串中的一個字元定界。序列中的每次呼叫都有一個搜尋目標
  • 如果 str 非空,則該呼叫是序列中的首次呼叫。搜尋目標是 str 所指向的以空字元結尾的位元組字串。
  • 如果 str 為空,則該呼叫是序列中的後續呼叫之一。搜尋目標由序列中的上一次呼叫決定。
序列中的每次呼叫都會在搜尋目標中查詢第一個包含在 delim 所指向的分隔符字串中的字元,分隔符字串可以在每次呼叫中不同。
  • 如果未找到此類字元,則搜尋目標中沒有標記。序列中下一次呼叫的搜尋目標保持不變。[1]
  • 如果找到此類字元,則它是當前標記的開始。然後 strtok 從該位置開始查詢第一個包含在分隔符字串中的字元。
    • 如果未找到此類字元,則當前標記延伸到搜尋目標的末尾。序列中下一次呼叫的搜尋目標是一個空字串。[2]
    • 如果找到此類字元,則它將被空字元覆蓋,該空字元終止當前標記。序列中下一次呼叫的搜尋目標從下一個字元開始。
如果 strdelim 不是指向以空字元結尾的位元組字串的指標,則行為未定義。
2)(1) 相同,但有以下不同之處
  • 在每次呼叫中,將 str 中剩餘的字元數寫入 *strmax,並將標記器的內部狀態寫入 *ptr
  • 序列中的後續呼叫必須傳入具有上一次呼叫儲存的值的 strmaxptr
  • 以下錯誤會在執行時檢測到,並呼叫當前安裝的約束處理函式,而不將任何內容儲存到 ptr 所指向的物件中
    • strmaxdelimptr 為空指標。
    • 對於序列中的後續呼叫,*ptr 為空指標。
    • *strmax 大於 RSIZE_MAX
    • 找到的標記末尾未出現在搜尋目標的前 *s1max 個字元內。
如果 str 指向的字元陣列缺少空字元,且 strmax 指向的值大於該字元陣列的大小,則行為未定義。
與所有邊界檢查函式一樣,只有當實現定義了 __STDC_LIB_EXT1__ 並且使用者在包含 <string.h> 之前將 __STDC_WANT_LIB_EXT1__ 定義為整數常量 1 時,才保證 strtok_s 可用。
  1. 在後續呼叫中仍可使用不同的分隔符字串形成標記。
  2. 在後續呼叫中不能再形成更多標記。

目錄

[編輯] 引數

str - 指向要標記化的以空字元結尾的位元組字串的指標
delim - 指向標識分隔符的以空字元結尾的位元組字串的指標
strmax - 指向最初儲存 str 大小的物件的指標:strtok_s 儲存剩餘要檢查的字元數
ptr - 指向 char* 型別物件的指標,strtok_s 用它來儲存其內部狀態

[編輯] 返回值

1) 返回指向下一個標記的第一個字元的指標,如果沒有標記則返回空指標。
2) 返回指向下一個標記的第一個字元的指標,如果沒有標記或存在執行時約束違規則返回空指標。

[編輯] 注意

此函式具有破壞性:它在字串 str 的元素中寫入 '\0' 字元。特別是,字串字面量不能用作 strtok 的第一個引數。

每次呼叫 strtok 都會修改一個靜態變數:它不是執行緒安全的。

與大多數其他標記器不同,strtok 中的分隔符對於每個後續標記可以不同,甚至可以取決於前一個標記的內容。

strtok_s 函式與 POSIX strtok_r 函式的不同之處在於,它透過防止在被標記化的字串外部儲存來防止溢位,並檢查執行時約束。Microsoft CRT strtok_s 簽名與此 POSIX strtok_r 定義匹配,而不是 C11 strtok_s

[編輯] 示例

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    char input[] = "A bird came down the walk";
    printf("Parsing the input string '%s'\n", input);
    char* token = strtok(input, " ");
    while (token)
    {
        puts(token);
        token = strtok(NULL, " ");
    }
 
    printf("Contents of the input string now: '");
    for (size_t n = 0; n < sizeof input; ++n)
        input[n] ? putchar(input[n]) : fputs("\\0", stdout);
    puts("'");
 
#ifdef __STDC_LIB_EXT1__
    char str[] = "A bird came down the walk";
    rsize_t strmax = sizeof str;
    const char* delim = " ";
    char* next_token;
    printf("Parsing the input string '%s'\n", str);
    token = strtok_s(str, &strmax, delim, &next_token);
    while (token)
    {
        puts(token);
        token = strtok_s(NULL, &strmax, delim, &next_token);
    }
 
    printf("Contents of the input string now: '");
    for (size_t n = 0; n < sizeof str; ++n)
        str[n] ? putchar(str[n]) : fputs("\\0", stdout);
    puts("'");
#endif
}

可能的輸出

Parsing the input string 'A bird came down the walk'
A
bird
came
down
the
walk
Contents of the input string now: 'A\0bird\0came\0down\0the\0walk\0'
Parsing the input string 'A bird came down the walk'
A
bird
came
down
the
walk
Contents of the input string now: 'A\0bird\0came\0down\0the\0walk\0'

[編輯] 參考資料

  • C23 標準 (ISO/IEC 9899:2024)
  • 7.24.5.8 strtok 函式 (p: TBD)
  • K.3.7.3.1 strtok_s 函式 (p: TBD)
  • C17 標準 (ISO/IEC 9899:2018)
  • 7.24.5.8 strtok 函式 (p: TBD)
  • K.3.7.3.1 strtok_s 函式 (p: TBD)
  • C11 標準 (ISO/IEC 9899:2011)
  • 7.24.5.8 strtok 函式 (p: 369-370)
  • K.3.7.3.1 strtok_s 函式 (p: 620-621)
  • C99 標準 (ISO/IEC 9899:1999)
  • 7.21.5.8 strtok 函式 (p: 332-333)
  • C89/C90 標準 (ISO/IEC 9899:1990)
  • 4.11.5.8 strtok 函式

[編輯] 另請參閱

在一個字串中查詢另一個字串中任意字元的第一個位置
(函式) [編輯]
返回由另一個位元組字串中找到的字元組成的最大初始段的長度
僅由另一個位元組字串中未找到的字元組成
(函式) [編輯]
返回由另一個位元組字串中找到的字元組成的最大初始段的長度
的字元
(函式) [編輯]
(C95)(C11)
在寬字串中查詢下一個標記
(函式) [編輯]
C++ 文件 用於 strtok