1. 程式人生 > >Linux C函式strtok解析

Linux C函式strtok解析

1. 今天看了看strtok函式,特意找了下Linux核心2.0.1版本的程式碼,因為在更高版本(至少2.6)已經使用strsep替換了該函式.

函式原型:

char * strtok(char * s,const char * ct)

使用第二個引數ct中的分隔符字串,分割第一個引數s,ct引數的分隔符可以是任意字元,可以是單個字元的分隔符,也可以是字串形式的分隔符如:"!,;'/"等,都可以作為分隔符。例如:

s="abc,def,123;456!/aaa"

ct=",;!/"

s將被分割為為:abc def 123 456 aaa

測試程式碼:

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

int main()
{
  char s[] = "abc,def,123;456!/aaa";
  char delim[] = " ,;!/";

  char *p = NULL;
  for(p = strtok(s, delim); p != NULL; p = strtok(NULL, delim))
  {
    printf("%s ", p);
  }
  printf("\n");

  return 0;
}
[[email protected] algorithm]$ gcc strtok.c -o strtok
[[email protected] algorithm]$ ./strtok
abc def 123 456 aaa

2. strtok程式碼分析,以下程式碼摘自Linux2.01.版本:

char * strtok(char * s,const char * ct)
{
	char *sbegin, *send;

	sbegin  = s ? s : ___strtok;
	if (!sbegin) {
		return NULL;
	}
	sbegin += strspn(sbegin,ct);
	if (*sbegin == '\0') {
		___strtok = NULL;
		return( NULL );
	}
	send = strpbrk( sbegin, ct);
	if (send && *send != '\0')
		*send++ = '\0';
	___strtok = send;
	return (sbegin);
}

先說下strtok的整體思想也就是關鍵的幾個步驟:

a。首先strtok將資料儲存在全域性變數__strtok中,因此不是執行緒安全的也即不可重入。

b。strtok查詢分隔符字串時,跳過連續的分隔符,這樣可以忽略連續分隔符之間的空串,連續分隔符是從源字串開始位置計算,個數通過函式strspn計算得出。

      size_t strspn(const char *s, const char *accept),計算字串 str 中連續有幾個字元都屬於字串 accept。

      例如:";,/!ABC!/DEF",前四個字元都是分隔符且是連續的,那麼strspn函式返回4,有效資料跳過前4個分隔符就從字元A開始,直到下一分隔符。

c。呼叫函式strpbrk,即源字串中的字元如果與分隔符字串中任意字元相同,就返回指向源字串中該字元的指標,即找到了分隔符,返回該資料的指標。

      char * strpbrk(const char * cs,const char * ct),比較字串str1和str2中是否有相同的字元,如果有,則返回該字元在str1中的位置的指標。

      例如:";,/!ABC!/DEF",跳過4個分隔符後,從A開始直到遇到分隔符感嘆號(!) 那麼,就返回指向資料起始位置的指標,該指標指向字元A。

細節分析:

a。 變數__strtok是全域性變數,定義在string.c檔案中:char * ___strtok = NULL; 在標頭檔案linux/string.h中進行外部宣告,只要使用該變數的c檔案包含該標頭檔案即可;

b。全域性變數__strtok儲存了剩餘未做分隔的字串的起始地址,每次呼叫strtok函式,都從全域性變數__strtok指向的地址開始查詢引數中的分隔符字串,找到之後__strtok指向本次分隔符的下一位置(有效資料或者結尾符\0,又或者是分隔符如果有連續分隔符的話)。

c。對於字串 "abc,def,123;456!/aaa"; 第一次呼叫strtok之後,分隔符逗號(,)被設定為\0,__strtok設定為指向第一個分隔符逗號之後的資料即__strtok指向字元d,返回指向字元a的指標;第二次呼叫strtok時,從__strtok指向的字元d開始查詢delim中的分隔符,找到第二個逗號時,與第一次操作一樣,分隔符逗號被設定為\0,並從新設定__strtok指向字元1,返回指向字元d的指標,後續一直如此迴圈。

d。如果源字串包含連續分隔符,則呼叫函式strspn計算出連續相同的分隔符字元後會跳過這些分隔符。

附上函式strspn的測試示例:

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

int main()
{
  int ret = 0;
  char s1[] = "abc,;!/}defgh,,,**#123,456";
  char s2[] = ";,/#}*abc,;!/}defgh,,,**#123,456";
  char delim[] = ",;!/}#*";

  ret = strspn(s1, delim);
  printf("ret1:%d\n", ret);

  ret = strspn(s2, delim);
  printf("ret2:%d\n", ret);

  return 0;
}

結果如下:

[[email protected] algorithm]$ gcc strspn.c -o strspn
[[email protected] algorithm]$ ./strspn              
ret1:0
ret2:6

函式是從源字串開始位置匹配分隔符,只有開始的連續才起作用,開始有1個或者多個則返回匹配到的分隔符個數,如果開始位置一個分隔符都沒有,則返回0,如果有1個則返回1個,上例中返回6個。

相關推薦

Linux C函式strtok解析

1. 今天看了看strtok函式,特意找了下Linux核心2.0.1版本的程式碼,因為在更高版本(至少2.6)已經使用strsep替換了該函式. 函式原型: char * strtok(char * s,const char * ct) 使用第二個引數ct中的分隔符字串,分

linux C函式之stat函式

1.函式功能: 通過檔名filename獲取檔案資訊,並儲存在buf所指的結構體stat中 2.函式原型 1)函式標頭檔案 #include <sys/stat.h> #include <unistd.h> 2)函式 int stat(const c

Linux C 函式速查

...abs         abs(計算整型數的絕對值) 相關函式 labs, fabs 表頭檔案 #include<stdli

【轉】Linux C函式庫參考

  asctime(將時間和日期以字串格式表示)clock(取得程序佔用CPU的大約時間)ctime(將時間和日期以字串格式表示)difftime(計算時間差距)ftime(取得目前的時間和日期)gettimeofday(取得目前的時間)gmtime(取得目前的時間和日期)loca

linux C函式之access函式的用法【轉】

1.函式功能: 檢查呼叫程序是否可以對指定的檔案執行某種操作。 2.函式原型: 1)函式標頭檔案 #include <stdio.h> #include <unistd.h> 2)函式 int access(

linux c 命令列解析

getopt_long.h標頭檔案,是解析命令列的一個頭檔案,裡面包括了有無及可選引數的定義,以及可選引數的解析 其中看標頭檔案就可以知道getopt_long函式是其主要的功能 其包含巨集定義如下 #define no_argument 0 #def

Linux--C函式

1.函式的定義為了使程式大而不繁,簡單明瞭,程式設計者要根據軟體的總體要求,把相同的功能或相似的操作歸納成模組的形式,並設計成函式,以實現程式設計的結構化。2.函式定義的一般格式型別識別符號 函式名([引數表列]){[宣告部分]語句}呼叫後續宣告的函式時,必須在呼叫之前先進行

Linux C]利用libxml2解析xml檔案

為了解析xml,可以使用Linux下預設安裝的libxml2。/*     a.c     功能:利用libxml2解析xml檔案 */#include <stdio.h>#include <stdlib.h>#include <string.h

Linux C 函式指標應用---回撥函式

    (這裡引用了知乎上一些知友的回答,感覺不錯,有助於理解,這裡引用作為借鑑,如有冒犯,煩請告知)     我們先來回顧一下函式指標,函式指標是專門用來存放函式地址的指標,函式地址是一個函式的入口地址,函式名代表了函式的入口地址。當一個函式指標指向了一個函式,就可以通過

Linux C中main函式中的引數argc和argv

                                          &

Linux C獲取時間函式例項

例項詳解Linux下C獲取時間函式的程式碼。 一、time 標頭檔案: #include <time.h> 原型: time_t time(time_t *t) time_t的定義: typedef __darwin_time_t  time_t; typedef long

C語言】字串函式strtok 按照指定字串分割

C語言字串函式 strtok() 函式原型 char *strtok(char *str,const char *delimiters); 引數 str,待分割的字串 delimiters,分隔符字串 該函式用來將字串str分割成一個個片段。 引數str指

Linux C 中獲取local日期和時間 time()&localtime()函式

1.  time() 函式 /* time - 獲取計算機系統當前的日曆時間(Calender Time) * 處理日期時間的函式都是以本函式的返回值為基礎進行運算 * 函式原型: * #include <time.h>

軟體素材---linux C語言:linux下獲取可執行檔案的絕對路徑--getcwd函式

      //標頭檔案:#include <unistd.h>     //定義函式:char * getcwd(char * buf, size_t size);    

軟體素材---linux C語言:拼接字串函式 strcat的用例(與char陣列聯合使用挺好)

【標頭檔案】#include <string.h> 【原型】 1 char *strcat(char *dest, const char *src); 【引數】: dest 為目標字串指標,src 為源字串指標。

C++ 函式呼叫過程中棧的變化解析

“ 走好選擇的路,別選擇好走的路,你才能擁有真正的自己。” There you go again! I'll back you up! 記錄下函式呼叫的情況~ 函式呼叫的另一個詞語表示叫作 過程。一個過程呼叫包括將資料和控制從程式碼的一部分傳遞到另一部分。

C++ 虛擬函式解析

1 前言 C++中的虛擬函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父型別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有“多種形態”,這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的程式碼來實現

Linux常用C函式

可以參考這個: /第三章   檔案IO******************************************/ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 函

Linux C高階程式設計——網路程式設計之包裹函式

                                    Linux網路程式設計(六)——包裹函式                          宗旨:技術的學習是有限的,分享的精神是無限的。          系統呼叫不能保證每次都成功,必須進行出

Linux C高階程式設計——檔案操作之庫函式

Linux C高階程式設計——檔案操作之庫函式 宗旨:技術的學習是有限的,分享的精神是無限的 ——為什麼要設計標準I/O庫? 直接使用API進行檔案訪問時,需要考慮許多細節問題 例如:read、write時,緩衝區的大小該如何確定,才能使效率最優 標準I/O庫封裝了諸多