动态数组的内存分配

问题描述 投票:0回答:2

在解决练习时,我陷入了内存分配的困境。

运动要求:创建一个根据分隔符分割字符串的函数。第二个参数是唯一的字符分隔符。该函数应返回一个数组,该数组包含在分隔符之间包裹的字符串。

示例:

Input: "abc def gh-!" && "-"
Output: ["abc def gh", "!"]

代码:

#include<stdlib.h>
  typedef struct s_string_array {
    int size;
    char** array;
  } string_array;


string_array* my_split(char* a, char* b) {

  //Memory allocation part:

  string_array*ptr=(string_array*)malloc(sizeof(string_array));
  int count=0;
  for(int i=0;a[i]!='\0';i++)
  {
   if(a[i]==b[0])
   {
    count++;
   }
  }
  ptr->size=count+1;
  ptr->array=malloc(sizeof(char*)*ptr->size);
  int size2=0;
  int q=0;
  for(int i=0;i<ptr->size;i++)
  {
      for(;a[q]!=b[0];q++)
      {
       size2++;
      }
      ptr->array[i]=malloc(sizeof(char)*(size2+2));
      ptr->array[i][size2+1]='\0';
      q+=2;
  }

  //Filling the array:

  int c=0;
  for(int i=0;a[i]!='\0';i++)
  {
    if(a[i]!=b[0]){
     for(int j=i,r=0;a[j]!=b[0];j++,r++)
     {
      ptr->array[c][r]=a[j];
     }
     c++;
    }
  }
  return ptr;
}

这给我一个错误。有人可以解释我在做什么错吗?

c split dynamic-memory-allocation c-strings function-definition
2个回答
0
投票

我认为您的方向错误。当我读到这篇文章时:

该函数应返回包含字符串的数组

它告诉我该函数应将一个char指针返回到以零结尾的char数组(即C样式字符串)。

换句话说,您要返回的是复杂的方法。

类似的事情应该做:

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

char* my_split(const char* str, const char sep)
{
    const char* p = str;
    size_t len = 0;
    size_t words = 1;

    // Count the number of chars to copy and the number of words
    while (*p)
    {
        if (*p == sep) ++words; else ++len;
        ++p;
    }

    if (len == 0)
    {
        char* out = malloc(3);
        assert(out);
        strcpy(out, "[]");
        return out;
    }

    // Calculate required memory
    size_t total =
                    1 +              // termination
                    2 +              // [ and ]
                    2 * words +      // " and " around each word
                    2 * (words-1) +  // the , and space between words
                    len;             // the strings

    char* out = calloc(total, 1);
    assert(out);
    strcpy(out, "[\"");
    size_t index = 2;
    p = str;
    while(*p)
    {
        if (*p == sep)
        {
            // Word finished prepare the next word (if any)
            strcat(out, "\"");
            ++index;
            if (*(p+1))
            {
                strcat(out, ", \"");
                index +=3;
            }
        }
        else
        {
            out[index] = *p;
            ++index;
        }
        ++p;
    }
    strcat(out, "\"]");

    // Verify the malloc size
    assert((total-1) == strlen(out));

    return out;

}

int main()
{
  char* input1 = "abc def gh-!";
  char* output1 = my_split(input1, '-');
  printf("%s\n", output1);
  free(output1);

  char* input2 = "a-b-c-d-e-f-g";
  char* output2 = my_split(input2, '-');
  printf("%s\n", output2);
  free(output2);

  return 0;
}

输出:

["abc def gh", "!"]
["a", "b", "c", "d", "e", "f", "g"]

0
投票

对于初学者,此函数声明

string_array* my_split(char* a, char* b) {

没什么意义。第一个参数应具有限定符const,因为传递的字符串不会在函数中更改,而第二个参数则不应是指针。从函数返回指向string_array类型的对象的指针也是没有意义的。

该函数至少应声明为

string_array my_split( const char *s, char c ) {

此循环

  int count=0;
  for(int i=0;a[i]!='\0';i++)
  {
   if(a[i]==b[0])
   {
    count++;
   }
  }

不计算由字符b[0]分隔的子字符串的数目,因为这样的字符可以彼此跟随而无需中间的其他字符。例如,这个字符串

"---A-"

如果分隔符为"A",则只有一个子字符串'-'

不清楚为什么ptr->size设置为值count+1

因为源字符串可以从单独的字符开始,然后进行此循环

  for(;a[q]!=b[0];q++)
  {
   size2++;
  }

因此将不会迭代此内存分配

  ptr->array[i]=malloc(sizeof(char)*(size2+2));

没有意义。

并且您必须在外部循环中将变量size_t重新初始化为零

  int size2=0;
  int q=0;
  for(int i=0;i<ptr->size;i++)

请注意分配内存的功能可能会失败。那就是他们可以返回NULL。您必须处理这种情况。

这里是一个演示程序,显示了如何实现该功能。返回的结构包含三个数据成员:字符串中siub字符串的总数,提取的子字符串的实际数量以及指向为该子字符串分配的内存的指针。

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

struct substring_array 
{ 
    size_t total;
    size_t actual;
    char **p; 
} split( const char *s, char c )
{
    struct substring_array a = { .total = 0, .actual = 0, .p = NULL };

    //  count the total number of substrings
    for ( const char *t = s; *t; )
    {
        while ( *t == c ) ++t;

        if ( *t )
        {
            ++a.total;
            while ( *++t != '\0' && *t != c );
        }
    }

    //  extract substrings
    int success = 1;
    while ( success && *s )
    {
        while ( *s == c ) ++s;

        if ( *s )
        {
            const char *first = s;

            while ( *++s != '\0' && *s != c );

            size_t len = s - first;

            char *current = malloc( len + 1 );
            success = current != NULL;

            if ( success )
            {
                char **tmp = realloc( a.p, ( a.actual + 1 ) * sizeof( char * )  );

                success = tmp != NULL;

                if ( success )
                {
                    a.p = tmp;
                    strncpy( current, first, len );
                    current[len] = '\0';
                    a.p[a.actual++] = current;
                }
                else
                {
                    free( current );
                }
            }
        }
    }

    return a;
}

int main(void) 
{
    const char *s = "abc def gh-!";
    char c = '-';

    struct substring_array a =split( s, c );

    if ( a.total == a.actual )
    {
        printf( "There were extracted all %zu substrings\n", a.total );
    }
    else
    {
        printf( "There were extracted %zu substrings of total %zu substrings\n", 
                a.actual, a.total );
    }

    for ( size_t i = 0; i < a.actual; i++ ) puts( a.p[i] );

    while ( a.actual != 0 ) free( a.p[--a.actual] );
    free( a.p );

    return 0;
}

程序输出为

There were extracted all 2 substrings
abc def gh
!
© www.soinside.com 2019 - 2024. All rights reserved.