首页 > 解决方案 > 动态数组的内存分配

问题描述

我在解决练习时被困在内存分配中。

练习要求:创建一个根据分隔符拆分字符串的函数。第二个参数是唯一的字符分隔符。该函数应返回一个包含分隔符之间的字符串的数组。

例子:

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;
}

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

标签: csplitdynamic-memory-allocationc-stringsfunction-definition

解决方案


对于初学者来说,这个函数声明:

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设置为 value 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。你必须处理这种情况。

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

#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
!

推荐阅读