strtok函數的使用注意事項
1. 函數原型及其基本應用
strtok函數是用來分解字元串的,其原型是:
char *strtok(char str[], const char *delim);
其中str是要分解的字元串,delim是字元串中用來分解的字元,該函數傳回分解後的字元串的起始位置指針。之是以是分解,就是說并沒有生成新的字元串,隻是在源字元串上面做了一些手腳,使得源字元串發生了變化,是以一定要注意,源字元串發生了變化!!!
先從最簡單的應用來看,看下面的例1。
// 例1
#include <string.h>
void main()
{
char s[] = "192.168.0.26";
char *delim = ".";
char *p;
printf("%s ", strtok(s, delim));
while((p = strtok(NULL, delim)))
printf("%s ", p);
printf("\n");
}
從例1中就可以看出strtok函數的基本使用方法,輸入一個字元串數組,然後就可以将其按照一定的分隔符(例1中為".")将一個長的字元串分割成一個個短的字元串。這裡需要注意的是,在對一個長字元串分割的時候,第一次調用時,strtok函數的第一個參數傳入要分割的字元串,而第二次以及後面再次調用該函數的時候,strtok函數的第一個參數應該傳入NULL,這是因為在strtok第一個參數為NULL的時候,該函數預設使用上一次未分割完的字元串的未分割的起始位置作為本次分割的起始位置,直到分割結束為止。
這個例子就最常見的基本應用,但是僅僅知道這些很容易忽略很多細節問題,後面本文将繼續讨論一些值得注意的問題。
2. 使用注意事項1
這裡首先需要強調的是strtok函數在進行字元串分解的時候,其第一個參數,即char str[]是在變化的,就像前面說過的一樣,其隻是對源字元串動了一些手腳,也就是改變了源字元串。以例1中的字元串來說,"192.168.0.26"是源字元串,在調用strtok對其分解結束後,字元串變成了"19201680026",注意其中紅色加粗部分是把'.'替換成了'\0',也就是替換成了字元串結束标志字元,這樣在列印或使用的時候都會使得前面的字元串成為一個看起來獨立的字元串,即"192"、"168"、"0"、"26",這些字元串還是在源字元串中,隻是後面都有了自己的字元串結束标志'\0'而已。
3. 使用注意事項2
在注意事項1中提到了源字元串發生了變化,同時注意到strtok函數原型的第一個參數是一個字元數組char str[],雖然說傳遞參數時實參可以是一個指針,但是這個指針如果是字元串常量指針,那麼就會引起程式運作時崩潰,因為源字元串要發生變化,而字元串常量是不能被改變的,例如下面的例2就是錯誤的。
// 例2
#include <string.h>
void main()
{
char *s = "192.168.0.26"; // 與例1的唯一差別,字元串數組變成了字元串常量指針!!!
char *delim = ".";
char *p;
printf("%s ", strtok(s, delim));
while((p = strtok(NULL, delim)))
printf("%s ", p);
printf("\n");
}
是以如果輸入是字元串常量指針的時候,是不能直接傳遞給strtok函數的第一個參數的,大家可以将這個字元串常量指針中的内容逐一拷貝到一個字元串數組中,再進行分解,不過這種方法效率比較低,是以并不建議這樣使用,如果實在無法使用strtok函數進行字元串分解,那麼可以使用其他的函數進行類似分解,比如使用strstr函數、strchr函數等。
4. 使用注意事項3
對于strtok函數的第二個參數,即分隔符,要注意:包含在delim中的字元均可以作為分隔符,而非嚴格比對。可以把delim了解為分隔符的集合。這一點是非常重要的!當然,我們在分解字元串的時候,很少使用多個分隔符。這也導緻,很多人在寫例子的時候隻讨論了一個分隔符的情況。有更多的人在看例子的時候也就錯誤的認識了delim的作用。
5. 使用注意事項4
如果strtok函數要分解的字元串的首字元就是分隔符,那麼strtok函數會忽略第一個字元,直接從下一個分隔符算起。比如:".192.168.0.26",那麼第一個字元'.'就會被忽略,分解後的第一個字元串就是"192"。
總之,strtok函數是一個看起來很簡單,但是使用起來有很多需要注意的細節的函數,是以應該了解掌握,由于strtok函數并不是線程安全的,是以很多情況下并不再使用這個函數,而是由程式員實作自己的字元串分割函數,進而保證線程安全,不過,在Linux中定義了strtok_r函數,這個函數是strtok函數的線程安全版本,具體使用方法可以參考其他資料。
如果大家還有别的意見,歡迎大家多多補充,謝謝。
參考資料:
http://blog.csdn.net/helpxs/article/details/6958975