2010.5.11 22:52更新: 在大猫同学的强烈要求下, 增加了测试代码中动态分配空间的销毁.
2010.5.14 22:46再更新: 上次更新代码之后, 大猫同学指出还是存在内存泄漏问题, 各位同学一定要注意malloc()
与free()
必须成对使用哦~
最近有这么一个需求, split()
函数大家都用过, 将字符串按特定的分隔符 (delimiter) 分割成几个部分, 这在脚本语言中早已司空见惯. 但C/C++中是没有的, 于是就给了我这样闲得蛋疼的人消磨时间的机会, 下面分别是用C和C++的标准库实现的split()
函数.
首先是C语言的实现, 这个是我自己写的, 函数返回一个指向
char*
数组 (也就是字符串数组) 的指针.
#include <string.h>
#include <stdlib.h>
/*
* split - Break a string @s into an array of strings.
* @s: The string to be split.
* @delim: The delimiter.
* @n: The length of the array of strings, created by splitting @s.
*/
char** split(char* s, char delim, int* n)
{
char* p;
char* q;
*n = 1;
p = q = s;
/*
* Calculate the value of @n.
*/
while ((p = strchr(q, delim)) != NULL)
{
++*n;
q = p + 1; // skip the delimiter
}
p = q = s;
char** sep = (char**) malloc(sizeof(char*) * (*n)); // the array of strings
int i;
for (i = 0; i != *n; ++i, q = p + 1)
{
/*
* When there isn't delimiter, put `p' point to the end of @s.
* Same like behavior of strchrnul() library function.
*/
if ((p = strchr(q, delim)) == NULL)
p = s + strlen(s);
int len = p - q;
sep[i] = (char*) malloc(sizeof(char) * (len + 1));
strncpy(sep[i], q, len);
sep[i][len] = '\0';
}
return sep;
}
可以使用下面的代码进行测试:
#include <stdio.h>
#include <stdlib.h>
char** split(char*, char, int*);
int main(int argc, char* argv[])
{
char str[] = ":GFW::is:evil:";
int i, n;
char** sep = split(str, ':', &n);
for (i = 0; i != n; ++i)
printf("%s\n", sep[i]);
for (i = 0; i != n; ++i)
{
free(sep[i]);
sep[i] = NULL;
}
free(sep);
sep = NULL;
return 0;
}
C++实现来自Stack Overflow的
一篇讨论, 我稍微进行了一些修改.
#include <sstream>
#include <vector>
using namespace std;
vector<string> split(const string s, char delim = ' ')
{
vector<string> elems;
istringstream ss(s);
string item;
while (getline(ss, item, delim))
{
elems.push_back(item);
}
if (item == "")
elems.push_back(item);
return elems;
}
代码很简洁, 测试代码就不写了, 大家应该都能看懂. 其实大名鼎鼎的
Boost也实现了
split()
, 但毕竟不是任何时候都能使用Boost.