嵌套 while 循环中的 strtok 行为异常
strtok in nested while loops behaves unexpectedly
我有一个看起来像 1,3-5,7,9-11 的字符串,我要通过重复调用 strtok 来标记它,以便输出看起来像:
1
3
5
7
9
11
我的代码如下所示:
#include <stdio.h>
#include <string.h>
void tokenize(char *string){
char *token;
token = strtok (string,"-");
while (token != NULL) {
// ... do some other unrelated stuff ...
printf("\tToken %s\n", token);
token = strtok (NULL, ",");
}
}
int main (int argc,char **argv)
{
char *token;
token = strtok (*(argv+1),",");
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
tokenize(token);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
return 0;
}
但是,当我 运行 代码过早结束时,我得到:
./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 3
但我 expect/want 是这样的:
./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 7
Token 9
Token 11
如果我注释掉显示为 tokenize(temptoken);
的行(换句话说,strtok on ", only),那么输出看起来就像人们期望的那样:
./tokenizer 1,3-5,7,9-11
Token1 1
Token1 3-5
Token1 7
Token1 9-11
所以看起来问题确实出在对已经标记化的字符串的后续 strtok 调用上,所以我尝试将 memcpy 内存指向标记指针,但这并没有真正帮助:
#include <stdio.h>
#include <string.h>
void tokenize(char *string){
char *token;
token = strtok (string,"-");
while (token != NULL) {
printf("\tToken %s\n", token);
token = strtok (NULL, ",");
}
}
int main (int argc,char **argv)
{
char *token;
char *temptoken ;
token = strtok (*(argv+1),",");
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
/* added memcpy */ memcpy(temptoken,token,strlen(token)+1);
tokenize(temptoken);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
return 0;
}
$ ./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 3-5
关于我可以做些什么来修复代码、理解我的误解所在并获得所需输出的任何想法?
您不能使用嵌套 strtok()
,因为它使用一些静态内存来保存调用之间的上下文,以了解正在标记化的字符串中的当前位置。
改用 strtok_r()
,它是 strtok 的可重入版本,没有任何内部状态。
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
/* added memcpy */ memcpy(temptoken,token,strlen(token)+1);
tokenize(temptoken);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
你期待什么。
您正在寻找令牌“,”
然后用你的函数标记它(并打印标记)
然后您再次在子标记化之前打印该标记
并且由于 strtok 具有内部状态而结束。
所以它和你写的完全一样。
您需要:
使用可重入版本 od strtok,
您应该 return 标记化函数中的值以指示是否已找到子标记:如果未找到,则打印标记,如果是,则不打印。
我有一个看起来像 1,3-5,7,9-11 的字符串,我要通过重复调用 strtok 来标记它,以便输出看起来像:
1
3
5
7
9
11
我的代码如下所示:
#include <stdio.h>
#include <string.h>
void tokenize(char *string){
char *token;
token = strtok (string,"-");
while (token != NULL) {
// ... do some other unrelated stuff ...
printf("\tToken %s\n", token);
token = strtok (NULL, ",");
}
}
int main (int argc,char **argv)
{
char *token;
token = strtok (*(argv+1),",");
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
tokenize(token);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
return 0;
}
但是,当我 运行 代码过早结束时,我得到:
./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 3
但我 expect/want 是这样的:
./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 7
Token 9
Token 11
如果我注释掉显示为 tokenize(temptoken);
的行(换句话说,strtok on ", only),那么输出看起来就像人们期望的那样:
./tokenizer 1,3-5,7,9-11
Token1 1
Token1 3-5
Token1 7
Token1 9-11
所以看起来问题确实出在对已经标记化的字符串的后续 strtok 调用上,所以我尝试将 memcpy 内存指向标记指针,但这并没有真正帮助:
#include <stdio.h>
#include <string.h>
void tokenize(char *string){
char *token;
token = strtok (string,"-");
while (token != NULL) {
printf("\tToken %s\n", token);
token = strtok (NULL, ",");
}
}
int main (int argc,char **argv)
{
char *token;
char *temptoken ;
token = strtok (*(argv+1),",");
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
/* added memcpy */ memcpy(temptoken,token,strlen(token)+1);
tokenize(temptoken);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
return 0;
}
$ ./tokenizer 1,3-5,7,9-11
Token1 1
Token 3
Token 5
Token1 3-5
关于我可以做些什么来修复代码、理解我的误解所在并获得所需输出的任何想法?
您不能使用嵌套 strtok()
,因为它使用一些静态内存来保存调用之间的上下文,以了解正在标记化的字符串中的当前位置。
改用 strtok_r()
,它是 strtok 的可重入版本,没有任何内部状态。
while (token != NULL) {
if (strchr(token,45)){ //45 is ASCII for "-".
/* added memcpy */ memcpy(temptoken,token,strlen(token)+1);
tokenize(temptoken);
}
printf("Token1 %s \n", token);
token = strtok (NULL, ",");
}
你期待什么。
您正在寻找令牌“,” 然后用你的函数标记它(并打印标记) 然后您再次在子标记化之前打印该标记 并且由于 strtok 具有内部状态而结束。
所以它和你写的完全一样。
您需要: 使用可重入版本 od strtok,
您应该 return 标记化函数中的值以指示是否已找到子标记:如果未找到,则打印标记,如果是,则不打印。