C令牌化并存储到数组中
我有一个文件,我想读取每一行,通过制表符标记它并存储到一个数组中。 但事实certificate,token [0] .. token [4]指向由strtok()产生的每个char的地址。 所以当我在文件的下一行调用strtok时,token [0] … token [4]会改变。 我该如何纠正? 如果我尝试使用char tokens[MAX_SIZE]
而不是char* tokens[MAX_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
澄清:这意味着,如果我打印整个tokens
数组,我将会得到
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); }
您还需要限制第一个令牌。
注意:如果采用这种方法,一旦程序完成,您将需要free
单个令牌。 您还需要在外部while
循环结束时释放getline
返回的缓冲区:
free(line);
另外, strtok
是不可重入的,这意味着它不能在并发环境中使用,甚至不能在嵌套循环中标记化字符串。 你应该使用strtok_r
代替。
您应该使用strtok_r而不是strtok。 因为strtok第一次才有效。 我不知道原因,但我曾经遇到过这个问题。