C标记化并存储到数组中
我有一个文件,我想读取每一行,通过标签标记它,并存储到一个数组中。但事实证明,令牌[0]…令牌[4]指向从strtok()生成的每个字符的地址。因此,每当我在文件的下一行调用strtok时,令牌[0]…令牌[4]都会更改。我如何纠正这个问题?如果我尝试使用C标记化并存储到数组中,c,arrays,pointers,C,Arrays,Pointers,我有一个文件,我想读取每一行,通过标签标记它,并存储到一个数组中。但事实证明,令牌[0]…令牌[4]指向从strtok()生成的每个字符的地址。因此,每当我在文件的下一行调用strtok时,令牌[0]…令牌[4]都会更改。我如何纠正这个问题?如果我尝试使用char-tokens[MAX\u SIZE]而不是char*tokens[MAX\u SIZE],则会发生转换错误,因为strtok返回char* 文件是 20 34 90 10 77 80 12 37 29 63 45
char-tokens[MAX\u SIZE]
而不是char*tokens[MAX\u SIZE]
,则会发生转换错误,因为strtok返回char*
文件是
20 34 90 10 77
80 12 37 29 63
45 21 55 18 46
我的代码是:
FILE *f;
if ((f = fopen("myinput.txt","r")) == NULL) {
perror("Failed to open file:");
return -1;
}
char * line;
size_t len = 0;
char *tokens[MAX_SIZE];
int i = 0;
while (getline(&line, &len, f) !=-1) {
char* lineWithoutNullByte = strtok(line,"\n");
tokens[i]=strtok(lineWithoutNullByte,"\t");
i++;
int x = 1;
while (x){
tokens[i] = strtok(NULL, "\t");
if (tokens[i] == NULL){
x=0;
}else{
i++;
}
}
printf("test: %s %s %s %s %s\n", tokens[0],tokens[1],tokens[2],tokens[3],tokens[4] );
}
预期产量为
test: 20 34 90 10 77
test: 20 34 90 10 77
test: 20 34 90 10 77
但我得到了:
test: 20 34 90 10 77
test: 80 12 37 29 63
test: 45 21 55 18 46
澄清:
这意味着,如果我打印整个令牌
数组,我将获得
45 21 55 18 46
45 21 55 18 46
45 21 55 18 46
您没有正确使用从
strtok
获得的令牌:您获得的令牌来自getline
返回的缓冲区。第一次调用为您提供了一个新的缓冲区;后续调用写入同一缓冲区,因为该行适合分配的空间
因为您将指针存储到该缓冲区中,所以下次将包含新数据的行放入旧空间时,所有指向该地址的令牌都将“看到”新数据。为了避免此问题,您需要在从strtok
获取令牌后立即复制令牌,例如,将它们传递到strdup
:
char *tmp = strtok(NULL, "\t");
if (tmp == NULL) {
x = 0;
tokens[i] = NULL;
} else {
i++;
tokens[i] = strdup(tmp);
}
您还需要strdup
第一个令牌
注意:如果您采用这种方法,则在您的程序完成后,您需要释放
单个令牌。您还需要释放外部while
循环结束时由getline
返回的缓冲区:
free(line);
此外,
strtok
是不可重入的,这意味着它不能在并发环境中使用,甚至不能在嵌套循环中标记字符串。你应该用strtok而不是strtok。因为strtok刚开始生效。我不知道原因,但我曾经遇到过一次这个问题。为什么第一行会重复三次?你得到的与文件相符,不是吗?你看最后第二行,我只打印0到4的令牌。我试图找出问题所在。如果我打印整个令牌数组,它的读数将为45 21 55 18 46 21 55 18 46 21 55 45 21 55 46 21 55 18 1846@LearningC我不知道你在说什么。我想得到一个大小为15的数组,其中包含文件中的每个值。char-tokens[MAX_-size][3]代码>令牌=strtok(…);strcpy(令牌[i],令牌)代码>亲爱的先生,谢谢!现在我明白为什么了。所以只需要复制令牌!我会找到关于斯特托克的。非常感谢如果我不是标准的话,那就不是标准的mistaken@Dabo对的不过,getline
也是如此。aahh没有注意到OP正在使用getline
,+1