第 15讲二维数组与指针
2
指针与二维数组
#define M 2
#define N 3

int b[M][N];
两种观点:
看成一个一维数组
看成数组的数组
3
将二维数组看成一个一维数组
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]
4
填空题:求二维数组元素的和
#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*3+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
5
#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
6
将二维数组看成数组的数组行地址
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]存放的是每行的首地址
7
指针与二维数组行地址
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]
8
指针与二维数组
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列 的 元素(数组元素)
9
用数组名引用二维数组元素
元素 b[i][j]的几种等价的引用方式
b[i][j]
*(b[i]+j)
*(*(b+i)+j)
(*(b+i))[j]
如何用指针 变量 引用二维数组元素?
10
二维数组与指针
用指针指向二维数组,有两种指针:
列指针,这种指针指向二维数组的每一个元素,它每加 1,指向二维数组的下一个数组元素。
行指针,这种指针指向二维数组的行,它每加 1,指向二维数组的下一行。
上边两种指针分别对应着对二维数组的两种看法。
11
二维数组的 行 指针
行指针指向二维数组的行
例,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]
12
#include <string.h>
main()
{
int i,pos,findFlag = 0;
char x[10];
char weekDay[7][10] = {"Sunday","Monday","Tuesday",
"Wednesday","Thursday","Friday",
"Saturday"};
char (*p)[10] =weekDay;
printf("Please enter a string:");
scanf("%s",x);
for (i=0; i<7 && !findFlag; i++)
{
if (strcmp(x,*(p+i)) == 0)
{
pos = i;
findFlag = 1;
}
}
if (findFlag)
printf("%s is %d\n",x,pos);
else
printf("Not found!\n");
}
读程序
weekDay[0]
weekDay[1]
weekDay[2]
weekDay[3]
weekDay[4]
weekDay[5]
weekDay[6]
Sunday\0
Monday\0
Tuesday\0
Wednesday\0
Thursday\0
Friday\0
Saturday\0
p
13
#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);
}
例题 8- 1
有没有其它写法?
把第 n行的数据当成一个一维数组,问题变成求一维数组元素的和。
14
#include <stdio.h>
float *find(float(*pionter)[4],int n);
void main()
{ float score[4][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
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<4;i++)
printf("%5.2f\t",*(p+i));
}
float *find(float(*pointer)[4],int n)
/*函数功能:在指针指向的二维数据中找第 n行的首地址,并返回 */
{
float *pt;
pt=*(pointer+n);
return(pt);
}
例题 8- 9
返回指针值的函数
15
#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);
}
例 8- 2 读程序
a[0]
a[1]
a[2]
a[3]
a[4]
abcde\0
abc\0
abcd\0
ab\0
abcdef\0
a
p
/*行指针,其变化是行方向的地址变化 */
/*指向第 i行 */
/*注意,*p仍然是地址,该语句输入从这个地址开始到 \0
结束的那一串字符 */
输出结果:
abcde
abc
abcd
ab
abcdef
ab
16
#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);
}
例 8- 2读程序
a[0]
a[1]
a[2]
a[3]
a[4]
abcde\0
abc\0
abcd\0
ab\0
abcdef\0
a
p
/*定义一维 指针数组 a,a有五个数组元素,每个元素存字符串的首地址 */
/*二级指针 */
/* p指向指针数组 a的每一个元素 */
/*注意,*p与 p[i]等价,仍然是地址 */
输出结果:
abcde
abc
abcd
ab
abcdef
ab
17
二、指针数组
元素均为指针类型数据的数组,称为指针数组
定义形式为:
类型关键字 *数组名 [数组长度 ];
例如
char *pStr[5];
含义,pStr [5] * char
注意与行指针的区别:
char ( *pStr) [5];
18

#include <stdio.h>
void main()
{int i;
char *ptr[]=
{"Pascal","Basic","Fortran","Java","Visual C"};
char **p; p = ptr;
for (i=0; i<5; i++)
{printf("%s\n",*p);
p++;
}
}
ptr[0] Pascal
ptr[1]
ptr[2]
ptr[3]
Basic
Fortran
Java
ptr指针数组 字符串
Visual Cptr[4]
&Ptr[0]
p
p
19
例:字符串排序方法一:用二维数组解决
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);
}
}
20
方法 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
若顺序发生变化,交换每个字符。
21
例,
方法二:用指针数组解决
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;
}
}
22
方法 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]
指针的好处之二:
提高效率 !
若顺序发生变化,交换数组元素(地址)。
23
小结
二维数组与指针 (第八章 1-2节 )
二维数组的行、列指针
指针数组
返回指针值的函数
下节课继续讲第六章-结构体
24
作业 1
复习:看懂所有与指针的例题
写出心得体会或提出自己的问题。