简体   繁体   English

(C编程)制作像argv这样的char **数组

[英](C Programming) Making a char ** array like argv

In a program I am writing I made a Tokenize struct that says: 在我编写的程序中,我做了一个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;
}

where TokenizeT is defined as: TokenizeT定义为:

struct TokenizerT_ {
    char * input_strng;
    int count;
    char **array[];
};

So what I am trying to do is create smaller tokens out of a large token that I already created. 所以我想做的是从已经创建的大令牌中创建较小的令牌。 I had issues returning an array so I made array part of the TokenizerT struct so I can access it by doing tok->array. 我在返回数组时遇到问题,所以我将数组作为TokenizerT结构的一部分,这样我就可以通过执行tok-> array来访问它。 I am getting no errors when I build the program, but when I try to print the tokens I get issues. 构建程序时没有出现任何错误,但是当我尝试打印令牌时却遇到了问题。

TokenizerT *ans;
TokenizerT *a = Tokenize(tkstr);
char ** ab = a->array;
ans = TKCreate(ab[0]);
printf("%s", ans->input_strng);

TKCreate works because I use it to print argv but when i try to print ab it does not work. TKCreate之所以有效,是因为我使用它来打印argv,但是当我尝试打印ab时它却无法工作。 I figured it would be like argv so work as well. 我认为这就像argv一样工作。 If someone can help me it would be greatl appreciated. 如果有人可以帮助我,将不胜感激。 Thank you. 谢谢。

Creating the Tokenizer 创建分词器

I'm going to go out on a limb, and guess that the intent of: 我要弯腰了,我猜是这样的:

TokenizerT *tok;
*tok->array = malloc(sizeof(TokenizerT));
char * arr = malloc(sizeof(50));

was to dynamically allocate a single TokenizerT with the capacity to contain 49 strings and a NULL endmarker. 动态分配单个TokenizerT ,其容量包含49个字符串和一个NULL结束标记。 arr is not used anywhere in the code, and tok is never given a value; 在代码的任何地方都没有使用arr ,并且从未给tok赋值; it seems to make more sense if the values are each shifted one statement up, and corrected: 如果将每个值上移一个语句并进行更正,则似乎更有意义:

// 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 is not a great name. I would have used tok->argv since you are apparently trying to produce an arg ument v ector, and that's the conventional name for one. In that case, tok->count would probably be tok->argc , but I don't know what your intention for that member is since you never use it.) tok->array是不是一个伟大的名字,我会用tok->argv ,因为你显然是想产生ARG ument v埃克特,这是一个传统的名字。在这种情况下, tok->count可能会是tok->argc ,但我不知道您对该成员的意图是因为您从未使用过它。)

Filling in the argument vector 填写参数向量

strtok will overwrite (some) bytes in the character string it is given, so it is entirely correct to create a copy (here ds ), and your code to do so is correct. strtok将覆盖指定字符串中的(某些)字节,因此创建一个副本(此处为ds )是完全正确的,并且这样做的代码也是正确的。 But note that all of the pointers returned by strtok are pointers to character in the copy . 但是请注意, strtok返回的所有指针都是指向副本中字符的指针。 So when you call free(ds) , you free the storage occupied by all of those tokens, which means that your new freshly-created TokenizerT , which you are just about to return to an unsuspecting caller, is full of dangling pointers. 因此,当您调用free(ds) ,您将释放所有这些令牌占用的存储空间,这意味着您将要返回给毫无戒心的调用者的新创建的TokenizerT充满了悬空的指针。 So that will never do; 这样就永远做不到; you need to avoid freeing those strings until the argument vector is no longer needed. 您需要避免释放这些字符串,直到不再需要参数向量为止。

But that leads to another problem: how will the string be freed? 但这带来了另一个问题:如何释放字符串? You don't save the value of ds , and it is possible that the first token returned by strtok does not start at the beginning of ds . 您没有保存ds的值,并且strtok返回的第一个标记可能不在ds的开头开始。 (That will happen if the first character in the string is a space character.) And if you don't have a pointer to the very beginning of the allocated storage, you cannot free the storage. (如果字符串中的第一个字符是空格字符,则会发生这种情况。)并且如果您没有指向已分配存储区开头的指针,则无法释放该存储区。

The TokenizerT struct TokenizerT结构

char is a character (usually a byte). char是一个字符(通常是一个字节)。 char* is a pointer to a character, which is usually (but not necessarily) a pointer to the beginning of a NUL-terminated string. char*是指向字符的指针,通常(但不一定)是指向以NUL终止的字符串开头的指针。 char** is a pointer to a character pointer , which is usually (but not necessarily) the first character pointer in an array of character pointers. char**是指向字符指针的指针 ,通常(但不一定)是字符指针数组中的第一个字符指针。

So what is char** array[] ? 那么char** array[]什么? (Note the trailing [] ). (请注意结尾的[] )。 "Obviously", it's an array of unspecified length of char** . “很明显”,它是char**长度未指定的数组。 Because the length of the array is not specified, it is an "incomplete type". 由于未指定数组的长度,因此它是“不完整的类型”。 Using an incomplete array type as the last element in a struct is allowed by modern C, but it requires you to know what you're doing. 使用不完整的数组类型在最后一个元素struct是通过现代的C允许的,但它需要你知道自己在做什么。 If you use sizeof(TokenizerT) , you'll end up with the size of the struct without the incomplete type; 如果使用sizeof(TokenizerT) ,则结果将为结构的大小, 类型不完整; that is, as though the size of the array had been 0 (although that's technically illegal). 也就是说,好像数组的大小为0(尽管从技术上讲这是非法的)。

At any rate, that wasn't what you wanted. 无论如何,那不是您想要的。 What you wanted was a simple char** , which is the type of an argument vector. 您想要的是一个简单的char** ,它是参数向量的类型。 (It's not the same as char*[] but both of those pointers can be indexed by an integer i to return the i th string in the vector, so it's probably good enough.) (这是一样char*[]但是这两个指针可以通过整数索引i在矢量返回 i 串,所以它可能不够好。)


That's not all that's wrong with this code, but it's a good start at fixing it. 这段代码并不是所有的问题,但是这是修复它的一个好的开始。 Good luck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM