【问题标题】:Function that divides the string with given delimiter用给定的分隔符分割字符串的函数
【发布时间】:2021-05-29 20:59:27
【问题描述】:

我有一个名为 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');
}

【问题讨论】:

  • 任何提示。使用调试器。至少它会立即告诉您触发 seg 故障的确切线路。这是应该收集的第一条信息。还可以使用调试器单步调试代码并在运行时对其进行检查,以查看哪里以及为什么会出现问题。
  • 函数显示分段错误。段错误发生在哪一行代码上?调试器会为您提供该信息。
  • 好吧,看来你不知道如何充分使用调试器。建议您学习一下,因为这将为您节省大量时间。无论如何,问题可能与您的big 分配有关。这不是分配二维数组的正确方法,因此访问可能会导致段错误。请参阅:Correctly allocating multi-dimensional arraysHow do I dynamically allocate a 2d array of chars?
  • bt 给出回溯。其中包括程序停止的当前代码行。
  • p 用于“打印”,例如p yp z 查看索引是否(何时)在访问 big[y][z] 时崩溃。 p big[y] 也可能很有启发性。

标签: c multidimensional-array malloc delimiter


【解决方案1】:

我没有得到代码所做的一切,但是:

你有一个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'?循环应该可能会停止,但它看起来不像。

【讨论】:

  • "或者直接分配一大块区域,然后在最后的字符串中分割。"。但这就是我想要做的。请注意,当我执行“大”malloc 时,我当时不知道我将拥有多少个小字符串。也许0也许20......为什么我为每个子字符串分配多少内存很重要?我认为这里的方法是放置足够的 bythes,以便所有字符串加在一起就可以适合。我不知道不同的方式:/ :(。感谢您的回答。感谢您的努力!
  • @Tony,抱歉,我不知道ft_count() 的意思。但是,如果big 应该包含指向单个单词的指针,那么您需要为那些指针 留出空间。如果你为所有单词分配空间,你仍然不知道每个单词从哪里开始。
  • @Tony,你想拆分jestemzzbogiemzalfa 以便big[0] 指向jestembig[1] 指向bogiem 等等,我是否理解正确?
  • @ikkachu 在每个“小”sring 之后我添加 '\0',这还不够吗?你现在的意思是我为 big[0][z] 分配了所有空间,当我带着下一个单词移动到 big[1][z] 时,我什么都没有?
  • 是的,这正是他们要求我们在任务中执行的操作:分配(使用 malloc(3))并返回通过使用字符 'c' 拆分 's' 获得的字符串数组分隔符。数组必须以 NULL 指针结尾。
【解决方案2】:

代码中存在多个问题:

  • 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 conventions de codeage (la norminette) 这不是反产品! Les boucles forsont 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 returnsont infantiles。

【讨论】:

  • 好吧,一个朋友也帮我解决了这个问题,但我不明白为什么 big[y] = small 直接,为什么每次内存通过后不释放?是不是我们一遍遍地覆盖同一个小malloc?我是这样看的:small(2) = bogiem。小(3)=阿尔法。因此,如果我在 bogiem 之上写 alfa,我将得到 alfaem。我想这是我的困惑。如果我只在里面创建 3 个 submalloc,那么多大的 malloc 知道它总共需要多少内存?
  • @Tony:small = malloc() 分配一个新的内存块并将其地址存储到small,这是一个指针。将此指针存储到数组中只是将指针的值复制到数组元素。下一次迭代将分配另一个块,等等。前一个块没有被覆盖,small 现在指向一个新块。
猜你喜欢
  • 2013-05-03
  • 2021-06-12
  • 2020-07-04
  • 2011-09-12
  • 2017-03-25
  • 1970-01-01
  • 2013-11-24
相关资源
最近更新 更多