strtok strtok_s & strsep

c 语言下的字符串分割函数:

一、strtok():

原型:char *strtok(char s[], const char *delim);

分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串

strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包涵的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。

strtok函数会破坏被分解字符串的完整,调用前和调用后的s已经不一样了。

一个列子:

#include <iostream>
using namespace std;

int main()
{
	char sentence[]="192.168...9...14";
	cout<<"sentence = "<<sentence<<"\nThe tokens are:\n";
	//char *p;
	char *token=strtok(sentence,".");
	while(token!=NULL){
		
		cout<<token<<" ";
		token=strtok(NULL,".");
	}
        cout<<endl;
	cout<<"at last,sentence = "<<sentence<<endl;
	return 0;
}

当有连续多个分隔符时,都只会分割一次。

输出:

192 168 9 14

192

再看一个例子:

char str1[] = "102.122..164";
	char *c1 = strtok(str1,".1");
	printf("%s\n",c1);
	c1 = strtok(NULL,".1");
	printf("%s\n",c1);
输出:

02
22
以下文档加粗部分的说明。

strtok

<cstring>
char * strtok ( char * str, const char * delimiters );
Split string into tokens
A sequence of calls to this function split str into tokens, which are sequences of contiguous characters separated by any of the characters that are part of delimiters.

On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.

To determine the beginning and the end of a token, the function first scans from the starting location for the first character not contained indelimiters (which becomes thebeginning of the token). And then scans starting from thisbeginning of the token for the first character contained indelimiters, which becomes theend of the token.

This end of the token is automatically replaced by a null-character by the function, and the beginning of the token is returned by the function.

Once the terminating null character of str has been found in a call to strtok, all subsequent calls to this function with a null pointer as the first argument return a null pointer.

The point where the last token was found is kept internally by the function to be used on the next call (particular library implementations are not required to avoid data races).


二、strtok_s 和 strtok_r

strtok()是一个不安全的函数,因为其把剩余的子串存放到一个静态变量里,若多线程同时访问,则会出现错误。

所以,在windows下出现了strtok_s:

char *strtok_s( char *strToken, const char *strDelimit, char **buf);

 

#include <iostream>
using namespace std;

int main()
{
	char sentence[]="192.168...9...14";
	cout<<"sentence = "<<sentence<<"\nThe tokens are:\n";
	char *p;
	char *token=strtok_s(sentence,".",&p);
	while(token!=NULL){
		
		cout<<token<<'\n';
		token=strtok_s(NULL,".",&p);
	}

	cout<<"at last,sentence = "<<sentence<<endl;
	return 0;
}

 在linux下,有strtok_r()函数。

	char *p;
	char str1[] = "102.122..164";
	char *c1 = strtok_r(str1,".1",&p);
	printf("%s\n",c1);
	c1 = strtok_r(NULL,".1",&p);
	printf("%s\n",c1);
输出:

02
22



三、strsep

在linux下,有更快的strsep()函数替代strtok()。

char *strsep(char ** str,const char * del);

c语言:

#include<string.h>
#include<stdio.h>
int main(){
	char str[] = "zcxwhimxwad";
	char *str1 = str;
	char *c = strsep(&str1,"mx");
	printf("%s %s\n",c,str1);//输出zc whimxwad
	c = strsep(&str1,"mx");
	printf("%s %s\n",c,str1);//输出whi xwad	

}


strsep()不需要判断token的开始字符。

	char str[] = "102.168..1....112";
	char *str2 = str;
	char *c = strsep(&str2,".1");
	printf("%s %s\n",c,str2);//输出 02.168..1....112 
	c = strsep(&str2,".1");
	printf("%s %s\n",c,str2);//输出02 168..1....112

输出:

 02.168..1....112
02 168..1....112

//上面的输出显示有问题,可以点view plain查看

应该是

 02.168..1....112  //最前面有一个空格

02 168..1....112 

可见,函数改变了原字符串,所以函数的参数不能是常量字符串。

如:

char  *str = "zcxwhimxwad";

strsep(&str,"mx");

运行时会出现段错误。

还有就是分割时,分隔符的匹配问题,"mx"表示匹配m或x。


总结一下:

strtok(),函数是一个线程不安全的函数,多线程时,windows下可以用strtok_s代替,linux下可以用strtok_r代替。在linux下,有一个更加快速的strsep()函数可以代替strtok.

strtok()函数使用时原字符串变量已被更改,分割成的token的开始字符是不包含在delimiter中的第一个字符。strtok_s和strtok_r和strtok用法相似。

strsep()函数不需要像strtok一样判断开始字符。


 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值