需要知道何时使用strtok()在两个令牌分隔符之间没有数据出现

时间:2012-01-02 22:12:15

标签: c strtok

我正在尝试对字符串进行标记,但我需要确切知道两个标记之间何时没有数据。例如,当标记以下字符串“a,b,c,,,d,e”时,我需要知道“d”和“e”之间的两个空插槽...我无法简单地使用它strtok()。我的尝试如下所示:

char arr_fields[num_of_fields];
char delim[]=",\n";
char *tok;
tok=strtok(line,delim);//line contains the data

for(i=0;i<num_of_fields;i++,tok=strtok(NULL,delim))
{
    if(tok)
        sprintf(arr_fields[i], "%s", tok);
    else
        sprintf(arr_fields[i], "%s", "-");          
}

使用上述示例执行上述代码将字符a,b,c,d,e放入arr_fields的前五个元素中,这是不可取的。我需要每个字符的位置进入数组的特定索引:即如果两个字符之间缺少一个字符,则应按原样记录。

6 个答案:

答案 0 :(得分:13)

7.21.5.8 strtok功能

该标准针对strtok

说明了以下内容
  

[#3]序列中的第一个调用搜索字符串          s1指出第一个不是的字符          包含在s2指向的当前分隔符字符串中。          如果没有找到这样的字符,那么就没有令牌          s1指向的字符串和strtok函数返回          空指针。如果找到这样的角色,那就是          开始第一个令牌。

在上面的引用中,我们可以看到您无法使用strtok作为特定问题的解决方案,因为它会将delims中的任何连续字符视为令牌。


我注定要沉默地哭泣,还是有人可以帮助我?

您可以轻松实现自己想要的strtok版本,请参阅本文末尾的摘要。

strtok_single使用strpbrk (char const* src, const char* delims),它将返回指向 delims 中任何字符的第一个匹配项的指针,该字符在以null结尾的字符串 src中找到

如果找不到匹配的字符,该函数将返回NULL。


<强> strtok_single

char *
strtok_single (char * str, char const * delims)
{
  static char  * src = NULL;
  char  *  p,  * ret = 0;

  if (str != NULL)
    src = str;

  if (src == NULL)
    return NULL;

  if ((p = strpbrk (src, delims)) != NULL) {
    *p  = 0;
    ret = src;
    src = ++p;

  } else if (*src) {
    ret = src;
    src = NULL;
  }

  return ret;
}

样本使用

  char delims[] = ",";
  char data  [] = "foo,bar,,baz,biz";

  char * p    = strtok_single (data, delims);

  while (p) {
    printf ("%s\n", *p ? p : "<empty>");

    p = strtok_single (NULL, delims);
  }

<强>输出

foo
bar
<empty>
baz
biz

答案 1 :(得分:2)

如果这是您想要的,则无法使用strtok()。从手册页:

  

解析后的两个或多个连续分隔符的序列       string被认为是一个单独的分隔符。分隔字符在       字符串的开头或结尾将被忽略。换句话说:       strtok()返回的标记总是非空字符串。

因此,在您的示例中,它只会从c跳转到d

您将不得不手动解析字符串,或者搜索可以让您的生活更轻松的CSV解析库。

答案 2 :(得分:2)

最近我正在寻找解决同一问题的方法并找到了这个帖子。

您可以使用strsep()。 从手册:

  

引入了strsep()函数作为strtok(3)的替代,   因为后者无法处理空场。

答案 3 :(得分:1)

this answer中所述,您需要自己实现strtok之类的内容。我更喜欢使用strcspn(而不是strpbrk),因为它允许更少的if语句:

char arr_fields[num_of_fields];
char delim[]=",\n";
char *tok;

int current_token= 0;
int token_length;
for (i = 0; i < num_of_fields; i++, token_length = strcspn(line + current_token,delim))
{
    if(token_length)
        sprintf(arr_fields[i], "%.*s", token_length, line + current_token);
    else
        sprintf(arr_fields[i], "%s", "-");
    current_token += token_length;
}

答案 4 :(得分:0)

  1. Parse(例如,strtok)
  2. 排序
  3. 插入
  4. 根据需要冲洗并重复:)

答案 5 :(得分:0)

您可以尝试使用strchr找出,符号的位置。将您的字符串标记为您找到的标记(使用memcpystrncpy),然后再次使用strchr。您将能够看到两个或多个逗号是否以这种方式彼此相邻(strchr将返回其减法将等于1的数字)并且您可以编写if语句来处理该情况。