如何在C中创建一个函数,允许我将基于分隔符的字符串拆分为数组?

时间:2015-02-11 20:14:14

标签: c arrays string pointers realloc

我想在C中创建一个函数,这样我就可以将函数传递给一个字符串和一个分隔符,然后它会返回一个数组,其中字符串的部分基于分隔符分开。通常用于将句子分成单词。

例如:"hello world foo" - > ["hello", "world", "foo"]

但是,我是C的新手,很多指针都让我感到困惑。我得到了一个主要来自this question的答案,但它是内联的,所以当我尝试将它分成一个函数时,指针的后勤工作让我感到困惑:

这是我到目前为止所做的:

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

void split_string(char string[], char *delimiter, char ***result) {
    char *p = strtok(string, delimiter);
    int i, num_spaces = 0;

    while (p != NULL) {
        num_spaces++;
        &result = realloc(&result, sizeof(char *) * num_spaces);

        if (&result == NULL) {
            printf("Memory reallocation failed.");
            exit(-1);
        }

        &result[num_spaces - 1] = p;

        p = strtok(NULL, " ");
    }

    // Add the null pointer to the end of our array
    &result = realloc(split_array, sizeof(char *) * num_spaces + 1);
    &result[num_spaces] = 0;

    for (i = 0; i < num_spaces; i++) {
        printf("%s\n", &result[i]);
    }

    free(&result);
} 

int main(int argc, char *argv[]) {
    char str[] = "hello world 1 foo";
    char **split_array = NULL;

    split_string(str, " ", &split_array);

    return 0;
}

它的要点是我有一个接受字符串的函数,接受分隔符并接受指向保存结果的位置的指针。然后它构造结果。结果的变量从NULL开始,没有内存,但我会根据需要逐步重新分配内存。

但我对指针感到困惑,就像我说的那样。我知道我的结果是char **类型的字符串类型char *,并且有很多这样的字符串,所以你需要指向每个字符串,但是我应该传递位置< / {>那个char **到新函数,对吧,它变成了char ***?当我尝试使用&访问它时虽然它似乎不喜欢它。

我觉得我在这里缺少一些基本的东西,我真的很感激能够深入了解代码出了什么问题。

1 个答案:

答案 0 :(得分:3)

您将解除引用与寻址混淆(完全相反)。顺便说一句,我无法在函数中的任何位置找到split_array,因为它在main中已经失效。即使您的解除引用和寻址正确,这仍然会有其他问题。

我相当确定你是否正在尝试这样做:

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

void split_string(char string[], const char *delimiter, char ***result)
{
    char *p = strtok(string, delimiter);
    void *tmp = NULL;
    int count=0;

    *result = NULL;

    while (p != NULL)
    {
        tmp = realloc(*result, (count+1)*sizeof **result);
        if (tmp)
        {
            *result = tmp;
            (*result)[count++] = p;
        }
        else
        {   // failed to expand
            perror("Failed to expand result array");
            exit(EXIT_FAILURE);
        }

        p = strtok(NULL, delimiter);
    }

    // add null pointer
    tmp = realloc(*result, (count+1)*sizeof(**result));
    if (tmp)
    {
        *result = tmp;
        (*result)[count] = NULL;
    }
    else
    {
        perror("Failed to expand result array");
        exit(EXIT_FAILURE);
    }
}

int main()
{
    char str[] = "hello world 1 foo", **toks = NULL;
    char **it;

    split_string(str, " ", &toks);

    for (it = toks; *it; ++it)
        printf("%s\n", *it);
    free(toks);
}

<强>输出

hello
world
1
foo

老实说,如果使用函数结果而不是输入/输出参数,这将更清晰,但你选择后者,所以你去。

祝你好运。