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

Function that divides the string with given delimiter

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

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

  1. 计算没有。当时字符串中的字符数包括 1 个定界符(如果 space 是定界符,那么如果连续有 2 个或更多 space 比它计算一个 space 而不是更多。为什么? 那个space是一个内存,用于在每个拆分字符串的末尾添加'\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] != '[=11=]')
    {
        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] != '[=12=]')
    {
        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] = '[=12=]';
        z = 0;
        while (z < k)
        {
            big[y][z] = small[z];
            z++;
        }
        y++;
        free(small);
    }
    big[y][i] = '[=12=]';
    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 *))时,你为中间的指针分配space,big[0]big[N-1],水平数组中右上角的指针.它仍然没有将它们设置为任何东西,也没有为最终字符串保留 space(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] != '[=12=]')
    {
        while (s[i] == c)
            i++;
        k = 0;
        while (s[i] != c)    /* here */
        {
            i++;
            k++;
        }

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

代码中存在多个问题:

  • 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] != '[=10=]')
    {
        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] == '[=11=]')
            break;
        k = 0;
        while (s[i + k] != '[=11=]' && 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] = '[=11=]';
        big[y] = small;
        y++;
    }
    big[y] = NULL;
    return (big);
}

42 咆哮:

Ces conventions de codage (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 return sont infantiles.