我有这个字符串:"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)
怎么了?
答案 0 :(得分: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
对输入字符串具有破坏性,并且不是线程安全的。
您是否考虑过使用sscanf
家庭?如果你有固定的格式,它会更容易使用。
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]);
}
答案 1 :(得分:0)
请查看strtok
的文档:
对strtok函数的一系列调用将s1指向的字符串分解为a 标记序列,每个标记由指向的字符串中的字符分隔 由s2。序列中的第一个调用具有非null的第一个参数;随后的电话 sequence具有null第一个参数。 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
以避免数据争用并使您的代码可重入。
答案 2 :(得分:0)
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);