首頁  >  文章  >  後端開發  >  strtok函數的用法是什麼

strtok函數的用法是什麼

coldplay.xixi
coldplay.xixi原創
2020-10-28 09:48:2716340瀏覽

strtok函數的用法:1、作用於字串s,以delim中的字元為分界符,將s切分成一個子字串;2、如果s為空值NULL,則函數儲存的指標【SAVE_PTR】在下次呼叫中將作為起始位置。

strtok函數的用法是什麼

相關免費推薦:程式設計影片課程

strtok函數的用法:

##一、函數的簡介

         函數原型:char *strtok(c​​har *s, char *delim)

         功能:作用於字串s,以delim中的字元為分界符,將s切割分成一個個子字串;如果,s為空值NULL,則函數保存的指標SAVE_PTR在下AVE_PTR一次調用中將作為起始位置。

         傳回值:分隔符號符合的第一個子字串

二、主要內容

       

1、函數的功能是為#        #分解字串,所謂分解,即沒有產生新串,只是在s所指向的內容首次出現分界符的位置,將分界符修改成了'/0',故第一次用strtok()返回第一個子字串

         2、第一次提取子串完畢之後,繼續對來源字串s進行提取,應在其後(第二次,第三次。 。。第n次)的調用中將strtok的第一個參數賦為空值NULL(表示函數繼續從上   一次調用隱式保存的位置,繼續分解字符串;對於前一次次調用來說,第一次呼叫結束前用一個this指針指向了分界符的下一個

#         3、當this指針指向“\0” 時,也就是沒有分割的子字串了,此時則回傳NULL

#         4、#可以將delim理解為分隔符的集合delim中的字元皆可以作為分隔符號。

         5、strtok在呼叫的時候,如果起始位置即為分隔符,則忽略了起始位置開始的分隔符號


#三、使用strtok需要注意的有以下幾點:

1.函數的作用是分解字串,所謂分解,即沒有產生新字串,只是在s所指向的內容上做了些手腳而已。因此,來源字串s發生了變化!

設來源字串s為char buffer[INFO_MAX_SZ]=",Fred male 25,John male 62,Anna female 16";  過濾字串delim為char *delim = " ",即空格為分界符。

strtok函數的用法是什麼 

上圖的程式碼會產生這樣的結果:

strtok函數的用法是什麼

首先,buffer發生了變化。如果此時印出buffer的值,會顯示“,Fred”,而後面" male 25…16”不翼而飛了。實際上,strtok函數根據delim中的分界符,找到其首次出現的位置,即Fred後面那個空格(buffer[5]),將其修改成了'/0’。其餘位置不變。這就很好解釋為什麼印buffer的值只能出現“,Fred”,而非buffer中的全部內容了。 因此,使用strtok時一定要慎重,以防止來源字串被修改。

 

了解buffer的變化,就很好解釋函數的回傳值了。傳回值buf為分界符之前的子字串(其實這個說法並不確切,詳見"3」中對於傳回值的詳細說明)。 注意,由變數的位址可知,buf仍指向來源字串。

strtok函數的用法是什麼

分界符delim沒有發生變化,就不再截圖了。

 

2.若要在第一次提取子串完畢之後,繼續對來源字串s進行提取,應在其後(第二次,第三次。。。第n次)的調用中將strtok的第一個參數賦為空值NULL。

strtok函數的用法是什麼

####

第一次調用的結果如前文所述,提取出了",Fred」。我們也想繼續以空格為分界,提取出後面的"male」等。由上圖可以看到,第一次之後的呼叫我們都給strtok的第一個參數傳遞了空值NULL(表示函數繼續從上一次呼叫隱式保存的位置,繼續分解字串;對於上述的第二次呼叫來說,第一次呼叫結束前用一個this指標指向了分界符的下一位,即'm'所在的位置),這樣可依序提取出

strtok函數的用法是什麼# ,strtok函數的用法是什麼 。 。 。 。以此類推。 。 。 。 。

至於為什麼要賦空值,要嘛你就記得結論,要嘛去查strtok的原始碼。本文的最後會有一些介紹。

當然也有部分愛鑽牛角尖的人,非不按套路出牌,要看看不賦空值繼續賦值為buffer會有什麼結果。其實,答案想也能想的到。再一次傳遞buffer,相當於還從字串的開頭查找分界符delim,而且此時buffer已經被修改(可見的部分只剩下",Fred」),因此,其結果必然是找不到分界符delim 。

 

3.關於函數傳回值的探討

由"1」所述,在擷取到子字串的情況下,strtok的回傳值(假設回傳值賦給了指標buf)是提取出的子字串的指標。這個指標指向的是子字串在來源字串中的起始位置。子字串末尾的下一個字元在提取前為分隔符,提取後被修改成了'/0’。 因此,若列印buf的值,可以成功的輸出子字串的內容。

在沒有提取到子字串的情況下,函數會傳回什麼值呢?

strtok函數的用法是什麼

由上圖可以看到buffer中並不包含分界符delim。呼叫strtok後buf的值為

strtok函數的用法是什麼

因為沒有找到,來源字串buffer沒有改變,buf指向來源字串的首位址,列印輸出的值為整個字符串的完整值。

什麼時候函數的回傳值為空值NULL呢?

百度百科上說,「當沒有分割的字串時則回傳NULL。」這是一個很模稜兩可的說法。如果想要確切的了解清楚這個問題,可能需要看一下strtok的實作原理。這裡先以實驗說明。

strtok函數的用法是什麼

第一次呼叫strtok,毫無疑問,buf指向",Fred」。

第二次呼叫strtok,由於第一個參數為NULL,表示函數繼續以上次呼叫所儲存的this指標的位置開始分解,即對"male 25」分解。分解完畢後,buf指向"male」。

第三次呼叫strtok,參數繼續設定為NULL,此時即對第二次儲存的this指標的位置開始分解,即對"25」分解。因為無法找到包含分隔符號delim的子字串,所以buf指向"25」。

strtok函數的用法是什麼

第四次調用,參數仍為NULL,此時第三次調用保存的this指針已指向字串的末尾'/0',已無法再進行分解。因此函數傳回NULL,這也就是百度百科中所提到的「當沒有被分割的字串時函數回傳NULL。」

strtok函數的用法是什麼

## 

4 .參數分隔符delim的探討(delim是分隔符號的集合)

很多人在使用strtok的時候,都想當然的以為函數在分割字串時完整匹配分隔符號delim,例如delim=”ab ”,則對於"acdab”這個字串,函數提取出的是"acd”。至少我在第一次使用的時候也是這麼認為的。其實我們都錯了,我是在看函數的原始碼時才發現這個問題的,並且看下面的例子。

strtok函數的用法是什麼

來源字串為buffer,分隔符delim為逗號和空格,按照一般的想法我們會以為調用函數後,buf的值為"Fred,male,25 ”,結果是這樣麼?

strtok函數的用法是什麼

第一次呼叫之後的結果竟然是"Fred”,而非我們所想的結果。 這是為什麼呢?

我們回到GNU C Library中對strtok的功能定義:「Parse S into tokens separated by characters in DELIM」。 也就是說包含在delim中的字元均可以作為分隔符,而非嚴格匹配。可以把delim理解為分隔符號的集合。這一點是非常重要的~

當然,我們在分解字串的時候,很少使用多個分隔符號。這也導致,很多人在寫例子的時候只討論了一個分隔符號的情況。有更多的人在看例子的時候也就錯誤的認識了delim的作用。

5.待分解的字串,首字就為分隔符號

首字不能算是一個很特殊的情況。按照常規的分解思路也能正確分解字串。

我想說明的是,strtok對於這種情況採用了比常規處理更快的方式。

strtok函數的用法是什麼

如上圖範例所示。僅用一次呼叫就可以得到以逗號分隔的字串"Fred male 25”,而F前面的','被忽略了。由此可見,strtok在呼叫的時候忽略了起始位置開始的分隔符號。 這一點,可以從strtok的原始碼得到證實。

6.不能傳遞字串常數給第一個參數!

本文所舉的例子都將來源字串儲存為字串陣列變數。若你將來源字串定義成字串常數,可想而知,程式會因為strtok函數試圖修改來源字串的值,而拋出異常。

strtok函數的用法是什麼

#

以上是strtok函數的用法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn