字符串處理:字符串分割函數—strtok, strtok_r

#include <string.h>
char* strtok(char *str, const char *delim);
char* strtok_r(char *str, const char *delim, char **saveptr);

【函數描述】將字符串str分割成由delim指定的分隔符的字符串,返回分割後的字符串。第一次執行要以被分割的字符串爲參數,之後要以NULL作爲參數。

【函數說明】strtok_r是Linux平臺下的strtok的線程安全版。Windows下的string.h文件並不包含它,Windows平臺下是strtok_s()函數。strtok_r()strtok()多了一個二級字符指針參數,它是用來在strtok_r()內部保存切割字符串後餘下的字符串的首地址。實際上,strtok()函數也有一個這樣的指針,不過它是被定義成了一個靜態的指針變量來保存切分字符串後餘下的字符串的首地址。而strtok_r()函數實際上是將strtok()內部隱式保存的這個靜態指針以形參的形式與函數外部的實參進行交互。由調用者進行傳遞、保存甚至是修改。調用者在連續切分相同字符串時,除了將str參數賦值給NULL,還要傳遞上次切分時保存下來的saveptr。實際上,它是將切分後剩餘字符串的首地址保存在外部的一個字符指針變量裏,然後將這個指針變量的地址傳遞給形參saveptr。

函數的實現

//strtok_r()函數的實現,來自於glibc
/* Parse S into tokens separated by characters in DELIM.
   If S is NULL, the saved pointer in SAVE_PTR is used as
   the next starting point.  For example:
        char s[] = "-abc-=-def";
        char *sp;
        x = strtok_r(s, "-", &sp);      // x = "abc", sp = "=-def"
        x = strtok_r(NULL, "-=", &sp);  // x = "def", sp = NULL
        x = strtok_r(NULL, "=", &sp);   // x = NULL
                                        // s = "abc\0-def\0"
*/
char* strtok_r(char *s,const char *delim,char **save_ptr)
{
	char *end;
	if(s == NULL)
		s = *save_ptr; //將上次切分後剩餘字符串的首地址賦值給s
	if(*s == '\0'){  //如果當前字符串爲空,返回NULL
		*save_ptr=s;
		return NULL;
	}
	//過濾掉當前字符串開頭的分隔符
	s+=strspn(s,delim);
	if(*s == '\0')
	{
	    *save_ptr=s;
	    return NULL;
	}
	//找到分隔符的位置
	end=s+strcspn(s,delim);
	if(*end == '\0')
	{
	    *save_ptr=end;
	    return s;
	}
	*end = '\0';  //將分隔符的位置用字符串結束符'\0'填充
	*save_ptr=end+1; //*save_ptr指向分隔符的下一個字符
	return s;  //返回分割的字符串
}

//strtok()函數的實現
char* strtok (char *s, const char *delim)
{
  static char *olds;  //定義了一個局部靜態字符指針變量
  return strtok_r (s, delim, &olds);
}

<說明>上面的strtok_r()函數的實現用到了兩個函數分別是strspn()和strcspn()函數。

#include <string.h>
size_t strspn(const char *s, const char *accept);
【函數描述】從參數s字符串的開頭計算連續的字符,而這些字符都是accept字符串中的字符。返回字符串s開頭
連續包含字符串accept中的字符數目。如果s所包含的字符都屬於accept,那麼返回s的長度;如果s的第一個字
符就不屬於accept,那麼返回0。注意,檢索的字符是區分大小寫的。

size_t strcspn(const char *s, const char *reject);
【函數描述】strcspn()函數的作用與strspn()函數的作用相反。它是計算字符串s中連續有幾個字符都不屬於字
符串reject,返回字符串s的開頭連續不含有字符串reject內的字符的數目。

示例程序

1. strtok()函數示例程序。

#include <stdio.h>
#include <string.h>
int main()
{
    char buffer[1024]="ss7Notify:5:1:15973362998";
    char *str,*buf;
    buf=buffer;
    int i=0;
    while((str = strtok(buf, ":")) != NULL)
    {
        printf("i=%d,%s\n",++i,str);
        buf=NULL;
    }
    return 0;
}

運行結果:

i=1,ss7Notify
i=2,5
i=3,1
i=4,15972362632

2. strtok_r()函數示例程序。

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

int main()
{
    char str[]="Legendary:Godlike:Dominating:Unstoppable:Rampage";
    char *ps, *qs;
    char *saveptr;
    int i=0;
    
    printf("before strtok_r(),str= %s\n",str);
    printf("begin:\n");
    ps=qs=str; //ps,qs指針初始指向str數組
    for(; NULL != (ps = strtok_r(qs, ":", &saveptr)); ++i){
        printf("i=%d, ps= %s\n", i, ps);
        qs=NULL;
    }
    printf("end, item count: %d\n", i);
    return 0;
}

運行結果:

before strtok_r(),str= Legendary:Godlike:Dominating:Unstoppable:Rampage
begin:
i=0, ps= Legendary
i=1, ps= Godlike
i=2, ps= Dominating
i=3, ps= Unstoppable
i=4, ps= Rampage
end, item count: 5

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章