C语言动态数组

更新时间:2025-05-12 23:43:19 阅读: 评论:0

C语言动态数组

动态数组是指在声明时没有确定数组大小的数组,即忽略方括弧中的下标;当要用它时,可随时用ReDim语句(C语言中用malloc语句)重新指出数组的大小。使用动态数组的优点是可以根据用户需要,有效利用存储空间。

基本介绍

中文名:C语言动态数组 释义:相对于静态数组而言 根据:随程式需要而重新指定大小 定义:声明时没有确定数组大小的数组

词目释义

动态数组,是相对于静态数组而言。静态数组的长度是预先定义好的,在整个程式中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程式需要而重新指定大小。动态数组的记忆体空间是从堆(heap)上分配(即动态分配)的。是通过执行代码而为其分配存储空间。当程式执行到这些语句时,才为其分配。程式设计师自己负责释放记忆体。(欲详细了解堆请见堆叠)

为什幺要使用动态数组?

在实际的编程中,往往会发生这种情况,即所需的记忆体空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些记忆体管理函式,这些记忆体管理函式结合指针可以按需要动态地分配记忆体空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用记忆体资源提供了手段。

动态数组与静态数组的对比

对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!对于动态数组,其创建麻烦,使用完必须由程式设计师自己释放,否则严重会引起记忆体泄露。但其使用非常灵活,能根据程式需要动态分配大小。如何构建动态数组

遵循原则

申请的时候从外层往里层,逐层申请;释放的时候从里层往外层,逐层释放。

构建所需指针

对于构建一维动态数组,需要一维指针;对于二维,则需要一维,二维指针;三维需要一,二,三维指针;依此类推。

构建所需函式

函式原型 返 回 功能说明 void *malloc(unsigned int size); 成功:返回所开闢
空间首地址  失败:返回空指针 向系统申请
size位元组的
堆空间 void *calloc(unsigned int num,  unsigned int size); 成功:返回所开闢
空间首地址  失败:返回空指针 按类型申请
num个size字
节的堆空间 void free(void *p); 无返回值 释放p指向
的堆空间 void *realloc(void *p,unsigned int  size); 成功:返回新开闢
空间首地址  失败:返回空指针 将p指向的
堆空间变为
size

说明:

(1)规定为void *类型,这并不是说该函式调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。可以用强制转换的方法将其转换为别的类型。例如:double*pd=NULL; pd=(double *)calloc(10,sizeof(double));  表示将向系统申请10个连续的double类型的存储空间,并用指针pd指向这个连续的空间的首地址。并且用(double)对calloc( )的返回类型进行转换,以便把double类型数据的地址赋值给指针pd。(2)使用sizeof的目的是用来计算一种类型的占有的位元组数,以便适合不同的编译器。(3)由于动态分配不一定成功,为此要附加一段异常处理程式,不致程式运行停止,使用户不知所措。通常採用这样的异常处理程式段:if(p==NULL) /* 或者if(!p)*/ { printf("动态申请记忆体失败!n"); exit(1); //异常退出 }(4)这四个函式头档案均包含在<stdlib.h>中。(5)分配的堆空间是没有名字的 只能通过返回的指针找到它。(6)绝不能对非动态分配存储块使用free。也不能对同一块记忆体区同时用free释放两次。如:free(p);free(p);(7)调用 free() 时, 传入指针指向的记忆体被释放, 但调用函式的指针值可能保持不变, 因为p是作为形参而传递给了函式。严格的讲, 被释放的指针值是无效的, 因为它已不再指向所申请的记忆体区。这时对它的任何使用便可能会可带来问题。malloc与calloc的区别对于用malloc分配的记忆体区间,如果原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分记忆体空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,使用malloc()函式的程式开始时(记忆体空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题,因此在使用它之前必须先进行初始化(可用memset函式对其初始化为0),但调用calloc()函式分配到的空间在分配时就已经被初始化为0了。当你在calloc()函式和malloc()函式之间作选择时,你需考虑是否要初始化所分配的记忆体空间,从而来选择相应的函式。

具体构建方法

以三维整型数组array[n1][n2][n3]为例。先遵循从外层到里层,逐层申请的原则:最外层指针是array,它是个三维指针,所指向的是array[],其为二维指针。所以给array申请记忆体应:array=(int***)calloc(n1,sizeof(int**));次层指针是array[],它是个二维指针,所指向的是array[][],其为一维指针。所以给array[]申请记忆体应:for(i=0;i<n1;i++){array[i]=(int**)calloc(n2,sizeof(int*));}最内层指针是array[][],它是个一维指针,所指向的是array[][][],其是个整型常量。所以给array[][]申请记忆体应:for(i=0;i<n1;i++){for(j=0;j<n2;j++){array[i][j]=(int*)calloc(n3,sizeof(int));}
}当然,你可以把它们整合在一起为:int i,j,k;int n1,n2,n3;int ***array;scanf("%d%d%d",&n1,&n2,&n3);array=(int***)calloc(n1,sizeof(int**));for(i=0;i<n1;i++){array[i]=(int**)calloc(n2,sizeof(int*));for(j=0;j<n2;j++){array[i][j]=(int*)calloc(n3,sizeof(int));for(k=0;k<n3;k++){array[i][j][k]=i+j+k+1;}}}最后不要忘了释放这些记忆体,这要遵循释放的时候从里层往外层,逐层释放的原则。分析过程可参考上面的解答,这里不再赘述。只给出代码吧:for(i=0;i<n1;i++){for(j=0;j<n2;j++){free(array[i][j]);//释放第三维指针}}for(i=0;i<n1;i++){free(array[i]);//释放第二维指针}free(array);//释放第一维指针其余维的如四维创建过程大同小异,这里不再赘述。

基础概念

C#集合、C#动态数组的概念之集合,什幺是集合呢?集合就如同数组,用来存储和管理一组特定类型的数据对象,除了基本的数据处理功能,集合直接提供了各种数据结构及算法的实现,如伫列、鍊表、排序等,可以让你轻易地完成複杂的数据操作。在使用数组和集合时要先加入system.collections命名空间,它提供了支持各种类型集合的接口及类。集合本身上也是一种类型,基本上可以将其作为用来存储一组数据对象的容器,由于c#面向对象的特性,管理数据对象的集契约样被实现成为对象,而存储在集合中的数据对象则被称为集合元素。这里提到了接口这个概念,它也是面向对象编程进化的重要标準,我们在这里不做过多的讲解,先注重学习集合中的对象及其使用就可以了,下面我们来学习第一种集合:C#集合、C#动态数组的概念之C#动态数组ArrayList.ArrayList 类提供了继承了IList接口。什幺是继承呢?这也是面向对象语言的重要特点之一,现在你们先把它理解为,如果一个对象继承了类或接口,那幺它也具有了这个类和接口中的方法、属性,可以用这些继承的方法和属性来做相应的操作,比如:数组增加元素没有Add()方法,但是动态数组ArrayList继承了一个增加元素有Add()方法的接口,那幺当它要增加元素的时候,不仅可以用索引,也可以用继承下来的Add()方法了。随着学习的深入,我会给大家再具体讲解继承的概念和使用继承的好处。那幺下面让我们来看看动态数组所继承的这个接口IList它有什幺特性呢?
C#动态数组之 Ilist接口:定义了利用索引访问集合对象的方法,还继承了ICollection和IEnumerable接口,除实现了接口原有的方法成员外,其本身也定义多个专门的方法成员,例如新增、移除、在指定位置插入元素或是返回特定元素在集合中所在的位置索引,这些方法主要为集合对象提供类似数组的元素访问功能。C#动态数组之ILsit接口成员:add、insert、RemoveAt、Remove、contains、Clear、indexof方法,它最大的特色在于提供类似数组索引的访问机制。C#集合、C#动态数组的概念的基本情况就向你介绍到这里,希望对你了解和学习C#集合、C#动态数组的概念有所帮助。

必看知识

由于百科里贴的代码每行前都会有许多中文空格,造成直接複製贴上到编译器上编译时会出现许多错误。(除非自己手工把代码前的空格全删掉)所以我特地把代码贴到了扩展资料那,要的话去那拿吧。

构建实例

一维

#include <stdio.h>#include <stdlib.h>int main(){int n1,i;int *array;puts("输入一维长度:");scanf("%d",&n1);array=(int*)malloc(n1*sizeof(int));//第一维for(i=0;i<n1;i++){array[i]=i+1;printf("%dt",array[i]);}free(array);//释放第一维指针return 0;}

二维

#include <stdlib.h>#include <stdio.h>int main(){int n1,n2;int **array,i,j;puts("输入一维长度:");scanf("%d",&n1);puts("输入二维长度:");scanf("%d",&n2);array=(int**)malloc(n1*sizeof(int*)); //第一维for(i=0;i<n1; i++){array[i]=(int*)malloc(n2* sizeof(int));//第二维
for(j=0;j<n2;j++){array[i][j]=i+j+1;printf("%dt",array[i][j]);}puts("");}for(i=0;i<n1;i++){free(array[i]);//释放第二维指针}free(array);//释放第一维指针return 0;}

三维

#include <stdlib.h>#include <stdio.h>int main(){int n1,n2,n3;int ***array;int i,j,k;puts("输入一维长度:");scanf("%d",&n1);puts("输入二维长度:");scanf("%d",&n2);puts("输入三维长度:");scanf("%d",&n3);array=(int***)malloc(n1*sizeof(int**));//第一维for(i=0; i<n1; i++){array[i]=(int**)malloc(n2*sizeof(int*)); //第二维for(j=0;j<n2;j++){array[i][j]=(int*)malloc(n3*sizeof(int)); //第三维for(k=0;k<n3;k++){array[i][j][k]=i+j+k+1;printf("%dt",array[i][j][k]);}puts("");}puts("");}for(i=0;i<n1;i++){for(j=0;j<n2;j++){free(array[i][j]);//释放第三维指针
}}for(i=0;i<n1;i++){free(array[i]);//释放第二维指针}free(array);//释放第一维指针return 0;}

四维

#include <stdlib.h>#include <stdio.h>int main(){int n1,n2,n3,n4;int ****array;int i,j,k,m;puts("输入一维长度:");scanf("%d",&n1);puts("输入二维长度:");scanf("%d",&n2);puts("输入三维长度:");scanf("%d",&n3);puts("输入四维长度:");scanf("%d",&n4);array=(int****)malloc(n1*sizeof(int***));//第一维for(i=0; i<n1; i++){array[i]=(int***)malloc(n2*sizeof(int**)); //第二维for(j=0;j<n2;j++){array[i][j]=(int**)malloc(n3*sizeof(int*)); //第三维for(k=0;k<n3;k++){array[i][j][k]=(int*)malloc(n4*sizeof(int));//第四维for(m=0;m<n4;m++){array[i][j][k][m]=i+j+k+m+1;printf("%dt",array[i][j][k][m]);}puts("");}puts("");}puts("");}for(i=0;i<n1;i++){
for(j=0;j<n2;j++){for(k=0;k<n3;k++)free(array[i][j][k]);//释放第四维指针}}for(i=0;i<n1;i++){for(j=0;j<n2;j++){free(array[i][j]);//释放第三维指针}}for(i=0;i<n1;i++){free(array[i]);//释放第二维指针}free(array);//释放第一维指针return 0;}

数组案例

#include <stdio.h>#include <stdlib.h>int main(){int*n,*p;int i;n=(int*)calloc(1,sizeof(int));for(i=0;i<5000;i++){n[i]=i+1;printf("%dt",n[i]);p=(int*)realloc(n,(i+2)*sizeof(int));//动态扩充数组if(p!=NULL)n=p;else{puts("error!");return 0;}}free(n);return 0;}

游戏套用

预备知识

(1)getch()函式原型: int getch(void);函式功能: 从控制台读取一个字元,但不显示在萤幕上。函式返回: 读取的字元。(2)rand()函式原型: int rand(void);函式功能: 随机函式, 产生0到32767间的随机整数(0到0x7fff之间)。函式返回: 随机整数所属档案: <stdlib.h>(3)srand()函式原型: void srand(unsigned seed);
函式功能: 该函式和rand随机函式配合使用,产生随机数的起始发生数据。参数说明: seed为无符号整数。所属档案: <stdlib.h>(4)time()函式原型: time_t time(time_t *timer)函式功能: 得到机器的日曆时间或者设定日曆时间。函式返回: 机器日曆时间。参数说明: timer=NULL时得到机器日曆时间,timer=时间数值时,用于设定日曆时间,time_t是一个long类型。所属档案: <time.h>(5)'b'实现退格,即当前游标后退一格。(6)'a'实现响铃,即执行时计算机会嘟一声。(7)得到随机数值範围在a~b(包含b)的方法:rand()%(b-a+1)+a;

代码

#include <stdio.h>#include <conio.h>//getch()函式所需头档案#include <stdlib.h>//随机函式所需头档案#include <time.h>//time()函式所需头档案void clear(void)//此函式用以清除当前行{printf("r r");}void start(void){puts("这是消单词游戏的精简版,还不会图像编程的人可以看一看");puts(" 由于没有引入资料库,所以此单词是模拟的。");puts("按任意键开始,按Esc键结束,按tab键重新开始:");puts(" 一旦输错,将发出声音警告,你必须重新输入。");puts(" 按任意键开始,按Esc键结束:");if( 'x1b' == getch() ) //按Esc键结束{exit( 1 );}}int main(){char*c_rand,*c_input;int i,j,N,n,space,N_rand;start();printf("r你想消最多由多少个字母组成的单词?(输入数字(1-9)");n=getch();N=n-'0';//将输入的字元转换为整型数字clear();//清除当前行if(!((N>=1&&N<=9)||n==27))//27是键Esc的ASII值
{printf("r範围错误,请重新开始:");getch();exit(1);//异常退出}if(n==27)return 0;srand(time(NULL));//用来对随机函式初始化c_rand=(char*)malloc(N+1);c_input=(char*)malloc(N+1);while(1){N_rand=rand()%N+1;//实现单词长度随机定义for(i=0;i<N_rand;i++){c_rand[i]=(rand() ==0)?(rand()&+'A'):(rand()&+'a');//随机取个字母}c_rand[N_rand]='';//下面四行代码实现单词位置随机出现space=rand() % 50;putchar('r');for(i=0;i<space;i++)putchar(' ');printf("%s",c_rand);for(i=0;i<N_rand;i++){c_input[i]=getch();//用户输入if(c_input[i]=='x1b')//"x1b"代表的是Esc键break;//下面五行代码实现字母消失效果putchar('r');for(j=0;j<space;j++)putchar(' ');for(j=0;j<=i;j++)putchar(' ');if(c_input[i]!=c_rand[i]){i=-1;putchar('a');//下面四行代码代码字母重现效果putchar('r');for(j=0;j<space;j++)putchar(' ');printf("%s",c_rand);}}if(c_input[i]=='x1b')//"x1b"代表的是Esc键
break;}free(c_rand);free(c_input);return 0;}

本文发布于:2023-03-26 00:57:44,感谢您对本站的认可!

本文链接:http://www.ranqi119.com/to/1679962946241153.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数组   语言   动态
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 站长QQ:55-9-10-26|友情:优美诗词|电脑我帮您|扬州装修|369文学|学编程|软件玩家|水木编程|编程频道