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

我试图标记一个字符串但我需要确切知道两个令牌之间何时没有数据。 例如,当标记下面的字符串“ a,b,c,,,d,e ”时,我需要知道’ d ‘和’ e ‘之间的两个空槽…我无法简单地使用strtok()找到它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前五个元素中,这是不希望的。 我需要每个字符的位置进入数组的特定索引:即如果两个字符之间缺少一个字符,则应按原样记录。

7.21.5.8 strtok函数

关于strtok的标准如下:

[#3]序列中的第一个调用搜索s1指向的字符串,查找s2指向的当前分隔符字符串中未包含的第一个字符。 如果没有找到这样的字符,则s1指向的字符串中没有标记, strtok函数返回空指针。 如果找到这样的字符,则它是第一个标记的开头。

在上面的引用中我们可以读到你不能使用strtok作为你特定问题的解决方案,因为它会将在delims找到的任何连续字符视为单个标记。


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

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

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

如果未找到匹配的字符,则该函数将返回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 : ""); p = strtok_single (NULL, delims); } 

产量

 foo bar  baz biz 

如果这是你想要的,你不能使用strtok() 。 从手册页:

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

因此,在你的例子中它只是从c跳到d

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

最近我一直在寻找同样问题的解决方案,并找到了这个线程。

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

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

正如在这个答案中提到的,你会想要自己实现类似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; } 
  1. 解析(例如,strtok)
  2. 分类
  3. 插入
  4. 根据需要冲洗并重复:)

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