字串切割函式strtok、strtok_s、strtok_r的區別
strtok函式
標頭檔案:#include <string.h>
函式原型:char * strtok (char *str, const char * delimiters);
引數:str:待分割的字串(c-string);delimiters:分割符字串。
該函式用來將字串分割成一個個片段。引數str指向欲分割的字串,引數delimiters則為分割字串中包含的所有字元。當strtok()在引數s的字串中發現引數delimiters中包涵的分割字元時,則會將該字元改為\0 字元。在第一次呼叫時,strtok()必需給予引數s字串,往後的呼叫則將引數s設定成NULL。每次呼叫成功則返回指向被分割出片段的指標。
需要注意的是
程式碼舉例:
例1:將字串通過’,’分割開,列印子串並判斷原字串(被分割的字串)是否發生改變
#include <stdio.h>
#include <string.h>
int main()
{
char str[]="ab,cd,ef";
char *ptr;
printf("before strtok: str=%s \n",str);
printf("begin:\n");
ptr = strtok(str, ",");
while(ptr != NULL){
printf("str=%s\n",str);
printf("ptr=%s\n",ptr);
ptr = strtok(NULL, ",");
}
return 0;
}
輸出結果:
before strtok: str=ab,cd,ef
begin:
str=ab
ptr=ab
str=ab
ptr=cd
str=ab
ptr=ef
例2:MSDN例子,字串中含有多個分隔符
#include <string.h>
#include <stdio.h>
char string[] = "A string\tof ,,tokens\nand some more tokens";//被分割的字串
char seps[] = " ,\t\n";//分隔符集
char *token;//用指標作為標記
void main( void )
{
printf( "%s\n\nTokens:\n", string );
/* 建立字串並獲取第一個標記(指向子串的首地址) */
token = strtok( string, seps );
while( token != NULL )
{
/* 在“string”中有標記*/
printf( " %s\n", token );
/* 得到下一個標記*/
token = strtok( NULL, seps );
}
}
輸出結果:
A string of ,,tokens
and some more tokens
Tokens:
A
string
of
tokens
and
some
more
tokens
結論:strtok在切割字串的過程,實際上就是將被分割的字串的分隔字元替換為‘\0’ 並且返回標記字串的首地址,直到返回NULL結束。
stotok函式的實現原理
函式程式碼:
#include<stdio.h>
#include<string.h>
//根據函式原型實現strtok()函式
char* myStrtok_origin(char* str_arr,const char* delimiters,char** temp_str)
{
//定義一個指標來指向待分解串
char* b_temp;
/*
* 1、判斷引數str_arr是否為空,如果是NULL就以傳遞進來的temp_str作為起始位置;
* 若不是NULL,則以str為起始位置開始切分。
*/
if(str_arr == NULL)
{
str_arr =*temp_str;
}
//2、跳過待分解字串
//掃描delimiters字元開始的所有分解符
str_arr += strspn(str_arr, delimiters);//尋找第一個子串,返回子串的長度
//3、判斷當前待分解的位置是否為'\0',若是則返回NULL,否則繼續
if(*str_arr =='\0')
{
return NULL;
}
/*
* 4、儲存當前的待分解串的指標b_temp,呼叫strpbrk()在b_temp中找分解符,
* 如果找不到,則將temp_str賦值為待分解字串末尾部'\0'的位置,
* b_temp沒有發生變化;若找到則將分解符所在位置賦值為'\0',
* b_temp相當於被截斷了,temp_str指向分解符的下一位置。
*/
b_temp = str_arr;
str_arr = strpbrk(str_arr, delimiters);
if(str_arr == NULL)
{
*temp_str = strchr(b_temp,'\0');
}
else
{
*str_arr ='\0';
*temp_str = str_arr +1;
}
//5、函式最後部分無論找沒找到分解符,都將b_temp返回。
return b_temp;
}
//使用myStrtok來簡化myStrtok_origin函式
char* myStrtok(char* str_arr,const char* delimiters)
{
static char* last;//靜態變數
return myStrtok_origin(str_arr, delimiters,&last);
}
int main(void)
{
char buf[]="[email protected]@[email protected]@heima";
//1、使用myStrtok_origin()函式
char*temp_str = NULL;
char*str = myStrtok_origin(buf,"@",&temp_str);
while(str)
{
printf("%s ",str);
str = myStrtok_origin(NULL,"@",&temp_str);
}
//2、使用myStrtok()函式
char*str1 = myStrtok(buf,"@");
while(str1)
{
printf("%s ",str1);
str1 = myStrtok(NULL,"@");
}
return 0;
}
輸出結果:
hello boy this is heima hello
strtok_s函式
strtok_s是Windows下的一個分割字串安全函式,其函式原型
char *strtok_s( char *strToken, const char *strDelimit, char **buf);
數將剩餘的字串儲存在buf變數中,而不是靜態變數中,從而保證了安全性。
程式碼示例:
例1:使用strtok_s函式分隔字串
#include <stdio.h>
#include <string.h>
int main()
{
char str[]="ab,cd,ef";
char *ptr;
printf("before strtok: str=%s\n",str);
printf("begin:\n");
char *pTmp = NULL;
ptr = strtok_s(str,",",&pTmp);
while(ptr != NULL)
{
printf("str=%s\n",str);
printf("ptr=%s\n",ptr);
ptr = strtok_s(NULL,",",&pTmp);
}
return 0;
}
輸出結果:
before strtok: str=ab,cd,ef
begin:
str=ab
ptr=ab
str=ab
ptr=cd
str=ab
ptr=ef
strtok_r函式
strtok_s函式是linux下分割字串的安全函式,函式宣告如下:
char *strtok_r(char *str, const char *delim, char **saveptr);
(1)該函式也會破壞帶分解字串的完整性,但是其將剩餘的字串儲存在saveptr變數中,保證了安全性。
(2)在函式strtok中剩餘字串是儲存在一個靜態變數中,因此,多執行緒在使用該靜態變數時引起衝突;而strtok_r則使用使用者傳入的指標為每個使用者saveptr重新申請變數,因而可以保證執行緒安全。
(3)strtok_r函式是strtok函式的可重入版本,也即執行緒安全版本。str為要分解的字串,delim為分隔符字串。char *saveptr引數是一個指向char 的指標變數,用來在strtok_r內部儲存切分時的上下文,以應對連續呼叫分解相同源字串。
程式碼示例:
#include <stdio.h>
#include <string.h>
int main()
{
char str[]="ab,cd,ef";
char *ptr;
char *p;
printf("before strtok: str=%s\n",str);
printf("begin:\n");
ptr = strtok_r(str, ",", &p);
while(ptr != NULL){
printf("str=%s\n",str);
printf("ptr=%s\n",ptr);
ptr = strtok_r(NULL, ",", &p);
}
return 0;
}
輸出結果:
拓展:
可重入函式:
(1)重入即表示重複進入,首先它意味著這個函式可以被中斷,其次意味著它除了使用自己棧上的變數以外不依賴於任何環境(包括static),這樣的函式就是purecode(純程式碼)可重入,可以允許有該函式的多個副本在執行,由於它們使用的是分離的棧,所以不會互相干擾。如果確實需要訪問全域性變數(包括static),一定要注意實施互斥手段。可重入函式在並行執行環境中非常重要,但是一般要為訪問全域性變數付出一些效能代價。
(2)指一個可以被多個任務呼叫的函式(過程),任務在呼叫時不必擔心資料是否會出錯。
不可重入函式:
如果函式介面的程式碼實現中在塊內定義和使用了static儲存型別的變數,這種函式將是不可重入函式。它在實時系統中是不安全函式。
參考:http://blog.csdn.net/jiangqin115/article/details/48545895
http://www.cnblogs.com/Bob-tong/p/6610806.html
http://blog.csdn.net/lavorange/article/details/47134121
相關推薦
字串切割函式strtok、strtok_s、strtok_r的區別
strtok函式 標頭檔案:#include <string.h> 函式原型:char * strtok (char *str, const char * delimiters); 引數:str:待分割的字串(c-string);delimit
strtok、strtok_s、strtok_r 字串分割函式
1、strtok函式 函式原型:char * strtok (char *str, const char * delimiters); 引數:str,待分割的字串(c-string);delimiters,分割符字串。 該函式用來將字串分割成一個個片段。引數str指
C字串——庫函式系列(strlen、strcat、strcpy、strcmp)
一定義: 字串:字串是由零個或者多個字元組成的有限序列; 子串:字串中任意個連續的字元組成的子序列,並規定空串是任意串的子串,字串本身也是子串之一;“abcdefg”,”abc“就是其子串,但是“ade”不屬於子串範圍。 子序列:不要求字元連續,但是其順序與其在主串中相一致;上例中,“abc
JS陣列的slice()方法傳負數和字串操作函式中的slice()、substr()、substring()
定義和用法 slice() 方法可從已有的陣列中返回選定的元素。 語法 arrayObject.slice(start,end) 引數 描述 start 必需。規定從何處開始選取。如果是負數,那麼它規定從陣列尾部開始算起的位置。也就是說,-1 指最
C語言字串擷取函式strtok和strtok_r
在看原始碼的時候需要將一段並排的IPs轉化成為一系列的IP,將"10.0.0.1;10.0.0.2;10.0.0.3;10.0.0.4;10.0.0.5"轉換成為單獨的"10.0.0.1
c語言的split字串分割函式strtok的使用
c語言也有類似其他語言的split字串分割函式,就是strtok 標頭檔案:#include <string.h>定義函式:char * strtok(char *s, const char *delim);函式說明:strtok()用來將字串分割成一個個片段。
c,c++中字串處理函式strtok,strstr,strchr,strsub
函式原型:char *strtok(char *s, char *delim); 函式功能:把字串s按照字串delim進行分割,然後返回分割的結果。 函式使用說: 1.strtok函式的實質上的處理是,strtok在s中查詢包含在delim中的字元並用NULL(’/0′)來替換,直到找遍整個字串。這句
strtok、strtok_r 字串分割函式
1.一個應用例項 typedef struct person{ char name[25]; char sex[10]; char age[4]; }Person; 需從字串 char buffer[INFO_MAX_
stof()、atoi()、atol()、strtod()、strtol()、strtoul() 共6個可以將字串轉換為數字的函式
標頭檔案:#include <stdlib.h> atoi() 函式用來將字串轉換成整數(int),其原型為: int atoi (const char * str); 【函式說明】atoi() 函式會掃描引數 str 字串,跳過前面的空白字元(例如空格,tab縮排等,可以通過 
2018.9.10學習內建函式、切片、字串拼接等
今日練習: # 題目1:從網路上使用爬蟲程式得到下面字串: # zhangsan-18-175-70-python5;lisi-20-170-80-python5;wangwu-28-165-60-python3;zhaoliu-18-175-70-python5;xi
【c語言】利用指標模式實現字串函式(strlen、strcat、strstr、strcpy、strcmp、memcpy、memove)
模擬實現strlen int my_strlen(const char *p) { assert(p != NULL); char *s = p; while (*p) { p++; } r
四、PHP處理字串常用函式
字串操作 一、字串的連線 “. ”可以連線兩個及以上的字元為一個字串 二、字串的操作 1.trim()去除字串首尾空格和特殊字元,並返回處理後字串。 string trim(string str[,string charlist]); 必選引數str要操作的字
Mysql內建函式(字串、日期、數子)
mysql操作函式 數值操作ABS(N):返回絕對值CEIL(N):返回不小於引數的最小整數值CEILING(N):返回不小於引數的最小整數值CONV(N,FROM_BASE,TO_BASE):數字的進位制轉換EXP(N):返回e的n次方FLOOR(N) :返回不大於引數的
JS 進階(9) ECMAScript6 基礎入門:變數、函式、解構賦值、陣列、字串、面向物件、json、promise
一、ES6是啥 ECMAScript 和 JavaScrip的關係 簡單的說ECMA 是一個標準,任何語言都可以去實現這個標準,但目前為止只有javascript 實現了。所以也就預設認為ECMAScript就是javascript。 ECMAScript
C語言字串函式總結:模擬實現常用的字串類函式(strlen、strcpy、strcmp........)
總結:模擬實現常用的字串類函式(strlen、strcpy、strcmp……..) 1. strlen 2. strcpy 3. strcat 4. strstr 5. strchr 6. strcmp 7. memcpy 8. m
nginx切割字串、泛域名、kong、轉發代理
因為業務需要多租戶,因此使用了nginx的正則方便地拿到租戶的編號。 業務請求要轉發到kong。 server { listen 80 default_ser
python中字串:宣告、編碼、函式、格式化
字串的宣告有三種方式:單引號、雙引號和三引號(包括三個單引號或三個雙引號)。例如: ? 1 2 3 4 5 6 7 8 9 10 11 12 >>> str1= 'hello world' >>> str2= "hello
python常用的幾種字串替換函式strip、replace、sub
#!/usr/bin/env python # coding:utf-8 import re ''' 功能:對常見的幾種字串處理函式進行測試使用學習 Author:沂水寒城 ''' def str_test(): str_list=['We are family!!!', '00 11 2
python字串內建函式操作例項(cmp、str、enumerate、zip等)
#coding=utf8 ''' cmp(str1,str2):根據字串的ASCII碼值進比較,返回一個整數。 如果返回值大於零,str1大於str2; 如果返回值小於零,str1小於str2; 如果返回值等於零,str1等於str2; len(object):返回序列的
C++中讀取字元、字串的函式
iostream流:cin、cin.get()、cin.getline() string流:getline() cin:配合輸入操作符">>"使用。而操作符">>"預設會跳過空格、製表符、tab、回車符等分隔符,實際上這