c - 动态数组的内存分配
问题描述
我在解决练习时被困在内存分配中。
练习要求:创建一个根据分隔符拆分字符串的函数。第二个参数是唯一的字符分隔符。该函数应返回一个包含分隔符之间的字符串的数组。
例子:
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;
}
它给了我一个错误。有人可以解释我做错了什么吗?
解决方案
对于初学者来说,这个函数声明:
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
!
推荐阅读
- python - Heroku & Discord.py:试图从同一个 Procfile 运行两个机器人
- reactjs - 我如何将已经有信息的功能组件呈现给另一个组件?
- docker - docker keycloak 扩展日志在哪里
- angular - 有没有办法使用更复杂的对象数据源在列而不是行上创建 Angular 动态材料表?
- git - VCS (Git) 与 Bayou 分布式系统之间有什么区别?
- django - Django 内容类型表数据迁移,同时使用旧数据库从 1.6 升级到 2.2
- devops - Docker 容器设置完成,但无法使用 aws 实例从浏览器访问 tomcat 和 webapp
- c++ - 我们可以阻止 std::list 整理内存吗?
- flutter - 智能卡读卡器有什么实现方式吗?
- python - 如何将聊天机器人与预训练的问答模型集成?