目录

0.引言

1.完整代码

2.可变数组的创造

3.可变数组的长度

4.可变数组的写入

5.可变数组的增长

6.可变数组的自动增长

7.可变数组的缺陷

7.1 效率极低

7.2 浪费内存空间

8.总结


0.引言

当我们在使用数组的时候,要提前初始这个数组的大小,所以使用数组时,我们总是提心吊胆害怕出现数组越界的情况,那么利用可变数组就可以轻松解决这个问题了(妈妈再也不用担心我的数组越界了)  本文主要详细介绍如何实现可变数组(创造,写入,增长,自动增长,清空),以及可变数组的缺陷。

【本文出现的任何疑惑或者问题都可以私信博主,一起交流讨论,随时回复!】

1.完整代码

#include<stdio.h>
#include<stdlib.h>typedef struct array{int size;int *array;
}Array;//可变数组的初始创造
Array array_creat(int init_size);//得到可变数组的大小(封装)
int array_size(Array a);//可变数组的写入
void array_write(Array *a,int index,int number);//可变数组的读取
int array_get(Array *a,int index);//可变数组的增大
void array_bigger(Array *a,int more_size);//可变数组的清空
void array_free(Array *a);int main()
{Array a=array_creat(5);int i;for(i=0;i<10;i++){int x;scanf("%d",&x);array_write(&a,i,x);}for(i=0;i<10;i++){printf("%d ",a.array[i]);}array_free(&a);return 0;} Array array_creat(int init_size){Array a;a.size=init_size;a.array=(int*)malloc(sizeof(int)*a.size);return a;}int array_size(Array a){return a.size;}void array_write(Array *a,int index,int number){if((index+1)>a->size){int block_size=20;array_bigger(a,block_size);}a->array[index]=number;}int array_get(Array *a,int index)
{return a->array[index];
}void array_bigger(Array *a,int more_size){int *another_array=(int*)malloc(sizeof(int)*(a->size+more_size));int i;for(i=0;i<a->size;i++){another_array[i]=a->array[i];}free(a->array);a->array=another_array;a->size=a->size+more_size;}void array_free(Array *a){free(a->array);a->array=NULL;a->size=0;}

2.可变数组的创造

首先我们需要定义一个结构,包含你要创造这个可变数组的大小和一个指针(用于储存数据)

typedef struct array{int size;int *array;
}Array;

接下来我们要写一个函数,进行可变数组的初始创造,目的在于给主函数中新定义的Array a

初始的size和动态内存分配指针a->array的空间。

Array array_creat(int init_size){Array a;a.size=init_size;a.array=(int*)malloc(sizeof(int)*a.size);return a;}

这个函数只有一个参数,就是给定size的大小。

int main()
{Array a=array_creat(5);return 0;
}

这样就在主函数中初始化了一个可变数组,这个可变数组的初始大小为5

3.可变数组的长度

这里可能显得多次一举了,因为我们要专门写一个函数去得到我们初始化可变数组的size

int array_size(const Array a)
{return a.size;} 

我们不是直接a.size就可以了吗,为什么还需要一个函数去return a.size?这里其实是对数据的封装(其实就是对数据的一种保护,可能在现在这个程序中看不出来它的作用,但是当在大程序用作是,就避免了很多麻烦)

4.可变数组的写入

前面我们创造了一个大小为5个int的可变数组,也就是给a->array动态分配了五个int空间,那么这个时候我们要将数据写入到这个指针中【具体指针应用可看我的博文《【超详解】浅入指针剖析》】

void array_write(Array *a,int index,int number){a->array[index]=number;}

这个函数有三个参数,一个是Array *a的指针,要把初始化的可变数组已指针的形式传进来进行数据的储存,int index就是储存指针的位置,int number就是你要在这个指针位置储存的数据。

int main()
{array_write(&a,0,10);return 0;
}

就将10这个值写入进可变数组,那么我们就是读取这个数了!

int array_get(Array *a,int index)
{return a->array[index];
}

这里同样做的是封装,而不是直接输出a.array[index]。

实例:

int main()
{
array_write(&a,0,1);
printf("%d",array_get(&a,0));
return 0;
}

output:10

5.可变数组的增长

我们之所以需要可变数组关键就在于要让他发生变化,不让它越界,那么最为关键就在于如何让已经初始化的数组进行增长,而且要保持已经写入的数据不发生改变!那么实现这个函数就需要做三件事情:1.分配一个更大空间给新的指针 2.拷贝原来的数据给新的指针 3.把新创造的指针赋值给原来的指针

void array_bigger(Array *a,int more_size)
{int *next_array=(int*)malloc(sizeof(int)*(a->size+more_size));int i;for(i=0;i<a->size;i++){next_array[i]=a->array[i];}free(a->array);a->array=next_array;a->size=a->size+more_size;} 

这里需要清空原来分配给a->array的空间,同时给定新的a->array和a->size。

6.可变数组的自动增长

现在我们知道了如何增长可变数组,但是还是只是人为的增长,我们一般的数组也可以做到人为增长啊。这里我们就需要让它进行自动增长!我们要实现,当我们要写入的数据位置超过了初始化的数组大小事,程序会帮我自动分配相应的空间大小,这里我们就需要在可变数组的写入函数中进行修改

void array_write(Array *a,int index,int number){if((index+1)>a->size){int block_size=20;int t=index+1;block_size=((t-a->size)/20+1)*block_size;array_bigger(a,block_size);}a->array[index]=number;}

这里定义了一个block_size=20,表明已20为一个单位进行扩增。block_size=((t-a->size)/20+1)*block_size;是确定要扩增多少个block_size。

所以在内存足够的清况下,写入储存数据时就不会存在越界的问题,程序会自动进行数组大小的扩增

int main()
{Array a=array_creat(5);array_write(&a,250,100);printf("%d",array_get(&a,250));return 0;
}

output:100    (没有任何问题,即使初始定义数组大小为5)

7.可变数组的缺陷

7.1 效率极低

每一次可变数组的增长都要进行数据的全部复制,那么假设有几百万个数据,每次增长都重新复制,那在很大程度上降低了程序的效率

7.2 浪费内存空间

如图所示:一开始假设我们Array a可以储存100个int数据,现在要进行增大一个block_size(20个数据),我们可以看出整个内存中还剩160个内存空间,理论上是可行的,但是当我清空a后,要创造一个可以储存120个连续空间的指针,但是已经找不出来这个位置了,也就浪费了160个内存空间位置。那么我们怎么处理这个问题呢?答案是:使用链表!【查看我的博文《一看就懂-c语言单向链表【初阶】》】

8.总结

可变数组的实现,解决了我们一直害怕的越界问题,但是它的缺点也是非常致命的。链表的出现就不仅解决了越界问题,同时还提高了效率,充分利用内存空间。

如果这篇文章对您有一丝丝帮助的话,请帮博文点个关注点个赞!

一看就懂-【c语言】可变数组的实现与缺陷分析相关推荐

  1. 《零基础看得懂的C语言入门教程 》——(八)了解基本数组还不是那么简单

    一.学习目标 了解数组的使用方法 目录 C语言真的很难吗?那是你没看这张图,化整为零轻松学习C语言. 第一篇:(一)脱离学习误区 第二篇:(二)C语言没那么难简单开发带你了解流程 第三篇:(三)轻轻松 ...

  2. 【C语言】数组详解,初学者一看就懂

    你每天都在做很多看起来毫无意义的决定,但某天你的某个决定就能改变你的一生.--<西雅图不眠夜>  目录 什么是C语言数组? 1.一维数组的创建与初始化 1.1数组的创建格式 1.2数组的初 ...

  3. C语言0长度数组(可变数组/柔性数组)详解

    CSDN GitHub C语言0长度数组(可变数组/柔性数组)详解 AderXCoding/language/c/zero_length_array 本作品采用知识共享署名-非商业性使用-相同方式共享 ...

  4. c++ 结构体赋值_《零基础看得懂的C语言入门教程》—(十二)结构体是这么回事

    一.学习目标 了解C语言的结构体的使用方法 了解C语言结构体的结构的赋值 了解多种C语言结构体变量的赋值方法和取值方法 目录 <零基础看得懂的C语言入门教程>--(二)简单带你了解流程 & ...

  5. 搞懂C语言指针,看这篇就够了!

    点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! ID:技术让梦想更伟大 整理:李肖遥 说到指针,估计还是有很多小伙伴都还是云里雾里的 ...

  6. 《零基础看得懂的C++入门教程 》——(8)搞定二维数组与循环嵌套

    一.学习目标 了解二维数组的使用方法 了解循环嵌套的使用方法 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想了解编译原理和学习方法点这 ...

  7. 《零基础看得懂的C++入门教程 》——(7)小数组玩起来

    一.学习目标 了解数组的使用方法 了解一维数组的使用方法 了解一维数组与循环的使用方法 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想 ...

  8. 为什么学习C语言这么久,看的懂代码,做不出题,写不出来项目?

    前言 我看得懂别人的程序,可是我自己却写不出来,我应该怎么办啊? 你了解这些嘛? 你只是能从别人书写的代码知道每一步都做些什么吧? 你明白别人的解题思路吗? 你知道别人为什么要用那样的算法吗? 如果你 ...

  9. C语言,谁都能看得懂的归并排序

    喜欢看排序算法动态效果的,可以看看这个网站 https://visualgo.net/zh/sorting 里面很多算法的动画解释,可以看到算法的排序效果,而且还附带了伪代码的实现过程. 本来想录制几 ...

最新文章

  1. ML之回归预测:以某个数据集为例从0到1深入理解科学预测之回归(实数值评分预测)问题的思路框架
  2. Spring 核心容器类BeanFactory
  3. C# 获取打开的EXCEL中某列的行数
  4. 什么是运行时Runtime、运行时库Runtime Library、运行时环境Runtime environment
  5. 房地产项目动态计划管理系统
  6. SURF算法python实现
  7. Java实现地固坐标与经纬度转换
  8. 什么是脏读、不可重复读、幻读? (数据库相关)
  9. 制作favicon图标
  10. word 尾注后边加致谢
  11. 华盛顿道格拉斯县计划建立区块链创新园区
  12. 锁仓怎么解_[期货知识]期货锁仓后怎么解锁?期货锁仓解锁技巧介绍 - 南方财富网...
  13. 如何录屏?电脑屏幕录制软件哪个好?
  14. 大班线描机器人_大班线描画-有趣的巨人
  15. 抖音数据分析工具pc端_用于分析Windows PC上硬盘空间的四个最佳免费工具
  16. 最好用的文字锁屏APP的使用教程
  17. C# 从做早餐看同步异步
  18. KB/s和Kbps是完全不同的概念
  19. 铁血丹心 歌词粤语转汉语谐音
  20. 搜狗浏览器升级,给“红海”市场“火上浇油”

热门文章

  1. 沙特SASO2927能效与SASO2902的区别
  2. 270. 使用Spinnaker发版及生产环境实践
  3. Photoshop学习(三十四):调整图像的某种颜色
  4. 软考高项笔记 | 项目评估的依据
  5. 安装RHEL7配置本地yum源 -- yum不能安装时,在本地安装,亲测成功
  6. 惠普暗影和幽灵系列电脑无法安装linux系统
  7. 前端开发:JS中的Window对象详解
  8. python操作MongoDB数据库(1)查询
  9. 快过年了,搞笑开启过年模式
  10. 日更计划Day1 USACO Feb BronzeT3