将char **标记逐步添加到C

时间:2016-03-18 16:44:36

标签: c char

我为这个问题尝试了很多解决方案,但都没有正常工作!

我想将char **数组的值复制到char *。

类型的变量中
char *line;
char **tokens = malloc(....);

所以,我尝试了以下内容:

for(i=0; i < sizeof(tokens); i++)
    strncpy(line, tokens[i], strlen(line));

或者

for(i=0; i < sizeof(tokens); i++)
    strncat(line, tokens[i]);

或者

for(i=0; i < sizeof(tokens); i++)
    memcpy(line, tokens[i], strlen(line));

我的理解是令牌[i]将是char *类型,但是如果我得到错误,我无法理解。

Segmentation fault (core dumped)

如果这些方法不起作用,我该如何进行复制?

任何提示?

char *removesubString(char *path, char **args){
        char *dir;
        int COUNT;
        COUNT = 100;
        char **dirs = malloc(sizeof(char*)*COUNT);
    int i, position;
    for (i = 2; i < sizeof(args); i++) {
        if(args[i] == NULL){
            break;
            }
        dir = strtok(path, PATH_DELIM);
        position = 0;
        while (dir != NULL) {
            if(strcmp(dir, args[i]) == 0){
                dir = strtok(NULL, PATH_DELIM);
                continue;
            }
            dirs[position] = dir;
            position++;
            dir = strtok(NULL, PATH_DELIM);
        }//end of while
        dirs[position] = NULL;
    }//end of for
    char *line;
    line = "";
    for (i = 0; i < position; i++) {
            strncpy(line, dirs[i], strlen(dirs[i]));
    }
    return line;
}

1 个答案:

答案 0 :(得分:0)

弹出关于代码的第一个问题是你的界限是错的:

char *line;
char **tokens = malloc(TOKENS_ARRAY_SIZE);

当你这样做时:

for(i=0; i < sizeof(tokens); i++) {
   …
}

它不会返回已分配内存的大小,而是返回tokens指针本身的已分配内存。来自sizeof manpage

  

返回

类型的对象表示的大小(以字节为单位)

当您在静态矩阵上执行sizeof时,它将返回矩阵的大小,因为这是为其分配的内存量。但是对于动态分配的矩阵,它只返回指针的大小,即如果你这样做:

char array_static[42];
char* array_dyn = malloc(sizeof(char)*42);
printf("sizeof(array_static) = %d\n", sizeof(array_static));
printf("sizeof(array_dyn) = %d\n", sizeof(array_dyn));

它将返回:

sizeof(array_static) = 42
sizeof(array_dyn) = 8

因此,如果动态数组中的项目数小于数组指针的返回大小,则会溢出,并且您将获得段错误。

因此,处理您的情况的正确方法是将动态数组的长度保留在另一个变量中,在设置分配的内存大小时更新它,然后将该值用于迭代。

int tokens_length = 42;
char *line;
char **tokens = malloc(sizeof(char*)*tokens_length);

for(i=0; i < sizeof(tokens_length); i++) {
    …
}

所以在你的情况下,你应该这样做:

// keep somewhere the number of directories that you *can* allocate
int nb_dirs = 100;
char **dirs = malloc(sizeof(char*) * nb_dirs);

…

// keep a pointer on how many directories you've added
int position = 0;
while (dir != NULL) {
    …
    position++;
    // fail loudly if you're adding more directories than you've allocated
    // or you might use realloc() to extend the array's length
    if (position >= nb_dirs) {
        printf("ERROR! Too many directories!");
        // RETURN WITH ERROR!
    }
    …
}
// here you iterate over all the directories you've added
for(i = 0; i <= position; i++){
    // here you can do stuff with dirs, and copy only the length of the dirs element
    strncpy(<TARGET>, dirs[i], strlen(dirs[i]);
}

然后还有另一个你应该考虑的问题:在你的循环中,你正在修改path,作为参数给出,你在strcpy() dirs进入:

strncpy(path, dirs[i], <LENGTH>);

但这没有多大意义,无论你想做什么都不是你写的。

这里,考虑到正确设置了size参数,您将把dirs数组的每个项复制到同一个变量中。所以你最终总是路径指针引用的dirs数组的最后一个值。

但问题是你只有路径指针,但是你知道它在给函数时的分配方式知之甚少。它是如何分配的,以及分配了多少内存?什么“有用”的大小(虽然可以用strlen()猜测一个?)

哦,最后,一旦你完成它们,不要忘记free()你的分配。不要泄漏记忆,这很粗鲁! ☺

编辑:

好吧,这是我能看到的错误的东西,以及一些关于它的评论:

char *removesubString(char *path, char **args){
    char *dir;
    int COUNT = 100;
    char **dirs = malloc(sizeof(char*)*COUNT);
    int i, position;

    /* for both XXX marks below:
     *
     * below, sizeof(args) will return the size of the pointer
     * not the number of items it contains. You *NEED* to pass
     * a "int argc" as parameter to your function, that gives
     * the numbers of items in the array.
     * Think about why you have argc in the main() function construct:
     *      int main(int argc, const char** argv)
     * _OR_ if the args array of strings is _ALWAYS_ terminated
     * by a NULL item, then you should do: */
    // int i = 0;
    // while(args[i] != NULL) {
    //     /* do stuff */
    //     ++i;
    // }

    for (i = 2; i < sizeof(args) /* XXX */; i++) {
        if(args[i] == NULL){ /* XXX */
            break;
        }
        dir = strtok(path, PATH_DELIM);
        position = 0;
        while (dir != NULL) {
            if(strcmp(dir, args[i]) == 0){
                dir = strtok(NULL, PATH_DELIM);
                continue;
            }
            /* because within the function you have no guarantee
             * on the number of tokens within path, if you have
             * more than 100 tokens, you will overflow the dirs array.
             * a good idea would be to test whether position is bigger
             * than or equal to COUNT, and if it is use realloc to
             * extend dirs */

            dirs[position] = dir;
            position++;

            dir = strtok(NULL, PATH_DELIM);

            /* you could avoid having twice the former line 
             * and instead make your loop body being: */
            // while (dir != NULL) {
            //     if(strcmp(dir, args[i]) != 0){
            //         /* TODO: check position vs COUNT and realloc dirs if necessary */
            //         dirs[position] = dir;
            //         ++position;
            //     }
            //     dir = strtok(NULL, PATH_DELIM);
            // }
        }
        dirs[position] = NULL;
    }
    char *line;
    line = ""; /* ← here you allocate line with a string of length 1 */
    for (i = 0; i < position; i++) {
        // so here, you'll write up to the number of characters 
        // within dirs[i], into a string of length one.
        strncpy(line, dirs[i], strlen(dirs[i]));
    }
    /* And even if it was working you'd be assigning the line 
     * variable to a new value at each iteration, ending up doing
     * something equivalent to the following line, but with "position"
     * numbers of iterations: */
    // strncpy(line, dirs[position-1], strlen(dirs[position-1]));

    /* Don't forget to free the instances you've allocated dynamically
     * before leaving the function: */
    // free(dirs);

    /* And finally there's another issue here, you're returning
     * a variable that has been statically allocated above, so that
     * when you'll try to use the pointed instance in the calling
     * context, that variable won't exist anymore. */
    return line;
}

HTH