在c中将长动态字符串拆分为字符串数组

Posted

技术标签:

【中文标题】在c中将长动态字符串拆分为字符串数组【英文标题】:splitting a long dynamic string into an array of strings in c 【发布时间】:2022-01-21 02:47:08 【问题描述】:

我对 C 很陌生,可以弄清楚为什么这个函数不能始终如一地工作:

char **splitString(char *string) 
    char *token = strtok(string, ","), **finalValue = NULL, **temp = NULL;
    size_t wordIndex = 0;
    while (token != NULL) 
        temp = realloc(finalValue, sizeof(char *));
        if (!temp) 
            freeArray(finalValue);
            finalValue = NULL;
            break;
        
        temp[wordIndex] = malloc((strlen(token)+1)*sizeof(char));
        if (temp[wordIndex] == NULL) 
            freeArray(finalValue);
            finalValue = NULL;
            break;
        
        strcpy(temp[wordIndex], token);
        printf("%s\n", temp[wordIndex]);
        finalValue = temp;
        printf("%s\n", finalValue[wordIndex]);
        wordIndex++;
        token = strtok(NULL, ",");
    
    return finalValue;

它接收一个用逗号分隔的字符串,它应该将它们分成不同的字符串,所有这些字符串都是通过malloc/realloc创建的。

【问题讨论】:

temp = realloc(finalValue, sizeof(char*)); 为单个指针分配内存。有什么意义? idk 我必须从原始字符串中创建多少个字符串,所以每次迭代时,我都会为另一个字符串创建一个位置 【参考方案1】:

问题就在这里:temp = realloc(finalValue, sizeof(char *)); 为单个指针重新分配。你应该写:

temp = realloc(finalValue, (wordIndex + 2) * sizeof(char *));

您还应该在finalValue 数组的末尾设置一个NULL 指针,以标记该数组的末尾,因为该函数不会以任何其他方式返回条目数。

另请注意,当realloc()malloc() 失败时,分配的字符串不会被释放。

此外,您不应使用strtok(),因为它会修改源字符串。建议使用strspn()strcspn() 或手动测试和strndup() 的替代方法。

最后,strtok() 有另一个可能适得其反的缺点:它将任何分隔符序列视为单个分隔符,并且不会产生空标记。如果您使用空格作为分隔符,这很好,但对于 "," 可能不正确,您可能希望 "a,,c" 产生 3 个标记:"a""""c"

这是一个可以处理空令牌的修改版本:

char **splitString(const char *string) 
    const char *p0, *p0;
    size_t i = 0, n = 1;
    char **array;

    for (p = string; *p; p++) 
        if (*p == ',')
            n++;
    
    array = calloc(sizeof(*array), n + 1);
    if (array != NULL) 
        array[n] = NULL; /* set a null pointer at the end of the array */
        for (p = p0 = string, i = 0; i < n;) 
            if (*p == ',' || *p == '\0') 
                if ((array[i++] = strndup(p0, p - p0)) == NULL) 
                    /* allocation failure: free allocated strings and array */
                    while (i --> 0)
                        free(array[i]);
                    free(array);
                    array = NULL;
                    break;
                
                if (*p == ',')
                    p0 = ++p;
                else
                    p0 = p;
             else 
                p++;
            
        
    
    return array;

strndup() 是许多系统上可用的 POSIX 函数,它将成为 C 标准下一版本的一部分。如果它在您的目标上不可用,这里有一个简单的实现:

char *strndup(const char *s, size_t n) 
    char *p;
    size_t i;
    for (i = 0; i < n && s[i]; i++)
        continue;
    p = malloc(i + 1);
    if (p) 
        memcpy(p, s, i);
        p[i] = '\0';
    
    return p;

【讨论】:

以上是关于在c中将长动态字符串拆分为字符串数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中将数字字符串拆分为数组? [复制]

在 Swift 中将字符串拆分为数组?

如何在 C++ 中将字符串拆分为数组

在c ++中将单词拆分为字母? [关闭]

如何在 Bash 中将字符串拆分为多行?

在 C# 中将字符串拆分为字符串数组列表