第 7部分指针、指针与数组
编程步骤:
分析?程序框架 (粗算法 )?细算法?程序?调试
2
新的概念,指针( Pointer)
指针也是一种数据类型
一种特殊的数据类型,这种类型存储的是 地址
C/c++的特色
有些复杂但很实用
指针变量与指针常量
指针变量
专门存放地址数据的变量
指针常量
指一个固定的地址,例如:数组名
3
两种寻址方式
如何读写内存中的数据?
通过变量的地址访问变量所在的存储单元
两种寻址方式
直接 (寻址)访问
直接按变量地址来存取变量内容的访问方式
间接 (寻址)访问
通过指针变量来间接存取它所指向的变量的访问方式房间 1
东西房间 2
房间 1
的钥匙直接 寻址 间接 寻址
4
间接寻址访问:
int i;
int *pi;
pi=&i;
*pi=3;
重点:直接寻址与间接寻址的表示
直接寻址访问:
int i;
i=3;
2000
0

变量 i

3010 变量 pi
地址 数据 变量名
如果能直接寻址那当然就不用间接寻址了,
但有时,只能用间接寻址的方法解决问题

数据类型,int *(指向整型变量的指针)
变量名称,pi
变量的初值,&i
含义:向系统申请一个动态区的内存空间,用来存储整型指针变量 pi的初值 &i,即将 pi指向了变量 i。
通过 *pi这种形式,实现对变量 i的 间接引用 。
①②2000
3
5
为什么引入指针的概念
指针有如下好处:
为函数提供修改变量值的手段
为 C的动态内存分配系统提供支持
可以改善某些子程序的效率
为动态数据结构(如例链表、队列、二叉树等)提供支持
6
int i,*p;
p=&i;
*p=100;
int i,*p=&i;
float j,*q=&j;
p=q;
int i;
float *p;
p=&i;
int *p;
p=100;必须进行赋值才能引用 !否则
p指向了哪呢?
一个指针变量不能指向与其类型不同的变量 !float又称变量 P的基类型应在类型相同的指针变量之间赋值
int *p;
scanf(“%p”,&p);
*p=100;
指针 变量 只存放地址 !
int *p;
*p=100;
对指针变量赋值只能通过 &求得!
7
例:读程序main(){int a=5,b=10;
int *pa=&a,*pb=&b;
*pb=-1;
printf(“b=%d\n”,*pb);
pa=pb;
printf(“*pa=%d,*pb=%d”,*pa,*pb);
}
读程序的关键:
–指针变量指向哪儿?
–所指向的变量里存储的数据是多少?
–更改的是指针还是指针所指向的变量?
&a &b
pa pb
5 10
a b
-1
8
主调函数 被调函数
main()
{ int a,b;
a = 5;
b = 9;
Swap(a,b);
printf
("a=%d,b=%d",a,b);
}
void Swap(int x,int y)
{ int temp;
temp = x;
x = y;
y = temp;
}
55
a b
实 参 形 参
99
x ya b
传数值调用
x y
5
temp
9 5
9
主调函数 被调函数
main()
{ int a,b;
a = 15;
b = 8;
Swap(&a,&b);
printf("a=%d,b=%d",a,b);
}
void Swap(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
&a
实 参 形 参
&b
x ya b
传地址调用
x y
5
temp
5
a b
99 5 地址值
指针的好处之一,
通过 将主调函数变量的地址传给形参 实现了 改变主调函数中变量的值 。
当计算结果不只一个时,
可以用这种方法,实现数据的“返回”。
10
指针变量与其它类型变量的对比
共性
在内存中占据一定大小的存储单元
先定义,再使用
指针变量的特殊性
指针变量只能存放地址,而不能存放数据
必须初始化后才能使用,否则指向不确定的存储单元
只能指向同一基类型的变量,否则 warning.
可参与的运算:加、减、关系、赋值
11
指针运算-地址运算
单个指针的运算
加减运算:每加(减) 1表示指针指向后(前)一个数据单元
例,p++;--p;p=p+n;
两个指针的运算
比较:用来比较两个指针的前后位置
例,(p1>p2)
相减:两个指针相距多远?
主要用于对数组的处理
12
小结 1
指针的基础知识
寻址方式
指针的概念、定义、赋值、间接引用、运算
13
习题 7.1
下面的函数用于计算两个整数之和,并通过指针形参 z得到 x和 y相加后的结果。
void Add(int x,int y,z)
{
= x+y;
}
int *
*z
14
习题 7.2
函数功能为 ________
void Exchange(int *p1,int *p2)
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
A)交换 *p1和 *p2的值
B)正确,但无法改变 *p1和 *p2的值
C)交换 *p1和 *p2的地址
D)可能造成系统故障
15
读程序- 1
#include<stdio.h>
void main ( )
{ int a[]={2,4,6,8,10};
int y=0,i,*p;
p=&a[0];
for(i=0;i<5;i++)
y + = * (p+i);
printf("%d\n",y);
}
两个重要内容:
指针指向了哪个数组元素?
是指针运算还是数组元素运算
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
a
a[0]
a[1]
a[2]
a[3]
a[4]
2
4
6
8
10
p
6000
p+1
p+2
p+3
p+4
16
用数组名(指针常量)
引用数组元素
6000
6001
6002
6003
6004
6005
6006
6007
a[0]
a[1]
a[2]
a[3]
a
a+1
a+2
main()
{int a[10],i;
puts(“please input %d score:”,N);
for (i=0; i<10; i++)
scanf("%d",&a[i]);
for (i=0; i<10; i++)
printf("%d ",a[i]);
}
输入输出数组元素:
方法 1:数组名+下标
ain()
{int a[10],i;
puts(“please input %d score:”,10);
for (i=0; i<10; i++)
scanf(“%d”,? );
for (i=0; i<10; i++)
printf("%d ",? );
}
输入输出数组元素:
方法 2:数组名 +偏移量
a+i
*(a+i)
17
用指针变量引用数组元素
main()
{int a[10],i;
int *p=a;
puts(“please input %d score:”,10);
for (i=0; i<10; i++)
scanf("%d",&p[i] );
for (i=0; i<10; i++)
printf("%d ",p[i] );
}
输入输出数组元素:
方法 3:指针变量+下标
也可以用指针变量引用一维数组元素
int a[10],*p=a;
6000
6001
6002
6003
6004
6005
6006
6007
a[0]
a[1]
a[2]
a[3]
a
p
p+1
p+2
main()
{int a[10],i;
int *p=a;
puts(“please input %d score:”,10);
for (i=0; i<10; i++)
scanf(“%d”,? );
for (i=0; i<10; i++)
printf("%d ",? );
}
输入输出数组元素:
方法 4:指针变量 +偏移量
p+i
*(p+i)
18
用指针变量引用数组元素
main()
{int a[10],i;
int *p;
for (p=a; p<(a+10); p++)
scanf("%d",p);
for (p=a; p<(a+10); p++)
printf("%d ",*p);
}
输入输出数组元素:
方法 5:指针变化
也可以用指针变量引用一维数组元素
int a[10],*p=a;
6000
6001
6002
6003
6004
6005
6006
6007
a[0]
a[1]
a[2]
a[3]
a
p
p++
p++
通过数组名的变化引用数组元素行不行?
数组元素的引用形式
a[i]或 *(a+i)
p[i]或 *(p+i)
*(p++)
19
区分几个表达式
P++
*p++
*(p++)
*(++p)
(*p)++
指向下一个地址单元
间接引用 p指向的数据单元,然后,p指向下一个地址单元
同上
先将 p指向下一个地址单元,然后间接引用
p指向的数据单元
P指向的数据 +1
20
读程序 -2
#include <stdio.h>
main()
{
int a[] = {1,2,3,4,5};
int *p = NULL;
p = a;
printf("%d,",*p);
printf("%d,",*(++p));
printf("%d,",*++p);
printf("%d,",*(p--));
printf("%d,",*p++);
printf("%d,",*p);
printf("%d,",++(*p));
printf("%d,",*p);
}
1,2,3,3,2,3,4,4
两个重要内容:
指针指向了哪个数组元素?
是指针运算还是数组元素运算
21
读程序- 3
#include <stdio.h>
char b[] = "program";
char *a =,PROGRAM”;
/*定义一个指针变量指向字符串,与上边定义的区别是:前者是先申请内存空间,后存入字符串,而后者是先将字符串存入在内存的某个地方,然后再用 a指向该字符串所在内存的开始位置。另外。 b是常量,a是变量 */
main()
{
int i = 0;
printf("%c%s\n",*a,b + 1);
while (putchar (*(a + i)))
{ i++;
}
printf("i = %d\n",i);
while ( -- i)
{ putchar (*(b + i));
}
printf("\n%s\n",&b[3]);
}
Program
PROGRAM
i=7
margor
gram
22
例:编写函数实现求和 1
float sum(float a[],int n)
{int i;float sum= a [0];
for(i=1;i<n;i++)
sum+= a [i];
return(sum);
}
#include<stdio.h>
float sum(float a[],int n);
void main()
{int i; float sco[4],s;
for(i=0;i<4;i++)
scanf(“%f”,&sco[i]);
s=sum( sco,4 );
printf(“%f”,s);
}
形参是 数组名实参是 数组名
23
例:编写函数实现求和 2
float sum(float *a,int n)
{int i;float sum= a [0];
for(i=1;i<n;i++)
sum+= a [i];
return(sum);
}
#include<stdio.h>
float sum(float *a,int n);
void main()
{int i; float sco[4],s;
for(i=0;i<4;i++)
scanf(“%f”,&sco[i]);
s=sum( sco,4);
printf(“%f”,s);
}
形参是 指针实参是 数组名
24
例:编写函数实现求和 3
float sum(float *a,int n)
{int i;float sum= a [0];
for(i=1;i<n;i++)
sum+= a [i];
return(sum);
}
#include<stdio.h>
float sum(float *a,int n);
void main()
{int i; float sco[4],s;
float *p=sco;
for(i=0;i<4;i++)
scanf(“%f”,&sco[i]);
s=sum( p,4);
printf(“%f”,s);
}
形参是 指针实参是 指针
25
例:编写函数实现求和 4
float sum(float a[4],int n)
{int i;float sum= a [0];
for(i=1;i<4;i++)
sum+= a [i];
return(sum);
}
#include<stdio.h>
float sum(float a[],int n);
void main()
{int i; float sco[4],s;
float *p=sco;
for(i=0;i<4;i++)
scanf(“%f”,&sco[i]);
s=sum( p,4 );
printf(“%f”,s);
}
形参是 数组名实参是 指针
26
总之,
数组作函数参数有下列四种写法:
但无论哪种形式,本质上,
传递的都是数组的 首地址 。
实参 形参数组名 数组名数组名 指针变量指针变量 数组名指针变量 指针变量
27
小结 2
指针与一维数组的关系
如何利用指针引用数组元素
形参是指针变量
28
作业 2
1,编写函数
void strcat(int *p1,int *p2)
{
……
}
并在主函数中调用。
29
习题 7.3
1下列对字符串的定义中,错误的是,。
A) char str[7] = "FORTRAN";
B) char str[] = "FORTRAN";
C) char *str = "FORTRAN";
D) char str[] =
{'F','O','R','T','R','A','N',?\0?};
2以下程序段的输出结果是,___________ 。
char a[] = "ABCDE" ;
char *p = NULL;
for (p=a; p<a+5; p++)
{
printf("%s\n",p);
}
A) ABCDE B) A C) E D) ABCDE
B D BCDE
C C CDE
D B DE
E A E
30
下面函数实现 strlen函数的功能,即计算指针 p
所指向的字符串中的实际字符个数。
unsigned int MyStrlen(char *p)
{
int len;
len = 0;
for (; *p != ; p++)
{
len ;
}
return ;
}
\0?
++
len 习题 7.4
31
下面函数也是实现 strlen函数功能的,但计算字符串 s中的实际字符个数的方法与上一道题有所不同。
unsigned int MyStrlen(char s[])
{
char *p = s;
while (*p != )
{
p++;
}
return ;
}
\0?
p-s 习题 7.5
32
习题 7.6
int MyStrcmp(char s[],char t[])
{
int i;
for (i=0; s[i] == t[i]; i++ )
{
if (s[i] == )
return 0 ;
}
return ( );
}
\0?
s[i]-t[i]
33
下面函数实现 strcmp函数的功能,即比较两个字符串的大小,将两个字符串中第一个出现的不相同字符的 ASII码值之差作为比较的结果返回,返回值大于
0表示第一个字符串大于第二个字符串,返回值小于
0表示,表示第一个字符串小于第二个字符串,当两个字符串完全一样时,返回值为 0。
int MyStrcmp(char *p1,char *p2)
{
for (; *p1 == *p2; p1++,p2++)
{
if (*p1 == '\0') return ;
}
return ;
}
0
*p1-*p2 习题 7.7
34
指针与二维数组
#define M 2
#define N 3

int b[M][N];
两种观点:
看成一个一维数组
看成数组的数组
35
将二维数组看成一个一维数组
int b[M][N];
二维数组 b相当于一个有 6个元素的一维数组
若有 int *p=&b[0][0];
或 p=b[0] ;(总之是列地址 )
b[i][j]相对于数组起始地址的偏移量为 i*N+j
则 p[i*N+j]或 *(p+i*N+j)表示每一个数组元素。
b[0][0]
b[0][1]
b[0][2]
b[1][0]
b[1][1]
b[1][2]
p
P[0]
P[2]
P[3]
P[4]
P[5]
P[1]
36
填空题:求二维数组元素的和
#include <stdio.h>
void main()
{ int a[3][4]={1,3,5,7,9,11,13,17,19,21,23};
int i,j,sum=0,*p= ;
for ( i=0 ;i<3;i++)
for(j=0; j<4; j++)
{
sum+=p[ ];
}
printf(“sum=%4d",sum);
}
a[0]或 &a[0][0]
i*4+j
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
……
P[0]
P[2]
P[3]
P[4]
P[5]
……
P[1]
p
37
#include <stdio.h>
void main()
{ int a[3][4]={1,3,5,7,9,11,13,17,19,21,23};
int *p= ;
for ( ; ;p++)
{ if (( )%4==0)
printf("\n");
printf("%4d",);
}
}
填空:输出二维数组元素的值
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
……
p
1
3
5
7
9
11
13
输出结果:
1 3 5 7
9 11 13 15
17 19 21 23
a[0]或 &a[0][0]
p<a[0]+12
p-a[0]
*p
38
将二维数组看成数组的数组行地址
b+0
b+1 b[1]
b[0]
b
一维数组 b[0]
b[1][0] b[1][1] b[1][2]
b[0][0] b[0][1] b[0][2]
一维数组 b[1]
将二维数组的每一行看成一维数组
*(b+1)
*(b+0)
列地址
b[0]+0 b[0]+1 b[0]+2
b[1]+0 b[1]+1 b[1]+2列地址
*(b[0]+0) *(b[0]+1) *(b[0]+2)
*(b[1]+0) *(b[1]+1) *(b[1]+2)
再将二维数组 b 看 成 由
b[0],b[1]两个元素组成的一维数组,注意,b[0],b[1]存放的是每行的首地址
39
指针与二维数组行地址
b+0
b+1
一 维数组 b
b
b[1]
*(b+1)
b[0]
*(b+0)
列地址
b[0]+0 b[0]+1 b[0]+2
*(b+0)+0 *(b+0)+1 *(b+0)+2
一维数组 b[0]
b[1]+0 b[1]+1 b[1]+2
*(b+1)+0 *(b+1)+1 *(b+1)+2
列地址
b[1][0] b[1][1] b[1][2]
*(*(b+1)+0) *(*(b+1)+1) *(*(b+1)+2)
b[0][0] b[0][1] b[0][2]
*(*(b+0)+0) *(*(b+0)+1) *(*(b+0)+2)
一维数组 b[1]
请注意:这样的一维数组只是一个示意图,并不在内存中存在。
40
指针与二维数组
b
代表 二 维数组的首地址,指向 第 0行 的首地址 (行地址)
b+i
指向 第 i行 的首地址( 行地址)
*(b+i) 或 b[i]
代表 第 i行第 0列 的地址(列地址)
*(b+i)+j 或 b[i]+j
代表 第 i行第 j列 的地址(列地址)
*(*(b+i)+j ) 或 b[i][j]
代表 第 i行第 j列 的 元素(数组元素)
41
用数组名引用二维数组元素
元素 b[i][j]的几种等价的引用方式
b[i][j]
*(b[i]+j)
*(*(b+i)+j)
(*(b+i))[j]
如何用指针 变量 引用二维数组元素?
42
习题 7.8
5设有语句,int array[3][4]; 则在下面几种引用下标为 i和 j的数组元素的方法中,不正确的引用方式是,_______
A) array[i][j]
B) *(*(array + i) + j)
C) *(array[i] + j)
D) *(array + i*4 + j)
43
二维数组与指针
用指针指向二维数组,有两种指针:
列指针,这种指针指向二维数组的每一个元素,它每加 1,指向二维数组的下一个数组元素。
行指针,这种指针指向二维数组的行,它每加 1,指向二维数组的下一行。
上边两种指针分别对应着对二维数组的两种看法。
44
二维数组的 行 指针
行指针指向二维数组的行
例,int (*p) [3];
含义:定义一个指针变量 p,用于指向一行(每行有 3个元素)
定义格式,类型 (*行指针名 ) [常量 N];
要用 p指向数组 b,如何初始化?
p=b(或 p=&b[0]);/*用行地址初始化 */
p++的含义是?
指向 b[1],即 指向下一行 的开始位置,是行地址。
如何用 P引用 b中每一个数据元素?
p[i][j]
*(p[i]+j)
*(*(p+i)+j)
(*(p+i))[j]
45
#include <stdio.h>
void main()
{ char a[5][10]={"abcde","abc","abcd","ab","abcdef"};
char (*p)[10];
int i;
for(i=0;i<5;i++)
{ p=a+i;
printf(“%s\n”,*p);
}
p=a+2;
p++;
printf("**p=%s\n",*p);
}
二维数组与指针数组的对比
abcde\0
abc\0
abcd\0
ab\0
abcdef\0
p
/*行指针,其变化是行方向的地址变化 */
/*指向第 i行 */
/*注意,*p仍然是地址,该语句输入从这个地址开始到 \0
结束的那一串字符 */
输出结果:
abcde
abc
abcd
ab
abcdef
ab
a[0]
a[1]
a[2]
a[3]
a[4]
a
请注意:这样的一维数组在内存中并不存在。
46
#include <stdio.h>
void main()
{ char *a[5]={"abcde","abc","abcd","ab","abcdef"};
char **p;
int i;
for(i=0;i<5;i++)
{ p=a+i;
printf(“%s\n”,*p);
}
p=a+2;
p++;
printf("**p=%s\n",*p);
}
读程序
a
p
/*定义一维 指针数组 a,a有五个数组元素,每个元素存字符串的首地址 */
/*二级指针 */
/* p指向指针数组 a的每一个元素 */
/*注意,*p与 p[i]等价,仍然是地址 */
输出结果:
abcde
abc
abcd
ab
abcdef
ab
字符串不是连续存储
abcde\0
abc\0
abcd\0
ab\0
abcdef\0
a[0]
a[1]
a[2]
a[3]
a[4]
47
相关语法:指针数组
元素均为指针类型数据的数组,称为指针数组
定义形式为:
类型关键字 *数组名 [数组长度 ];
例如
char *a[5];
含义,a [5] * char
注意与行指针的区别:
char ( *a) [5];
48
例:字符串排序方法一:用二维数组解决
char str[N][10] = {"Pascal","Basic","Fortran",
"Java","Visual C"};
for (i=0; i<N-1; i++) /*交换法排序 */
for (j = i+1; j<N; j++)
{ if (strcmp(str[j],str[i]) < 0)
{strcpy(temp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],temp);
} /*交换的是每一对字符串 */
}
49
方法 1排序前后
s t r [ 0 ] P a s c a l \ 0 \ 0 \ 0 \ 0
s t r [ 1 ] B a s i c \ 0 \ 0 \ 0 \ 0 \ 0
s t r [ 2 ] F o r t r a n \ 0 \ 0 \ 0
s t r [ 3 ] J a v a \ 0 \ 0 \ 0 \ 0 \ 0 \ 0
s t r [ 4 ] V i s u a l C \ 0 \ 0
n a m e [ 0 ] B a s i c \ 0 \ 0 \ 0 \ 0 \ 0
n a m e [ 1 ] F o r t r a n \ 0 \ 0 \ 0
n a m e [ 2 ] J a v a \ 0 \ 0 \ 0 \ 0 \ 0 \ 0
n a m e [ 3 ] P a s c a l \ 0 \ 0 \ 0 \ 0
n a m e [ 4 ] V i s u a l C \ 0 \ 0
str
str
str
str
str
若顺序发生变化,交换每个字符。
请注意:
这样的一维数组只是一个示意图,
并不在内存中存在。
50
例,
方法二:用指针数组解决
char *ptr[N] = {"Pascal","Basic","Fortran",
"Java","Visual C"};
for (i=0; i<N-1; i++) /*交换法排序 */
for (j = i+1; j<N; j++)
{if (strcmp(ptr[j],ptr[i]) < 0)
{ temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
} /*交换的是地址 */
}
51
方法 2排序前后指针数组 ptr 字符串排序 前
Pascal\0
Basic\0
Fortran\0
Java\0
Visual C\0
ptr[0]
ptr[1]
ptr[2]
ptr[3]
ptr[4]
指针数组 ptr 字符串排序 后
Pascal\0
Basic\0
Fortran\0
Java\0
Visual C\0
ptr[0]
ptr[1]
ptr[2]
ptr[3]
ptr[4]
指针的好处之二:
提高效率 !
若顺序发生变化,交换数组元素(地址)。
52
#include <stdio.h>
void ave(float (*p)[3],int n);
void main()
{ int num;
float score[5][3]={{65,98,76},{78,69,87},
{67,68,81},{80,65,98},{64,83,79}};
printf("please input number of student,I will tell you his average
score:");
scanf("%d",&num);
ave(score,num);
getch();
}
void ave(float(*p)[3],int n) /*对 p指向的二维数组中第 n行的数据求和 */
{ int i;
float average=0;
printf("the average score of NO.%d are:",n);
for(i=0;i<3;i++) /*对第 n行的数据求和 */
average=*(*(p+n)+i)+average;
average=average/3;
printf("%5.2f",average);
}
求某个学生的平均值
53
#include <stdio.h>
float *find(float(*pionter)[4],int n);
void main()
{ float score[5][3]={{65,98,76},{78,69,87},
{67,68,81},{80,65,98},{64,83,79}};
float *p;
int i,m;
printf("Enter the number to be found:");
scanf("%d",&m);
printf("the score of NO.%d are:\n",m);
p=find(score,m); /*调用函数在 score中找第 m个学生所在行的首地址 */
for(i=0;i<3;i++)
printf("%5.2f\t",*(p+i));
}
float *find(float(*pointer)[3],int n)
/*函数功能:在指针指向的二维数据中找第 n行的首地址,并返回 */
{
float *pt;
pt=*(pointer+n);
return(pt);
}
输出某个学生的成绩
返回指针值的函数
54
小结 3
二维数组与指针
二维数组与指针的关系
区别行、列指针
指针数组
返回指针值的函数
55
重要提示:
什么时候用指针:
当想用指针间接引用变量的时候
当想希望用指针提高程序效率的时候
不要:
能直接引用变量的时候不要用指针
能用数组名字指针数组的时候不要用指针
56
问题
当我们处理实际问题时,如何申请空间?
int a[100]; /*总是有一定的浪费 */
int a[n]; /*不合法 */
如何根据实际需要申请 n个内存存放 n个数据?
57
一、动态分配内存
? 问题:如何解决根据班级实际人数来定义数组?
自己根据实际需要向系统申请内存如何申请呢?
58
三个相关库函数
#include <stdlib.h>
Void *malloc(unsigned int size);
向系统申请大小为 size的内存块,把首地址返回。如果申请不成功,返回 NULL
Void *calloc(unsigned int num,
unsigned int size);
向系统申请 num个 size大小的内存块,把首地址返回。
如果申请不成功,返回 NULL
void free(void* p);
释放由 malloc()和 calloc()申请的内存块。 p是指向此块的指针
void*类型的指针可以指向任意类型的变量
59
动态数组举例
1 动态一维数组
2 动态二维数组,但看成一维数组
3 动态二维数组
60
动态一维数组
#include<stdio.h>
#include<stdlib.h>
void main()
{
int i,n,*p = NULL;
printf("Please enter array size:");
scanf("%d",&n);
p = (int *) malloc(n * sizeof (int)); //根据上边输入的人数申请内存
printf("please input %d intergers",n);
for(i=0;i<n;i++) //为动态数组输入数据
scanf("%d",&p[i]); //也可以用 scanf("%d",p+i);
puts("the array is:");
for(i=0;i<n;i++)
printf("%4d",p[i]);
free(p); //释放申请的内存空间
}
61
动态二维数组,但看成一维数组来处理
(通过列地址引用二维数组元素 )
#include<stdio.h>
#include<stdlib.h>
void main()
{
int i,j,m,n,*p = NULL;
printf("Please enter size of row:");
scanf("%d",&m);
printf("Please enter size of line:");
scanf("%d",&n);
p = (int *) calloc(n*m,sizeof (int));
//根据前边输入的行、列宽度申请内存空间
printf("please input %d intergers",m*n);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&p[i*n+j]);
//为二维数组输入数据,但使用的是一维数组的引用形式
puts("the array is:");
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
printf("%4d",p[i*n+j]);
putchar('\n');
}
free(p);//释放 申请的内存空间
}
62
#include<stdio.h>
#include<stdlib.h>
void main()
{
int i,j,m,n,*p= NULL,**Parray=NULL;
printf("Please enter size of row:");
scanf("%d",&m);
printf("Please enter size of line:");
scanf("%d",&n);
p = (int *) calloc(m,n*sizeof (int));//根据前边输入的行、列宽度申请内存空间
Parray=(int **)calloc(m,sizeof(int *));//根据前边输入的行宽度申请一个指针数组要用的内存空间
for(i=0;i<m;i++)//指针数组中存储二维数组每一行的首个元素的地址 (列地址 )
Parray[i]=p+i*n;
printf("please input %d intergers",m*n);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",(*(Parray+i))+j);//为二维数组输入元素。指针数据名就相当于二维数组名
puts("the array is:");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("%4d",Parray[i][j]);
putchar('\n');
}
free(p);//释放内存空间
free(Parray);
}
动态二维数组
(通过行地址引用二维数组元素 )
P列地址Parray行地址
&P[0]
&P[3]
1 2 3
4 5 6
63
小结 4
动态数组
三个库函数的使用
动态数组的应用
下节课讲结构体与共用体,请提前预习