strtok_r

  strtok_r()函數用於分割字符串。strtok_r是linux平臺下的strtok函數的線程安全版。windows的string.h中並不包含它。

函數原型

char *strtok_r(char *str, const char *delim, char **saveptr);

  strtok_r函數是strtok函數的可重入版本。str爲要分解的字符串,delim爲分隔符字符串。char **saveptr參數是一個指向char *的指針變量,用來在strtok_r內部保存切分時的上下文,以應對連續調用分解相同源字符串。
  第一次調用strtok_r時,str參數必須指向待提取的字符串,saveptr參數的值可以忽略。連續調用時,str賦值爲NULL,saveptr爲上次調用後返回的值,不要修改。一系列不同的字符串可能會同時連續調用strtok_r進行提取,要爲不同的調用傳遞不同的saveptr參數。
  strtok_r實際上就是將strtok內部隱式保存的this指針,以參數的形式與函數外部進行交互。由調用者進行傳遞、保存甚至是修改。需要調用者在連續切分相同源字符串時,除了將str參數賦值爲NULL,還要傳遞上次切分時保存下的saveptr。

應用

#include <stdio.h>
#include <string.h>
 
int main(void)
{
  int j,in = 0;
  char buffer[100] = "Fred male 25,John male 62,Anna female 16";
  char *p[20];
  char *buf = buffer;
  char *outer_ptr = NULL;
  char *inner_ptr = NULL;
  while ((p[in] = strtok_r(buf, ",", &outer_ptr)) != NULL)
  {
    buf = p[in];
    while ((p[in] = strtok_r(buf, " ", &inner_ptr)) != NULL)
    {
      in++;
      buf = NULL;
    }
    buf = NULL;
  }
  printf("Here we have %d strings\n", in);
  for (j = 0; j < in; j++)
  {
    printf(">%s<\n", p[j]);
  }
  return 0;
}

在這裏插入圖片描述

調用strtok_r的代碼比調用strtok的代碼多了兩個指針,outer_ptr和inner_ptr。outer_ptr用於標記每個人的提取位置,即外循環;inner_ptr用於標記每個人內部每項信息的提取位置,即內循環。具體過程如下:
(1)第1次外循環,outer_ptr忽略,對整個源串提取,提取出"Fred male 25",分隔符’,’ 被修改爲了’\0’,outer_ptr返回指向’J’。
(2)第一次內循環,inner_ptr忽略,對第1次外循環的提取結果"Fred male 25"進行提取,提取出了"Fred",分隔符’ ‘被修改爲了’\0’,inner_ptr返回指向’m’。
(3)第二次內循環,傳遞第一次內循環返回的inner_ptr,第一個參數爲NULL,從inner_ptr指向的位置’m’開始提取,提取出了"male",分隔符 ’ ‘被修改爲了’\0’,inner_ptr返回指向’2’。
(4)第三次內循環,傳遞第二次內循環返回的inner_ptr,第一個參數爲NULL,從inner_ptr指向的位置’2’開始提取,提取出了"25",因爲沒有找到’ ‘,inner_ptr返回指向25後的’\0’。
(5)第四次內循環,傳遞第三次內循環返回的inner_ptr,第一個參數爲NULL,因爲inner_ptr指向的位置爲’\0’,無法提取,返回空值。結束內循環。
(6)第2次外循環,傳遞第1次外循環返回的outer_ptr,第一個參數爲NULL,從outer_ptr指向的位置’J’開始提取,提取出"John male 62",分隔符’,’被修改爲了’\0’,outer_ptr返回指向’A’。(調用strtok則卡死在了這一步)
……以此類推,外循環一次提取一個人的全部信息,內循環從外循環的提取結果中,二次提取個人單項信息。
可以看到strtok_r將原內部指針顯示化,提供了saveptr這個參數。增加了函數的靈活性和安全性。

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