在我写的程序中,我创建了一个Tokenize结构,上面写着:
TokenizerT *Tokenize(TokenizerT *str) {
TokenizerT *tok;
*tok->array = malloc(sizeof(TokenizerT));
char * arr = malloc(sizeof(50));
const char *s = str->input_strng;
int i = 0;
char *ds = malloc(strlen(s) + 1);
strcpy(ds, s);
*tok->array[i] = strtok(ds, " ");
while(*tok->array[i]) {
*tok->array[++i] = strtok(NULL, " ");
}
free(ds);
return tok;
}
其中TokenizeT定义为:
struct TokenizerT_ {
char * input_strng;
int count;
char **array[];
};
所以我要做的就是从我已创建的大型令牌中创建更小的令牌。我有问题返回一个数组,所以我做了TokenizerT结构的数组部分,所以我可以通过dok->数组访问它。我构建程序时没有错误,但是当我尝试打印令牌时,我遇到了问题。
TokenizerT *ans;
TokenizerT *a = Tokenize(tkstr);
char ** ab = a->array;
ans = TKCreate(ab[0]);
printf("%s", ans->input_strng);
TKCreate有效,因为我用它来打印argv但是当我尝试打印ab时它不起作用。我认为它就像argv一样工作。如果有人可以帮助我,我将非常感激。谢谢。
答案 0 :(得分:3)
我要走出困境,并猜测其意图:
TokenizerT *tok;
*tok->array = malloc(sizeof(TokenizerT));
char * arr = malloc(sizeof(50));
是动态分配单个TokenizerT
,其容量包含49个字符串和一个NULL结束标记。代码中的任何位置都不使用arr
,tok
永远不会给出值;如果每个值都被移动一个语句并且更正了,那么似乎更有意义:
// Note: I use 'sizeof *tok' instead of naming the type because that's
// my style; it allows me to easily change the type of the variable
// being assigned to. I leave out the parentheses because
// that makes sure that I don't provide a type.
// Not everyone likes this convention, but it has worked pretty
// well for me over the years. If you prefer, you could just as
// well use sizeof(TokenizerT).
TokenizerT *tok = malloc(sizeof *tok);
// (See the third section of the answer for why this is not *tok->array)
tok->array = malloc(50 * sizeof *tok->array);
(tok->array
不是一个好名字。我会使用tok->argv
因为您显然正在尝试制作 arg ument v ector ,那是一个传统的名字。在这种情况下,tok->count
可能是tok->argc
,但我不知道你对该成员的意图是什么,因为你从来没有使用过它)。
strtok
将覆盖给定字符串中的(某些)字节,因此创建副本(此处为ds
)完全正确,并且您执行此操作的代码是正确的。但请注意,strtok
返回的所有指针都是指向副本中的字符的指针。因此,当您致电free(ds)
时,您可以释放所有这些令牌所占用的存储空间,这意味着您即将返回到毫无戒心的来电者的新创建的TokenizerT
已满晃来晃去的指针。所以永远不会这样做;你需要避免释放这些字符串,直到不再需要参数向量。
但这会导致另一个问题:如何释放字符串?您不能保存ds
的值,strtok
返回的第一个令牌可能不会在ds
的开头处开始。 (如果字符串中的第一个字符是空格字符,则会发生这种情况。)如果您没有指向已分配存储的非常开始的指针,则无法释放存储空间。
char
是一个字符(通常是一个字节)。 char*
是指向字符的指针,该字符通常(但不一定)是指向NUL终止字符串开头的指针。 char**
是指向字符指针的指针,它通常(但不一定)是字符指针数组中的第一个字符指针。
那么char** array[]
是什么? (注意尾随[]
)。 "显然",它是一个未指定长度char**
的数组。因为未指定数组的长度,所以它是一个"不完整的类型"。现代C允许使用不完整的数组类型作为struct
中的最后一个元素,但它需要您知道自己在做什么。如果您使用sizeof(TokenizerT)
,那么您最终会得到结构的大小,而不是不完整的类型;也就是说,好像数组的大小为0(虽然这在技术上是非法的)。
无论如何,那不是你想要的。你想要的是一个简单的char**
,它是一个参数向量的类型。 (它的不与char*[]
相同,但这两个指针都可以用整数i
索引,以返回i th 向量中的字符串,所以它可能已经足够好了。)
这个代码不是所有,但它是修复它的良好开端。祝你好运。