用给定的分隔符分割字符串的函数

问题描述

我有一个名为 ft_split(char const *s,char c)函数,它应该接受字符串和分隔符 char c 并将 s 分成一堆更小的字符串。

这是我尝试解决它的第 3 天或第 4 天,我的方法是:

  1. 计算编号。字符串中当时包含 1 个分隔符的字符数(如果空格是分隔符,那么如果一行中有 2 个或更多空格,则计数为一个空格而不是更多。为什么?该空格是用于添加 '\0' 的内存每个分割字符串的结尾)

  2. 它找到分隔符之间的字符大小 (k) -> malloc 内存 -> 从字符串复制到 malloc -> 从 malloc 复制到 malloc -> 重新开始。

但好吧...函数显示分段错误。调试器显示,在分配“大”内存后,它不会进入 while 循环,而是在退出函数后直接进入 big[y][z] = small[z]。

感谢任何提示

#include "libft.h"
#include <stdlib.h>
int ft_count(char const *s,char c)
{
    int i;
    int j;

    i = 0;
    j = 0;
    while (s[i] != '\0')
    {
        i++;
        if (s[i] == c)
        {
            i++;
            while (s[i] == c)
            {
                i++;
                j++;
            }
        }
    }
    return (i - j);
}
char **ft_split(char const *s,char c)
{
    int i;
    int k;
    int y;
    int z;
    char *small;
    char **big;

    i = 0;
    y = 0;
    if (!(big = (char **)malloc((ft_count(s,c) + 1) * sizeof(char))))
        return (0);
    while (s[i] != '\0')
    {
        while (s[i] == c)
            i++;
        k = 0;
        while (s[i] != c)
        {
            i++;
            k++;
        }
        if (!(small = (char *)malloc(k * sizeof(char) + 1)))
            return (0);
        z = 0;
        while (z < k)
        {
            small[z] = s[i - k + z];
            z++;
        }
        small[k] = '\0';
        z = 0;
        while (z < k)
        {
            big[y][z] = small[z];
            z++;
        }
        y++;
        free(small);
    }
    big[y][i] = '\0';
    return (big);
}
int main()
{
    char a[] = "jestemzzbogiemzalfa";
    ft_split(a,'z');
}

解决方法

我没有完全了解代码在做什么,但是:

你有一个 char **big,它是一个指向字符的指针,所以大概应该指向一个 char * 数组,然后指向字符串。看起来像这样:

[ big (char **) ] ->  [ big[0] (char *)  ][ big[1] (char *) ][ big[2] ... ]
                         |                   [
                         v                   v
                      [ big[0][0] (char) ]  ...
                      [ big[0][1] (char) ]
                      [ big[0][2] (char) ]
                      [ ...              ]

在这里,当您调用 big = malloc(N * sizeof(char *)) 时,您为中间指针分配空间,big[0]big[N-1],即水平数组右上角的指针。它仍然不会将它们设置为任何内容,并且不会为最终字符串(big[0][x] 等)保留空间

相反,你需要做类似的事情

big = malloc(N * sizeof(char *));
for (i = 0; i < N; i++) {
    big[i] = malloc(k);
}

单独为每个最终字符串,使用正确的大小等。或者只是一次性分配一个大区域,然后将其拆分到最终字符串中。

现在,在您的代码中,您似乎从未将任何内容分配给 big[y],因此它们可能是任何内容,这很可能解释了引用 big[y][z] 时的段错误。如果您使用 calloc(),您现在会认为 big[y] 为 NULL,而 malloc() 可能是,也可能不是。


另外,这里:

    while (s[i] != '\0')
    {
        while (s[i] == c)
            i++;
        k = 0;
        while (s[i] != c)    /* here */
        {
            i++;
            k++;
        }

我想知道如果在 while (s[i] != c) 处到达字符串的结尾会发生什么,即如果 s[i] 在那一点是 '\0'?循环可能应该停止,但看起来不像。

,

代码中存在多个问题:

  • ft_count() 函数不正确:在测试分隔符之前增加 i,因此如果字符串以分隔符开头,则数字不正确。您应该计算从分隔符到非分隔符的转换次数:
int ft_count(char const *s,char c)
{
    char last;
    int i;
    int j;

    last = c;
    i = 0;
    j = 0;
    while (s[i] != '\0')
    {
        if (last == c && s[i] != c)
        {
            j++;
        }
        last = s[i];
        i++;
    }
    return j;
}

此外,ft_split() 函数也不正确:

  • big 指针数组分配的内存量无效:您应该将元素数量乘以元素大小,这不是 char 而是 char *。立>
  • 如果字符串以分隔符结尾,则在数组末尾添加一个空字符串。您应该在跳过分隔符后测试空字节。
  • 在扫描项目后的分隔符时,您不会测试空终止符。
  • 您没有将 small 指针存储到 big 指针数组中。而不是将字符串复制到 big[y][...],您应该只设置 big[y] = small 而不是 free(small)

这是修改后的版本:

char **ft_split(char const *s,char c)
{
    int i;
    int k;
    int y;
    int z;
    char *small;
    char **big;

    if (!(big = (char **)malloc((ft_count(s,c) + 1) * sizeof(*big))))
        return (0);
    i = 0;
    y = 0;
    while (42)  // aka 42 for ever :)
    {
        while (s[i] == c)
            i++;
        if (s[i] == '\0')
            break;
        k = 0;
        while (s[i + k] != '\0' && s[i + k] != c)
        {
            k++;
        }
        if (!(small = (char *)malloc((k + 1) * sizeof(char))))
            return (0);
        z = 0;
        while (z < k)
        {
            small[z] = s[i];
            z++;
            i++;
        }
        small[k] = '\0';
        big[y] = small;
        y++;
    }
    big[y] = NULL;
    return (big);
}

42 咆哮:

Ces 规范代码 (la norminette) 不是反生产力! Les boucles for sont plus lisibles et plus sûres que ces while,les casts sur les valeurs de retour de malloc() sont inutiles et confusantes,les parenthèses autour de l'argument de {{1} }}儿子婴儿。