字符串分割

strtok()函数

char* strtok(char* str, const char* delimiters)

str 是要被分割的字符串,str 将被修改,所以str 不能为字符串常量。

delimiters分割符的集合

#include<stdio.h>
#include<string.h>

int main()
{
    char str[20] = "abc def";
    const char* delimiters = " ";
    char s1[10] = {0};
    char s2[10] = {0};
    
    char* p = strtok(str, delimiters);
    strcpy(s1, p);
    if(p != NULL)
    {
        p = strtok(NULL, delimiters);
        strcpy(s2, p);
    } 
    printf("s1 = %s s2 = %s\n", s1, s2);
    
    system("pause");
    return 0;
}

在这里插入图片描述

分析一波:

第一次调用strtok()函数时,strtok()将会找到第一个分割符的位置,让后将这个分割符替换成NULL,然后返回一个指向a 的指针。也就是相当于返回了字符串abc

第二次调用strtok()函数时,传的参数是(NULL, delimiters),因为第一个参数为NULL,strtok()函数会使用之前存储的字符串,因为strtok()函数内部有个static变量保存了之前使用过的字符串信息。所以strtok()函数是不可重入函数,也既是线程不安全函数。这时候strtok()函数会继续找下一个delimiters,在字符串 abc def 中当然是找不到的,而且遍历到了字符串末尾,所以返回指向 d 的指针。

如果此时再调用strtok(NULL, delimiters)函数,将会返回NULL,因为此时static变量指向了字符串 abc def 的末尾。

如果 delimiters 中的分割符不只一个,那么遇到每个分割符都会进行分割。

strtok_r()函数

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

str 是要被分割的字符串,str 将被修改,所以str 不能为字符串常量。

delimiters分割符的集合

saveptr 是指向分割符后的第一个字符,第一次传入时为NULL

strtok_r()函数实现

char *strtok_r(char *s, const char *delim, char **save_ptr)
{
	char *token;

	if (s == NULL) s = *save_ptr;

	/* Scan leading delimiters.  */
	s += strspn(s, delim);
	if (*s == '\0') return NULL;

	/* Find the end of the token.  */
	token = s;
	s = strpbrk(token, delim);
	if (s == NULL)
		/* This token finishes the string.  */
		*save_ptr = strchr(token, '\0');
	else
	{
		/* Terminate the token and make *SAVE_PTR point past it.  */
		*s = '\0';
		*save_ptr = s + 1;
	}

	return token;
}

代码整体的流程如下:

  1. 判断参数s是否为NULL,如果是NULL就以传递进来的save_ptr作为起始分解位置;若不是NULL,则以s开始切分。
  2. 跳过待分解字符串开始的所有分界符。
  3. 判断当前待分解的位置是否为’\0’,若是则返回NULL;不是则继续。
  4. 保存当前的待分解串的指针token,调用strpbrk在token中找分界符:如果找不到,则将save_ptr赋值为待分解串尾部’\0’所在的位置,token没有发生变化;若找的到则将分界符所在位置赋值为’\0’,token相当于被截断了(提取出来),save_ptr指向分界符的下一位。
  5. 函数的最后(无论找到还是没找到)都将返回。

strtok()函数实现

char* strtok(char* s, const char* delim)
{
	static char* p = NULL;
	return strtok_r(s, delim, &p);
}

来看个例子

char buffer[] = "Fred male 25,John male 62,Anna female 16"; 以空格和逗号为分割符进行分割。

#include<stdio.h>
#include<string.h>

char* strtok_r(char* s, const char* delim, char** save_ptr);

int main()
{
	int 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 (int j = 0; j<in; j++)
	{
		printf(">%s<\n", p[j]);
	}

	system("pause");
	return 0;
}

这个例子中用了两层循环,先将 buffer 在外循环中按照逗号分割,然后在内循环中按照空格分割,将分割好的字符串保存在指针数组 p 中便于打印。
在这里插入图片描述

c++中实现分割字符串

vector<string> splitstr(string& str, const string& delim)
{
	vector<string> result;
	size_t pos1 = str.find_first_not_of(delim, 0);
	size_t pos2 = str.find_first_of(delim, pos1);
	if (pos1 == string::npos || pos2 == string::npos)
	{
		result.push_back(str);
	}
	while (pos1 != string::npos || pos2 != string::npos)
	{
		result.push_back(str.substr(pos1, pos2-pos1));
		pos1 = str.find_first_not_of(delim, pos2);
		pos2 = str.find_first_of(delim, pos1);
	}
	return result;
}

str.find_first_not_of(delime, 0)0 位置开始找到 str 中第一个不属于 delim 中的字符,返回这个字符的位置。

str.find_first_of(delim, pos1)pos1 位置开始找到 str 中第一个属于 delim 中的字符,返回这个字符的位置。

str.substr(pos1, n)pos1 开始,提取 strn 个字符,将这些字符以一个新的 string 返回。

参考:https://www.cnblogs.com/zhouhbing/p/4103916.html

参考:https://www.cnblogs.com/happykoukou/p/5427268.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值