【问题标题】:String tokenizing problems字符串标记问题
【发布时间】:2014-04-29 13:00:51
【问题描述】:

我有这个字符串:"Alaska:(3,4)",我想要"Alaska""3""4" 子字符串。但我有一个问题。

cityName = strtok(str , ":");
printf("name : %s\n",cityName);
temp = strtok(NULL , "(");
printf("%s\n",temp);
temp = strtok(NULL , ",");
printf("%s\n",temp);
temp = strtok(NULL, ")");
printf("%s\n",temp);

对于此代码,我得到以下输出:

name : Alaska
3,4)
(null)
(null)

怎么了?

【问题讨论】:

  • +1 首次提问明确说明的问题、提供的代码、输入、输出和所需的输出。可悲的是很少见。

标签: c string tokenize


【解决方案1】:

您的实现不起作用的原因是因为strtok 在第二次调用后已将字符串识别为完全解析(因为在第一个标记之前没有找到任何内容)。您需要在第二次调用后重新开始解析。

void bar(char * str) {
    char * cityName, *temp;
    cityName = strtok(str , ":");
    printf("name : %s\n",cityName);
    temp = strtok(NULL , "(");
    printf("%s\n",temp);
    temp = strtok(temp , ","); // restart parsing here
    printf("%s\n",temp);
    temp = strtok(NULL, ")");
    printf("%s\n",temp);
}

请注意,strtok 对输入字符串具有破坏性,并且不是线程安全的。

你考虑过使用sscanffamily吗?如果你有固定的格式,它会更容易使用。

void foo(char * str) {
    char city[32], num[2][32];
    sscanf(str, "%[^:]:(%[^,],%[^)])", city, num[0], num[1]);
    printf("%s\n%s\n%s\n", city, num[0], num[1]);
}

【讨论】:

  • 这如何回答这个问题?
【解决方案2】:

请查看strtok 的文档:

对 strtok 函数的一系列调用将 s1 指向的字符串分解为 标记序列,每个标记由指向的字符串中的一个字符分隔 通过 s2。序列中的第一个调用有一个非空的第一个参数;中的后续调用 序列的第一个参数为空。 s2 指向的分隔符字符串可能是 因呼叫而异。
序列中的第一个调用在 s1 指向的字符串中搜索第一个字符 不包含在 s2 指向的当前分隔符字符串中。如果没有这样的字符 找到了,那么s1和strtok函数所指向的字符串中就没有记号了 返回一个空指针。如果找到这样的字符,它就是第一个标记的开始。
然后 strtok 函数从那里搜索包含在 当前分隔符字符串。如果没有找到这样的字符,则当前标记扩展到 s1 指向的字符串的结尾,随后搜索令牌将返回 null 指针。如果找到这样的字符,它将被一个空字符覆盖,这 终止当前令牌。 strtok 函数保存指向以下内容的指针 字符,下一次搜索令牌将从该字符开始。

简而言之,strtok 搜索不在分隔符中的第一个字符作为序列的开头,然后在分隔符中搜索第一个字符作为序列的结尾。
这意味着您对strtok 的最后两次调用返回NULL,因此printf 调用是未定义行为,任何事情都可能发生。

最好使用sscanf 或滚动您自己的解析器(可能不再需要)。

如果您想继续使用strtok,请更正您的分隔符并仅尝试获取三个标记:

cityName = strtok(str , ":");
printf("name : %s\n",cityName);
temp = strtok(NULL , "(,)");
printf("%s\n",temp);
temp = strtok(NULL , "(,)");
printf("%s\n",temp);

不过,请考虑至少转移到 strtok_s 以避免数据争用并使您的代码可重入。

【讨论】:

    【解决方案3】:

    strtok(3) 不喜欢空分隔符。你可以访问strsep(3)

    char str[] = "Alaska:(3,4)";
    char *p = str;
    char *temp;
    char *cityName = strsep(&p , ":");
    printf("name : %s\n",cityName);
    temp = strsep(&p , "(");
    printf("%s\n",temp);
    temp = strsep(&p , ",");
    printf("%s\n",temp);
    temp = strsep(&p, ")");
    printf("%s\n",temp);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多