C标记化并存储到数组中

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

我有一个文件,我想读取每一行,通过标签标记它,并存储到一个数组中。但事实证明,令牌[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  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