用C语言简单实现一个可变数组

转载:https://blog.csdn.net/melody_1016/article/details/81948809 

我们知道,C语言的数组是固定大小的,尽管可以用一个变量来定义数组大小,但是一旦定义了,在大小在运行过程中无法改变。如果一开始就定义一个容量较大的数组,那么由于不知道实际要存放多少元素,可能会造成空间浪费或者还是不够用。所以,本篇博客,我们就用C语言实现一个可以变大小的数组。

先上代码:

头文件array.h

#ifndef _ARRAY_H_
#define _ARRAY_H_
 
const int BLOCK_SIZE = 2;
typedef struct
{
	int*array;
	int size;
}Array;
 
Array array_creat(int init_size);//创建一个数组
void array_free(Array *a);//回收空间
int  array_size(Array *a);//目前有多少个空间可以用
int*array_at(Array*a, int index);//访问数组当中某个单元:可以读也可以写(即可以做左值也可以做右值)
void array_inflate(Array*a, int more_size);//数组增容
void array_set(Array*a, int index, int value);//向数组中写入东西
 
 
#endif


array.cpp

#include"array.h"
#include<stdio.h>
#include<stdlib.h>
 
//创建一个数组
Array array_creat(int init_size)
{
    Array a;
    a.array = (int*)malloc(sizeof(int)*init_size);
    a.size = init_size;
    return a;
}
 
//回收空间
void array_free(Array *a)
{
    free(a->array);
    a->array = NULL;
    a->size = 0;
}
 
//目前有多少个空间可以用
int  array_size(Array *a)
{
    return a->size;
}
 
//访问数组当中某个单元:可以读也可以写(即可以做左值也可以做右值)
int*array_at(Array*a, int index)
{
    if (index >= a->size)
    {
        array_inflate(a, (index / BLOCK_SIZE + 1)*BLOCK_SIZE - a->size);
    }
    
    return &(a->array[index]);
}
 
//数组增容
void array_inflate(Array*a, int more_size)
{
    int*p = (int*)malloc(sizeof(int)*(a->size + more_size));//新开辟一段空间
    int i;
    //将原空间的内容全部拷贝至新空间
    for (i = 0; i < a->size; i++)
    {
        p[i] = a->array[i];
    }
    //array_free(a);
    free(a->array);
    a->array = p;
    a->size += more_size;
 
}
void array_set(Array*a, int index, int value)
{
    a->array[index] = value;
}
int main()
{
    Array a;
    a=array_creat(3);
    //array_free(&a);
    *array_at(&a, 0) = 10;
    *array_at(&a, 1) = 20;
    *array_at(&a, 2) = 30;
    *array_at(&a, 3) = 40;
    *array_at(&a, 4) = 50;
    *array_at(&a, 5) = 60;
 
    //array_set(&a, 0, 10);
    //array_set(&a, 1, 20);
    //array_set(&a, 2, 30);
 
    //array_inflate(&a, 2);
 
    //array_set(&a, 3, 40);
    //array_set(&a, 4, 50);
    for (int i = 0; i < 4; i++)
    {
        printf("%d ", a.array[i]);
    }
    //printf("%d\n", array_size(&a));
    array_free(&a);
    //Array *pa= array_creat(NULL, 3);
    //pa = array_creat(&a, 3);
    //array_free(&a);
    //array_free(&a);
    system("pause");
    return 0;
}

下面对代码的设计思路和重点部分讲解一下:

一、Array array_creat(int init_size)//创建一个数组,这里返回值为什么是Array的变量本身而不是Array*呢?

如果返回的的是指向结构体的指针,即函数定义为Array* array_creat(Array*a,int init_size),那么在函数内部,应该就是这样

Array* array_creat(Array*a,int init_size)
{
   a->size=init_size;
   a->array=(int*)malloc(sizeof(int)*a->size);
   return a;
}
但是,这里就有一个潜在的风险:如果传进来的a为null,那么直接通过空指针访问它的数据,必然程序崩溃;如果传进来的a已经指向一块开辟好的内存,那么要先free掉原来的空间,再把a指向新空间才可以,用上面的代码,明显会出问题。而如果按照原来的做法(即返回的是Array),则我们可以在main()函数中定义一个Array类型的结构体变量来接收array_creat(int init_size)函数返回的结构体:即Array=array_creat(3);这处理起来就比较简单了。

二、void array_inflate(Array*a, int more_size);//数组增容,具体是怎么进行增容呢?

 

三、BLOCK_SIZE的引入目的?

当初始容量写满后,如果再要写入数据,必须进行增容,我们的 array_inflate函数只单纯负责增容,不进行检测容量的大小;那么如何判断空间已满,需要扩容呢?这里是在array_at函数中进行判断的,因为array_at函数的作用是访问数组单元和写入数值的,可以通过它的参数index与当前size大小比较,判断是否已满,如果原内存已满,则调用array_inflate函数进行扩容。

这里引入BLOCK_SIZE是为了扩容方便。如果写成以下方式,则原内存空间满后,每再写入一个数据,都要重新申请比原来多一个数据大小的空间,再进行数据的拷贝。这样反复的开空间和拷贝数据降低了效率。

int*array_at(Array*a, int index)
{
    if (index >= a->size)
    {
        array_inflate(a, index-a->size+1);//每次扩充一个大小
    }
    return &(a->array[index]);
}
所以我们寻求一种方式,可以每次都扩充固定大小,比如20个,那么原内存空间满(假设原内存空间可以存放100个数据)后,再插入一个数据,即index=100时,系统一次性扩充20个(即新申请120个数据大小),这样后续插入数据时,只要index没有到120,就不用再扩容了。

 

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值