当前位置:首页 >> 理学 >>

第19讲 二维数组 字符串与指针 函数与指针lf


1

第19讲
二维数组 字符串与指针 函数与指针

一.指针与二维数组
1. a 二维数组和数组元素的地址
2000 a[0] 2002 a[0][0] a[0][1]

2

2000

a+12008

a[1]

? 对二维数组 int a[3][4],有 ?a-----二维数组的首地址,即第0行的首地址 a[0][2] ?a+i-----第i行的首地址 a[0][3] ?a[i] ? *(a+i)------第i行第0列的元素地址 2008 a[1][0] ?a[i]+j ? *(a+i)+j -----第i行第j列的元素地址 2010 ?*(a[i]+j) ? *(*(a+i)+j) ? a[i][j] a[1][1] a[1][2] ? a+i=a[i]=*(a+i) =&a[i][0], 值相等,含义不同 a[1][3] ?a+i 表示第i行首地址,指向行 2016 ?a[i] ? *(a+i) ? &a[i][0],表示第i行第0 a[2][0] 2018 列元素地址,指向列 a[2][1]

a+22016
a[2]

a[2][2]
a[2][3]

int a[3][4];
a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2]

地址表示: (1) a+1 (2) &a[1][0] (3) a[1] (4) *(a+1) (5)(int *) (a+1) 地址表示: (1) &a[1][2] (2) a[1]+2 (3) *(a+1)+2 (4)&a[0][0]+1*4+2

行指针

3

列指针

a[1][3]
a[2][0] a[2][1]

二维数组元素表示形式: (1)a[1][2] (2)*(a[1]+2) (3)*(*(a+1)+2) (4)*(&a[0][0]+1*4+2)

a[2][2]
a[2][3]

表示形式 a a[0],*(a+0),*a

含义 二维数组名,数组首地址

地址 2000 2000 2008 2008 2012 13

4

第0行第0列元素地址
第1行首地址 第1行第0列元素地址 第1行第2列元素地址 第1行第2列元素值

a+1 a[1],*(a+1) a[1]+2,*(a+1)+2,&a[1][2]
*(a[1]+2),*(*(a+1)+2),a[1][2]

例 用指针变量指向二维数组的数组元素
p
main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p<a[0]+12;p++) { if((p-a[0])%4==0) printf("\n"); printf("%4d ",*p); } }
p=*a; p=&a[0][0]; p=(int *)a; p=a;
int a[3][4];

5

a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2]

a[1][3]
a[2][0] a[2][1]

a[2][2]
a[2][3]

2. 通过建立指针数组和行指针引用二维数组
? 定义形式: 数据类型 (*指针名)[一维数组的元素个数]; int a[3][4]; 例 int (*p)[4]; a p a[0][0]

6

( )不能少 (*p)说明p是一个指针变量!
(*p)[4]说明p的值是某个 包含4个元素的一维数组 的首地址,p是行指针

a[0][1]

p[0]+1或 *p+1 *(*p+1)或 (*p)[1] p+1 p[1]+2或 *(p+1)+2 *(*(p+1)+2) p+2

a[0][2]
a[0][3]

a+1

a[1][0]

a[1][1]
a[1][2] a[1][3]

可让p指向二维数组某一行
如 int a[3][4], (*p)[4]; p=a; p指向的一维数组的元素个数和 二维数组列数必须相同

a+2

a[2][0] a[2][1] a[2][2]

?指针数组: 如 int a[3][4], *q[4]; q[0]=&a[0][0]; q[1]=&a[2][0];

a[2][3]

例 指向一维数组的指针变量(行指针)应用 main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int i,j,(*p)[4]; for(p=a,i=0;i<3;i++,p++) ?for(p=a,p<a+3;p++) for(j=0;j<4;j++) printf("%d ",*(*p+j)); ? p[0][j] printf("\n"); } p=a[0]; p=*a; p=&a[0][0]; p=a; ? p=&a[0];

p

int a[3][4];

7

a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2]

p

p

a[1][3]
a[2][0] a[2][1]

a[2][2]
a[2][3]

a+3

3. 二维数组名或行指针作函数的形参
8

通过指针引用二维数组的几种形式:
若int a[3][4]; int (*p1)[4]=a; int *p2=a[0]; 实参 形参

数组名a
数组名a 指针变量p1

数组名int x[][4]
指针变量int (*q)[4] 数组名int x[][4]

指针变量p1
指针变量p2

指针变量int (*q)[4]
指针变量int *q

例 3个学生各学4门课,计算总平均分,并输出第n个学生成绩 函数说明 void average(float *p,int n) 9 main() { float *p_end, sum=0,aver; { void average(float *p,int n); p_end=p+n-1; void search(float (*p)[4],int n); for(;p<=p_end;p++) float score[3][4]= sum=sum+(*p); {{65,67,79,60},{80,87,90,81}, aver=sum/n; {90,99,100,98}}; printf("average=%5.2f\n",aver); average(*score,12); } search(score,2); 列指针 void search(float (*p)[4], int n) } { int i; p printf(" No.%d :\n",n); 行指针float p[][4] p for(i=0;i<4;i++) 65 52 79 60 printf("%5.2f ",*(*(p+n)+i)); } 80 87 90 81 *(*(p+n)+i) ? p[n][i]
90 99 100 98

例 3个学生各学4门课,计算总平均分,并查找一门以上课 不及格学生, 输出其各门课成绩 void search(float (*p)[4], int n) p { int i,j,flag; 65 52 79 60 for(j=0;j<n;j++) 80 87 90 81 { flag=0; for(i=0;i<4;i++) *(*(p+j)+i) ? p[j][i] 90 99 100 98 if(*(*(p+j)+i)<60) flag=1; if(flag==1) { printf("No.%d is fail,his scores are:\n",j+1); for(i=0;i<4;i++) printf("%5.1f ",*(*(p+j)+i)); printf("\n"); main() } { void search(float (*p)[4], int n); } float score[3][4]={{...},{...},{...}}; } search(score,3); }

10

二维数组与指向一维数组的指针变量的关系
11

如有: int a[5][10],(*p)[10]; p = a ;
? ? ? ? ? ? 系统给数组a分配2*5*10个字节的内存区。 系统只给变量p分配能保存一个指针值的内存区(2字节); 数组名a的值是一个指向有10个元素的一维数组的指针常量; p=a+i 使 p指向二维数组的第i行; *(*(p+i)+j) ? a[i][j] ; 二维数组形参实际上是一个指向一维数组的指针变量, 即: fun(int x[ ][10]) ? fun(int (*x)[10]) 在函数fun中两者都可以有x++;x=x+2;等操作! 但在变量定义(不是形参)时,两者不等价;

指针数组与二级指针的关系
int **p 与 int *q[10] ?系统只给p分配能保存一个指针值的内存区;而给q分 配10个内存区,每个内存区均可保存一个指针值 ; ?指针数组名是二级指针常量; ?p=q; p+i 是q[i]的地址; ?指针数组作形参,int *q[ ]与int **q完全等价;但作 为变量定义两者不同。

12

二. 指针与字符串
1. 字符串表示形式
(1) 用字符数组实现 例 main( ) { char string[]=“I love China!”; printf(“%s\n”,string); printf(“%s\n”,string+7); }
string
I l o v e C h i n a ! \0

13
string[0] string[1] string[2] string[3] string[4] string[5] string[6] string[7] string[8] string[9] string[10] string[11] string[12] string[13]

(2) 用字符指针实现 14 字符指针初始化:把字符串首地址赋给string string 相当于以下两个语句: char *string; string="I love China!"; 例 main( ) { char *string="I love China!"; printf("%s\n",string); string+=7; *string!=0 while(*string) { putchar(string[0]); string++; } *string }
I l o v e C h i n a ! \0

string

2. 用指向字符串的指针作函数参数
例 字符串复制
void copy_string(char from[],char to[]) 15 { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0'; } main() { char a[]="I am a teacher."; char b[]="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); }

(1)用字符数组 作参数

(2) 用字符指针变量作参数
例 实现字符串复制 16

void copy_string(char *from,char *to) { for(;*from!='\0';from++,to++) *to=*from; *to='\0'; } void main() { char *a="I am a teacher.123456789"; char b[80]="You are a student."; printf("string_a=%s\nstring_b=%s\n",a,b); 注意:数组b要有 足够的存储空间! copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); }

3. 字符指针变量与字符数组的分别
char *cp; 与 char str[20]; 17 ? 字符数组str由若干元素组成,每个元素放一个字符;而指针 变量cp中只能存放一个地址值。 char str[20]= "……"; (?) ? char str[20]; str= "I love China!"; (?) cp++; (?) char *cp; cp= "I love China!"; (?) str++; (?) ? str是地址常量;cp是地址变量。 str+1; (?) ? cp接受键入字符串时,必须先开辟存储空间。 例 char str[10]; scanf("%s",str); (?) 而 char *cp; scanf("%s", cp); (?) 改为: char *cp,str[10]; cp=str; scanf("%s",cp); (?)

4. 字符串与数组的关系
? 字符串用一维字符数组存放; ? 一维字符数组中若有一个元素的值为0,则该数组可当字符串用; ? 字符数组具有一维数组的所有特点; ? 数组名是指向数组首地址的地址常量; ? 数组元素的引用方法可用指针法和下标法; ? 数组名作函数参数是地址传递等; char str[80]; ? 区别 scanf(“%s”,str); ? 存储格式:字符串结束标志; printf(“%s”,str); gets(str); ? 赋值方式与初始化; puts(str); ? 输入输出方式:%s %c char str[]={“Hello!”}; char str[]=“Hello!”; char str[]={?H?,?e?,?l?,?l?,?o?,?!?}; char *cp=“Hello”; int a[]={1,2,3,4,5}; int *p={1,2,3,4,5}; (?) (?) (?) (?) (?) (?)

18

char str[10],*cp; int a[10],*p; str=“Hello”; (?) cp=“Hello!”; (?) a={1,2,3,4,5}; (?) p={1,2,3,4,5}; (?)

对字符串排序 例 对字符串排序(简单选择排序)
main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; void print(char *name[],int n) sort(name,n); { int i=0; print(name,n); char *p; } /*p=name[0];*/ void sort(char *name[],int n) while(i<n) { char *temp; { p=*(name+i++); int i,j,k; printf("%s\n",p); for(i=0;i<n-1;i++) } { k=i; } for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }

19

例 用二级指针处理字符串 20 用*p可输出地址(%o或%x), #define NULL 0 也可用它输出字符串(%s) void main() { char **p; char *name[]={"hello","good","world","bye",""}; p=name+1; printf("%o : %s ", *p,*p); p+=2; while(**p!=NULL) printf("%s\n",*p++); ?*(p++)右结合 }
运行结果: 644 : good bye

三. 指针与函数
?函数指针:函数被存放在内存中一片连续的存储单元内, 21
其中排在最前面的那个存储单元的地址就是这个函数的地 址,也叫函数指针,用函数名表示,它是一个地址常量。
max
指令1 指令2

?指向函数的指针变量

作用:专门存放函数的入口地址 可指向返回值类型相同的不同函数 ?定义形式: 数据类型 (*指针变量名)();

…...

函数返回值的数据类型 ( )不能省 int (*p)() 与 int *p()不同 如 int (*p)( );

函数指针变量的赋值
如 int (*p)( ); p = max;

max 指令1 指令2

22

…...

函数指针变量指向的函数必须有函数说明

函数调用形式: c= max(a,b); ? c= (*p)(a,b); ? c= p (a,b); 注意:对函数指针变量 p ? n , p++ 等操作没有意义!

1. 用指向函数的指针变量调用函数 23 main() main() { int max(int ,int); { int max(int ,int), (*p)(); int a,b,c; int a,b,c; scanf("%d,%d",&a,&b); p=max; c=max(a,b); scanf("%d,%d",&a,&b); printf("a=%d,b=%d,max=%d\n",a,b,c); c=(*p)(a,b); } printf("a=%d,b=%d,max=%d\n",a,b,c); int max(int x,int y) } { int z; int max(int x,int y) if(x>y) z=x; { int z; else z=y; if(x>y) z=x; return(z); else z=y; } return(z); }

2. 用指向函数的指针变量作函数参数
例 用函数指针变量作参数,求最大值、最小值和两数之和 24

void main() { int a,b,max(int,int), min(int,int),add(int,int); void process(int,int,int (*fun)()); scanf("%d,%d",&a,&b); process(a,b,max); process(a,b,min); process(a,b,add); } void process(int x,int y,int (*fun)()) { int result; result=(*fun)(x,y); printf("%d\n",result); }

max(int x,int y) { printf(“max=”); return(x>y?x:y); } min(int x,int y) { printf(“min=”); return(x<y?x:y); } add(int x,int y) { printf(“sum=”); return(x+y); }

3. 返回指针值的函数
函数定义形式:
类型标识符 *函数名(参数表); 例 int *f(int x, int y)

main() { float score[][4]={{60,70,80,90}, {56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4],int n), *p; int i,m; printf("Enter the number of student:"); scanf("%d",&m); printf("The scores of No.%d are:\n",m); p=search(score,m); pointer for(i=0;i<4;i++) printf("%5.2f\t",*(p+i)); pointer+1 } float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt); }

例 用指针函数 实现:有若干 学生成绩,要 求输入学生序 号后,能输出 其全部成绩。

25

p score数组
60 56 70 89 80 67 90 88

34

78

90

66

4. main函数的参数
? 命令行:在DOS操作系统状态下,为执行某个程序而键入的 26 一行字符 ? 命令行一般形式:命令名 参数1 参数2………参数n C:\TC> copy source.c temp.c <CR> 有3个字符串参数的命令行

?带参数的main函数形式:
形参名argc, argv任意 main(int argc, char *argv[]) { ……… } 指针数组:各元素指向命令 行参数中各字符串首地址 命令行中参数个数

命令行参数的传递
?命令行参数传递
系统自动调用 main函数时传递 命令行实参 main(int argc, char *argv[]) 27 { ……… }

main(形参)

C:\TC> copy source.c temp.c <CR>
argv char *argv[] argv[0]

"copy "
"source.c " "temp.c "

argc=3

argv[1] argv[2]

例 输出命令行参数 /*test.c*/ main(int argc, char *argv[]) { while(argc>1) { ++argv; printf("%s\n",*argv); --argc; } } 28

argv

char *argv[]

argv[0]

test hello world

argc=3

argv[1] argv[2]

1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下) argc, char *argv[]) main(int { while(argc-->0) 例如: C:\TC> test hello world! printf("%s\n",*argv++); } 运行结果:test 运行结果:hello
world!

hello world!

有关指针操作的小结
1.指针变量是把其它变量的地址作为内容的变量。指针变量 的内容可以是0、NULL和一个确定的地址。 2. 地址运算符(&) 返回其操作数的地址。 地址运算符的操作数必须是一个变量(或数组元素)。 3. 指针运算符(*) 又称为“间接引用运算符” ,它表示从相 应的存储单元中获取某种类型的数据值。 4. 指针±整数 5. 指针1-指针2 6. 指针的关系运算,如:指针1<指针2 7. 在调用带有参数的函数时,如果调用函数要求被调用函数 修改参数的值,应该把参数的地址传递给被调用函数, 被调用函数用间接引用运算符(*)修改调用函数中的参数 的值。

29

指针的数据类型
定义 int i; int *p; int a[n]; int *p[n]; 定义整型变量i p为指向整型数据的指针变量 定义含n个元素的整型数组a n个指向整型数据的指针变量组成的指针数组p p为指向含n个元素的一维整型数组的指针变量 f为返回整型数的函数 p为返回指针的函数,该指针指向一个整型数据 p为指向函数的指针变量,该函数返回整型数 p为指针变量,它指向一个指向整型数据的指针变量

含义

30

int (*p)[n]; int f(); int *p();
int (*p)(); int **p;

例 下列定义的含义 (1)int *p[3]; (2)int (*p)[3]; (3)int *p(int); (4)int (*p)(int); (5)int *(*p)(int); (6)int (*p[3])(int); (7)int *(*p[3])(int);

指针数组 31 指向一维数组的指针 返回指针的函数 指向函数的指针,函数返回int型变量 指向函数的指针,函数返回int 型指针 函数指针数组,函数返回int型变量 函数指针数组,函数返回int型指针


相关文章:
更多相关标签: