简体   繁体   English

如何在C的2D字符数组中填充字符串?

[英]How to fill strings in a 2D char array of C?

Trying to implement strtok . 试图实现strtok

#include <stdio.h>

char* my_strtok (char* arg_string, const char* arg_delimeter)
{
    char** after_tokenization      = (char**) malloc (sizeof(char) * 1000);
    char*  hold_chars_of_one_group = (char*) malloc (sizeof(char) * strlen(arg_string));

    int j = 0;
    int i = 0;
    int k = 0;

    while (arg_string[i])
    {
        if (arg_string[i] != *arg_delimeter)
        {
            hold_chars_of_one_group[k] = arg_string[i];
            k++;
        }
        else
        {
            after_tokenization[j][0] = hold_chars_of_one_group;

            j++;
            k = 0;
        }
        i++;
    }

    return after_tokenization;
}


int main(void)
{
    char*p = my_strtok ("qwerty,asdf,shizuka,sharma", ",");
    return 0;
}

By putting printfs I can see that seg fault is in this line: 通过放置printfs,我可以看到seg错误在这一行:

after_tokenization[j][0] = hold_chars_of_one_group;

Before crashing j's value is shown to be 2. Sufficient memory has been allocated to both arrays, then what is the way to push values in a 2D char array of C? 在显示j的值崩溃之前,它的值为2。在这两个数组中都分配了足够的内存,那么将值推入C的2D字符数组中的方法是什么?

Why am I getting seg fault over there? 为什么我在那出现段错误? What's the way out? 出路是什么?

after_tokenization[j][0] = hold_chars_of_one_group;

Even if you allocated enough memory for after_tokenization . 即使您为after_tokenization分配了足够的内存。 The pointer at after_tokenization[j] isn't initialized. after_tokenization[j]指针未初始化。 It contains an unspecifed address. 它包含一个未指定的地址。 So when you dereference it by applying the subscript operator [0] , it's undefiend behavior. 因此,当您通过应用下标运算符[0]取消引用它时,这是未定义的行为。

And that is most probably the cause of your crash. 这很可能是导致崩溃的原因。

You need an array of pointers to hold the strings, so it should be: 您需要一个指针数组来保存字符串,因此应该是:

char** after_tokenization      = (char**) malloc (sizeof(char*) * 1000);

and after_tokenization[j][0] is meaningless because after_tokenization[j] is just a pointer, you haven't allocate memory for it. after_tokenization[j][0]是没有意义的,因为after_tokenization[j]只是一个指针,您没有为其分配内存。 Here is the modified version according to your code. 这是根据您的代码修改的版本。

char** my_strtok (char* arg_string, const char* arg_delimeter)
{
    char** after_tokenization      = (char**) malloc (sizeof(char*) * 1000);
    char*  hold_chars_of_one_group = (char*) calloc(strlen(arg_string) + 1, sizeof(char)); // use calloc to fill the memory with bytes of value zero.

    int j = 0;
    int i = 0;
    int k = 0;

    while (arg_string[i])
    {
        if (arg_string[i] != *arg_delimeter)
        {
            hold_chars_of_one_group[k] = arg_string[i];
            k++;
        }
        else
        {
            hold_chars_of_one_group[k] = 0;
            after_tokenization[j] = hold_chars_of_one_group;
            hold_chars_of_one_group += k+1;

            j++;
            k = 0;
        }
        i++;
    }

    // last one
    if (hold_chars_of_one_group[0] != 0) {
        hold_chars_of_one_group[k] = 0;
        after_tokenization[j] = hold_chars_of_one_group;
    }

    /*for (i = 0; i < 10; i++) {
        printf("%s\n", after_tokenization[i]);
    } */


    return after_tokenization;
}

I believe their are some problems with you code: 我相信它们与您的代码有关:

  • You are typecasting return of malloc() . 您正在类型转换malloc()返回。 Their is no need for that in C. Please read this . 他们不需要C语言。请阅读此内容
  • Allocation for after_tokenization is wrong. after_tokenization分配是错误的。 You need to allocate space for char * pointers, not char characters. 您需要为char *指针而不是char字符分配空间。 it needs to be allocated like this: 它需要像这样分配:

     char** after_tokenization = malloc (sizeof(char*) * 1000); 
  • Return of malloc() needs to be checked, as it can return NULL . 需要检查malloc()返回,因为它可以返回NULL

  • This line: 这行:

     after_tokenization[j][0] = hold_chars_of_one_group; 

    is dangerous, as you are not really copying hold_chars_of_one_group into your array. 这很危险,因为您并没有真正将hold_chars_of_one_group复制到阵列中。 You need to malloc() some space for this, then strcpy() it into the array. 您需要为此分配malloc()一些空间,然后将其strcpy()放入数组中。 Their is multiple methods for this. 他们为此有多种方法。

    Your current code just overwrites the address of previous pointers added. 您当前的代码只会覆盖之前添加的指针的地址。 Their also no need for [j][0] , as you only need to copy into a pointer location [j] . 它们也不需要[j][0] ,因为您只需要复制到指针位置[j]

  • strtok() can take multiple delimiters, but your code only handles 1 . strtok()可以使用多个定界符,但是您的代码只能处理1 This isn't really a problem, just something to consider. 这实际上不是问题,只是要考虑的问题。

  • my_strtok() returns char * , but you are returning char ** in this function. my_strtok()返回char * ,但是您在此函数中返回char ** You need to change this to char **my_strtok() . 您需要将其更改为char **my_strtok()

  • You also need to free() any allocated memory at the end. 最后,您还需要free()任何已分配的内存。

These points will help improve your code, and make it functional. 这些要点将有助于改进您的代码并使之起作用。

Here is some example code: 这是一些示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSTR 1000

char **mystrtok(char *arg_string, const char *arg_delimeter);

int main(void) {
    char **result = NULL;

    result = mystrtok("qwerty,asdf,shizuka,sharma", ",");

    /* printing and freeing strings */
    for (size_t i = 0; result[i] != NULL; i++) {
        printf("%s\n", result[i]);
        free(result[i]);
        result[i] = NULL;
    }

    free(result);
    result = NULL;

    return 0;
}

char **mystrtok(char *arg_string, const char *arg_delimeter) {
    char **after_tokenization = NULL;
    char *group_char = NULL;
    size_t arrsize = MAXSTR, slen, count = 0, numstr = 0, delim_flag;

    /* allocation of array, with error checking */
    after_tokenization = malloc(arrsize * sizeof * after_tokenization);
    if (!after_tokenization) {
        printf("Cannot allocate %zu spaces for pointers\n", arrsize);
        exit(EXIT_FAILURE);
    }

    slen = strlen(arg_string);

    /* allocation of buffer, with error checking */
    group_char = malloc(slen+1);
    if (!group_char) {
        printf("Cannot allocate %zu bytes for string\n", slen+1);
        exit(EXIT_FAILURE);
    }

    for (size_t ch = 0; arg_string[ch]; ch++) {
        delim_flag = 0;

        /* loop to handle multiple delimeters */
        for (size_t del = 0; arg_delimeter[del]; del++) {
            if (arg_string[ch] == arg_delimeter[del]) {
                delim_flag = 1;
            }
        }

        /* no delim found, add to buffer */
        if (!delim_flag) {
            group_char[count++] = arg_string[ch];
            group_char[count] = '\0';

        /* only add if delim found and buffer is not NULL */
        } else if (delim_flag && *group_char) {

            /* make space in array */
            after_tokenization[numstr] = malloc(slen+1);
            if (!after_tokenization[numstr]) {
                printf("Cannot allocate %zu bytes for string\n", slen+1);
                exit(EXIT_FAILURE);
            }

            /* copy buffer into array */
            strcpy(after_tokenization[numstr], group_char);

            numstr++;
            count = 0;

            /* clear buffer */
            memset(group_char, '\0', slen+1);
        }
    }

    /* for last string found */
    if (*group_char) {
        after_tokenization[numstr] = malloc(slen+1);
        if (!after_tokenization[numstr]) {
            printf("Cannot allocate %zu bytes for string\n", slen+1);
            exit(EXIT_FAILURE);
        }

        strcpy(after_tokenization[numstr], group_char);
        numstr++;
    }

    /* free buffer, not longer needed */
    free(group_char);

    /* add sentinel, just in case */
    after_tokenization[numstr] = NULL;

    /* return char** at the end */
    return after_tokenization;
}

Note: This is just some code I wrote, and it can be heavily improved. 注意:这只是我编写的一些代码,可以进行大量改进。 It just shows the idea. 它只是说明了这个想法。

fix like this 像这样修复

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char** my_strtok (char* arg_string, const char* arg_delimeter){
    size_t len = strlen(arg_string);
    char **after_tokenization     = malloc(sizeof(char*) * ((len + 1)/2 +1));//max token + 1 (+1 for NULL)
    char *hold_chars_of_one_group = malloc(len + 1);

    int i, j, k;
    i = j = k = 0;

    while (*arg_string){
        if (*arg_string != *arg_delimeter){
            hold_chars_of_one_group[k++] = *arg_string;
        } else  {
            hold_chars_of_one_group[k++] = 0;
            after_tokenization[j++] = &hold_chars_of_one_group[i];
            i = k;
        }
        ++arg_string;
    }
    hold_chars_of_one_group[k] = 0;
    after_tokenization[j++] = &hold_chars_of_one_group[i];
    after_tokenization[j] = NULL;//NULL is terminator

    return after_tokenization;
}

int main(void){
    char **p = my_strtok ("anisha,kaul,shizuka,sharma", ",");
    for(char **temp = p; *temp; ++temp){
        printf ("-%s-\n", *temp);
    }
    free(*p);
    free(p);
    return 0;
}

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

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