想不到吧,這個部落格居然還活著,而且還會填坑。
原本以為常用的字串函式都介紹得差不多了,直到最近工作時看到 strtok
才想到,好像還沒介紹過他。
strtok
:字串分割
所屬標頭檔:<string.h>
函式宣告:
char* strtok( char* restrict str, const char* restrict delim );
strtok
的功能是將字串分成一個個的 token,也就是字串片段。聽起來好像很簡單,不過 strtok
的運作方式可能會讓人有點意外。
先說明參數的部分:第一個參數 str
是要被分割的字串,而第二個 delim
則表示要以哪些字元來分割字串,在 delim
裡的所有字元皆會被用於分割 str
。
接著來看看 strtok
的使用方式,strtok
的呼叫分為兩種類型:初次呼叫及後續呼叫。
初次呼叫:以非
NULL
的字串str
呼叫strtok(str, delim)
,strtok
會將str
中第一個遇到的分隔字元替換為\0
,也就是進行分割,然後回傳此 token 的指標。後續呼叫:在初次呼叫之後,我們要改用
NULL
來呼叫strtok
,也就是strtok(NULL, delim)
。這種情況下,strtok
會從上次分割的地方繼續,尋找下一個分隔字元並進行分割,最後將新找到的 token 回傳。有趣的是,在每次的後續呼叫中,
delim
都可以換成不同的分隔字元。
當 strtok
找不到下一個 token,例如已經到底(\0
)或字串剩下的部分都是分隔字元,則會回傳 NULL
。
strtok
會直接修改原本的字串,需謹慎使用。
不過為什麼只傳入 NULL
,strtok
就會知道要從哪裡繼續呢?其實 strtok
函式使用了靜態(static
)變數來儲存上次分割處的下一個位址,以利在後續呼叫時使用。
每次呼叫 strtok
都會修改這個靜態變數,導致這個函式並不是執行緒安全(thread-safe)的。
來看看具體的使用範例:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[32] = "hello world foo bar span";
char *token;
token = strtok(str, " ");
while (token) {
printf("%s\n", token);
token = strtok(NULL, " ");
}
return 0;
}
細心的讀者們可能會想到,要是字串開頭就是分隔字元會發生什麼事呢?這時候 strtok
會一路向後尋找第一個不是分隔字元的字元,並當作此次 token 的起始位置,若找不到則回傳 NULL
。
另外,若 str
或 delim
不是以 \0
結尾的字串,就會造成 Undefined behavior。
最後再來看同時有多個分隔字元的例子:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char str[512] = // Note: this paragraph is generated by ChatGPT
"The deep sea remains one of the most mysterious places on Earth, with vast areas still unexplored by humans. Strange "
"creatures, like bioluminescent fish and giant squid, thrive in its cold, dark depths. Scientists believe that "
"studying these extreme environments could help us understand life on other planets. As technology advances, we may "
"one day uncover the secrets hidden in the ocean's abyss.";
char *sentence;
sentence = strtok(str, ",."); // split by , or .
while (sentence) {
while (isspace(sentence[0])) { // Skip spaces if any
sentence++;
}
printf("%s\n", sentence);
sentence = strtok(NULL, ",.");
}
return 0;
}
參考資料:
後記:
好久不見,這幾年經歷的事實在是太多了,去年更是從年頭忙到年尾。雖然發了篇新文,但也不代表之後會固定更新就是ㄌ
其實是看到 Google 搜尋後台的報告中,點閱數逐漸下滑,才在想是不是該來救一下的,不過大概也不是發幾篇文就能救得起來XD