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

时间:2017-01-22 06:37:20

标签: c arrays pointers

尝试实施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;
}

通过放置printfs我可以看到seg错误在这一行:

after_tokenization[j][0] = hold_chars_of_one_group;

在崩溃之前,j的值显示为2.已经为两个数组分配了足够的内存,那么在C的2D字符数组中推送值的方法是什么?

为什么我在那边遇到段故障?出路是什么?

4 个答案:

答案 0 :(得分:2)

after_tokenization[j][0] = hold_chars_of_one_group;

即使您为after_tokenization分配了足够的内存。 after_tokenization[j]处的指针未初始化。它包含一个未指定的地址。因此,当您通过应用下标运算符[0]取消引用它时,它就是不可取的行为。

这很可能是导致车祸的原因。

答案 1 :(得分:2)

你需要一个指针数组来保存字符串,所以它应该是:

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

after_tokenization[j][0]没有意义,因为after_tokenization[j]只是一个指针,你没有为它分配内存。这是根据您的代码修改后的版本。

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;
}

答案 2 :(得分:1)

我相信他们的代码有些问题:

  • 您正在转发malloc()的回复。他们在C中不需要这样做。请阅读this
  • after_tokenization的分配错误。您需要为char *指针分配空间,而不是char个字符。它需要像这样分配:

    char** after_tokenization = malloc (sizeof(char*) * 1000);
    
  • 需要检查malloc()的返回,因为它可以返回NULL

  • 这一行:

    after_tokenization[j][0] = hold_chars_of_one_group;
    

    很危险,因为您并没有真正将hold_chars_of_one_group复制到阵列中。你需要malloc()一些空间,然后strcpy()进入数组。他们有多种方法。

    您当前的代码只会覆盖添加的先前指针的地址。它们也不需要[j][0],因为您只需要复制到指针位置[j]

  • strtok()可以使用多个分隔符,但您的代码只处理1。这不是一个真正的问题,只需考虑一下。

  • my_strtok()返回char *,但您在此函数中返回char **。您需要将其更改为char **my_strtok()

  • 您还需要free()最后分配的内存。

这些要点有助于改进您的代码并使其正常运行。

以下是一些示例代码:

#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;
}

注意:这只是我编写的一些代码,可以大大改进。它只是表明了这个想法。

答案 3 :(得分:0)

像这样修复

#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;
}