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。
(2)使用sizeof的目的是用来计算一种类型的占有的字节数,以便适合不同的
编译器。
(3)由于动态分配不一定成功,为此要附加一段
异常处理程序,不致程序运行停止,使用户
if(p==NULL) /* 或者if(!p)*/ { printf("动态申请内存失败!\n"); exit(1); //异
常退出 }
(4)这四个函数头文件均包含在<stdlib.h>中。
(5)分配的堆空间是没有名字的 只能通过返回的
指针找到它。
如:
free(p);free(p);
的内存区。这时对它的任何使用便可能会可带来问题。
对于用
malloc分配的内存区间,如果原来没有被使用过,则其中的每一位可能都是0;反之,
如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,
使用
malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内
存空间已被重新分配)可能会出现问题,因此在使用它之前必须先进行初始化(可用memset函数
对其初始化为0),但调用
calloc()函数分配到的空间在分配时就已经被初始化为0了。
间,从而来选择相应的函数。
具体构建方法
先遵循从外层到里层,逐层申请的原则:
最外层
指针是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[][]申请内存应:
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++)
{
}
}
for(i=0;i<n1;i++)
{
}
其余维的如四维创建过程大同小异,这里不再赘述。
构建实例
一维
#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("%d\t",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("%d\t",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("%d\t",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("%d\t",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("%d\t",n[i]);
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]='\0';
//下面四行代码实现单词位置随机出现
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;
}
-
扩展阅读:
-
- 1
动态数组在消字母游戏精简版的应用(C语言)
- 2
http://hi.baidu.com/liangxiaowen1989/blog/item/3a638c942e8a20057af48001.html
- 3
动态扩充数组实例(C语言)
- 4
http://hi.baidu.com/liangxiaowen1989/blog/item/e320d2a880caedf11f17a204.html
- 5
四维动态数组构建实例(C语言)
- 6
http://hi.baidu.com/liangxiaowen1989/blog/item/315d9dd6fccab5d0a044df39.html
- 7
三维动态数组构建实例(C语言)
- 8
http://hi.baidu.com/liangxiaowen1989/blog/item/8d5659943fa08f46d0135e33.html
- 9
二维动态数组构建实例(C语言)
- 10
http://hi.baidu.com/liangxiaowen1989/blog/item/5b41d3a635edea98d0435836.html
- 11
一维动态数组构建实例(C语言)
- 12
http://hi.baidu.com/liangxiaowen1989/blog/item/36b56602a05282e109fa9335.html
- 13
为什么上述案例main函数均有返回值?
- 14
- 15
C/C++语言void及void指针深层探索:
- 16
- 1
-
开放分类: