C语言 字符串分割
博客专区 > NDSM 的博客 > 博客详情
C语言 字符串分割
NDSM 发表于3年前
C语言 字符串分割
  • 发表于 3年前
  • 阅读 110
  • 收藏 1
  • 点赞 0
  • 评论 0
摘要: 不管是Java的StringTokenizer还是python的split都是处理分割字符串的利器。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;
}
标签: strtok
共有 人打赏支持
粉丝 13
博文 47
码字总数 24990
×
NDSM
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: