C语言 字符串分割

1.利用sscaf处理固定长度与分隔符的字符串

 

#define RAW_STRING "aaa,bbb,ccc,ddd"

char szBuf[4][8]= {0}; int  ret  = 0;

ret = sscanf(RAW_STRING,"%[^,],%[^,],%[^,],%[^,]",&szBuf[0],&szBuf[1],&szBuf[2],&szBuf[3]);

 

%[^,] 表示匹配到【,】符号之前的所有字符串

2.利用标准库函数strtok处理长度与分隔符变化的字符串

strtok为不可重用函数线程不安全的标准库函数
原型:extern char *strtok(char *s, char *delim);
功能:分解字符串为一组标记串。s为要分解的字符串,delim为分隔符字符串。

说明:首次调用时,s必须指向要分解的字符串,随后调用要把s设成NULL。
strtok在s中查找包含在delim中的字符并用NULL('\0')来替换,直到找遍整个字符串。
返回指向下一个标记串。当没有标记串时则返回空字符NULL。

#define RAW_STRING "aaa,bbb,ccc,ddd"
char s[64] = {0};
char *token = ",";
char *s_ptr = NULL;
strcpy(s,RAW_STRING);
s_ptr = strtok(s,token);
while(s_ptr)
{
 printf("[%s]\n",s_ptr);
 s_ptr = strtok(NULL,token);
}

 

首次使用src为分割的字符串(绝对不可以是字符串常量,否则修改函数内部修改程序只读代码段会段错误)

若返回非空则代表查找token成功返回首个字符串分段

之后src传NULL值,每次调用此函数会分别返回剩下的字符串分段,当全部分段完成查找并后返回NULL

函数的原理分析

通过每次执行会发现此函数每一次调用进行的操作是
1.查找token
2.将首次出现的token的位置修改为'\0'
3.返回查找的原字符串
此函数内部有一个静态变量保存着每次操作后token位置后的首个字符串起始位置的指针,从而在后面的调用中能以此为基础分割剩余的字符串

由此可见此函数是线程不安全的不可重入函数
当多个线程同时调用时,其函数内部的静态指针变量的值不可确定

windows(VS2008)以上平台有一个安全的函数:

char * __cdecl strtok_s(
 _Inout_opt_z_ char * _Str,
 _In_z_ const char * _Delim,
 _Inout_ _Deref_prepost_opt_z_ char ** _Context
);

 

_Str为原字符串
_Delim为分隔符
_Context为外部传入的二级指针变量用于修改每次操作后token位置后的首个字符串起始位置的指针

将原标准库函数内部的静态指针变量取消从而实现线程可重入

#define RAW_STRING "aaa,bbb,ccc,ddd"

 

char s[64] = {0};
char *token = ",";
char *s_next= NULL,*s_ptr= NULL;
 
strcpy(s,RAW_STRING);
s_ptr = strtok_s(s,token,&s_next);
while(s_ptr)
{
 printf("[%s]\n",s_ptr);
 s_ptr = strtok_s(NULL,token,&s_next);
}

 

GUN GCC下也有一个strtok函数的可重入版本用法同strtok_s
为char *strtok_r(char *str, const char *delim, char **saveptr);

str为要分解的字符串,delim为分隔符字符串。char **saveptr参数是一个指向char *的指针变量,用来在strtok_r内部保存切分时的上下文,以应对连续调用分解相同源字符串。

模拟实现原理(暂不做非法参数的处理)

char* mystrtok_s(char* src,const char* token,char** next)
{
 char *pToken = NULL,*pBegin = NULL;

 

if( !*next )
 {
  return NULL;
 }

 

 pBegin = src ? src : *next;

 

 pToken = strstr(pBegin,token);
 if( pToken )
 {
  *pToken = '\0';
  *next = pToken + 1;
 }
 else
 {
  *next = NULL;
 }

 

 return pBegin;
}

转载于:https://my.oschina.net/mlgb/blog/380660

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值