如何使用C编程语言编写一个函数来拆分和返回带有分隔符的字符串数组?
char* str = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
str_split(str,',');
Run Code Online (Sandbox Code Playgroud)
hmj*_*mjd 156
您可以使用该strtok()
函数拆分字符串(并指定要使用的分隔符).请注意,strtok()
将修改传递给它的字符串.如果其他地方需要原始字符串,请复制它并将副本传递给strtok()
.
编辑:
示例(注意它不处理连续的分隔符,例如"JAN ,,, FEB,MAR"):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char** str_split(char* a_str, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
int main()
{
char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
char** tokens;
printf("months=[%s]\n\n", months);
tokens = str_split(months, ',');
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("month=[%s]\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./main.exe
months=[JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC]
month=[JAN]
month=[FEB]
month=[MAR]
month=[APR]
month=[MAY]
month=[JUN]
month=[JUL]
month=[AUG]
month=[SEP]
month=[OCT]
month=[NOV]
month=[DEC]
Run Code Online (Sandbox Code Playgroud)
Tyl*_*ler 67
我认为strsep
仍然是最好的工具:
while ((token = strsep(&str, ","))) my_fn(token);
Run Code Online (Sandbox Code Playgroud)
这实际上是一行分割字符串.
额外的括号是一个风格元素,表示我们有意测试赋值的结果,而不是相等运算符==
.
对于该模式的工作,token
并且str
都有型char *
.如果你以字符串文字开头,那么你首先需要复制它:
// More general pattern:
const char *my_str_literal = "JAN,FEB,MAR";
char *token, *str, *tofree;
tofree = str = strdup(my_str_literal); // We own str's memory now.
while ((token = strsep(&str, ","))) my_fn(token);
free(tofree);
Run Code Online (Sandbox Code Playgroud)
如果两个分隔符一起出现str
,则会得到一个token
空字符串的值.str
修改的值是因为遇到的每个分隔符都被零字节覆盖 - 这是另一个复制首先被解析的字符串的好理由.
在评论中,有人建议这strtok
比strsep
因为strtok
更便携更好.Ubuntu和Mac OS X有strsep
; 可以安全地猜测其他unixy系统也能做到.Windows缺乏strsep
,但它有strbrk
这个简短而甜蜜的strsep
替代品:
char *strsep(char **stringp, const char *delim) {
if (*stringp == NULL) { return NULL; }
char *token_start = *stringp;
*stringp = strpbrk(token_start, delim);
if (*stringp) {
**stringp = '\0';
(*stringp)++;
}
return token_start;
}
Run Code Online (Sandbox Code Playgroud)
这是对strsep
vs的一个很好的解释strtok
.可以主观判断利弊; 但是,我认为这是一个明显的标志,strsep
被设计为替代strtok
.
the*_*imp 25
String tokenizer这段代码应该让你朝着正确的方向前进.
int main(void) {
char st[] ="Where there is will, there is a way.";
char *ch;
ch = strtok(st, " ");
while (ch != NULL) {
printf("%s\n", ch);
ch = strtok(NULL, " ,");
}
getch();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
use*_*944 12
下面的方法将为您完成所有工作(内存分配,计算长度).可以在这里找到更多信息和描述 - 实现Java String.split()方法来拆分C字符串
int split (const char *str, char c, char ***arr)
{
int count = 1;
int token_len = 1;
int i = 0;
char *p;
char *t;
p = str;
while (*p != '\0')
{
if (*p == c)
count++;
p++;
}
*arr = (char**) malloc(sizeof(char*) * count);
if (*arr == NULL)
exit(1);
p = str;
while (*p != '\0')
{
if (*p == c)
{
(*arr)[i] = (char*) malloc( sizeof(char) * token_len );
if ((*arr)[i] == NULL)
exit(1);
token_len = 0;
i++;
}
p++;
token_len++;
}
(*arr)[i] = (char*) malloc( sizeof(char) * token_len );
if ((*arr)[i] == NULL)
exit(1);
i = 0;
p = str;
t = ((*arr)[i]);
while (*p != '\0')
{
if (*p != c && *p != '\0')
{
*t = *p;
t++;
}
else
{
*t = '\0';
i++;
t = ((*arr)[i]);
}
p++;
}
return count;
}
Run Code Online (Sandbox Code Playgroud)
如何使用它:
int main (int argc, char ** argv)
{
int i;
char *s = "Hello, this is a test module for the string splitting.";
int c = 0;
char **arr = NULL;
c = split(s, ' ', &arr);
printf("found %d tokens.\n", c);
for (i = 0; i < c; i++)
printf("string #%d: %s\n", i, arr[i]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Here is my two cents:
int split (const char *txt, char delim, char ***tokens)
{
int *tklen, *t, count = 1;
char **arr, *p = (char *) txt;
while (*p != '\0') if (*p++ == delim) count += 1;
t = tklen = calloc (count, sizeof (int));
for (p = (char *) txt; *p != '\0'; p++) *p == delim ? *t++ : (*t)++;
*tokens = arr = malloc (count * sizeof (char *));
t = tklen;
p = *arr++ = calloc (*(t++) + 1, sizeof (char *));
while (*txt != '\0')
{
if (*txt == delim)
{
p = *arr++ = calloc (*(t++) + 1, sizeof (char *));
txt++;
}
else *p++ = *txt++;
}
free (tklen);
return count;
}
Run Code Online (Sandbox Code Playgroud)
Usage:
char **tokens;
int count, i;
const char *str = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
count = split (str, ',', &tokens);
for (i = 0; i < count; i++) printf ("%s\n", tokens[i]);
/* freeing tokens */
for (i = 0; i < count; i++) free (tokens[i]);
free (tokens);
Run Code Online (Sandbox Code Playgroud)