经典C语言第五章数组.ppt

上传人:小飞机 文档编号:6331355 上传时间:2023-10-17 格式:PPT 页数:87 大小:369.32KB
返回 下载 相关 举报
经典C语言第五章数组.ppt_第1页
第1页 / 共87页
经典C语言第五章数组.ppt_第2页
第2页 / 共87页
经典C语言第五章数组.ppt_第3页
第3页 / 共87页
经典C语言第五章数组.ppt_第4页
第4页 / 共87页
经典C语言第五章数组.ppt_第5页
第5页 / 共87页
点击查看更多>>
资源描述

《经典C语言第五章数组.ppt》由会员分享,可在线阅读,更多相关《经典C语言第五章数组.ppt(87页珍藏版)》请在三一办公上搜索。

1、教学目标:本讲介绍C语言中数组的定义和使用,其中重点介绍一维数组的定义、引用、初始化,此外对二维数组的定义、引用和初始化在文中也作了详细的说明。要求大家熟练掌握一维数组的使用,了解的二维数组的应用,灵活运用数组编程。本讲重点:一维数组的定义、初始化及应用;数组元素的引用方法:下标法、数组名法。字符串的使用和字符串函数的应用。本讲难点:利用指针实现对数组的操作;二维数组的应用。教学方法:理论教学与实践教学相结合。,5.1 一维数组及指针 5.2 一 维字符数组及指针5.3 多维数组及指针 5.4 指针数组 5.5 二级指针 5.6 程序设计举例,第五章 数组,5.1 一维数组及指针,数组属于构造

2、类型,数组是具有相同数据类型的变量的序列,序列中的每个变量称为数组元素,数组元素用一个统一的标识符“数组名”和其顺序号“下标”来表示。数组可以是一维的,也可以是多维的。数组必须先定义后使用。,5.1.1.一维数组的定义和初始化1一维数组的定义一维数组定义的一般形式为:类型标识符 数组名常量表达式其中,类型标识符表示数组的数据类型,即数组元素的数据类型,可以是任意数据类型,如整型、实型、字符型等。常量表达式可以是任意类型,一般为算术表达式,其值表示数组元素的个数,即数组长度。数组名要遵循标识符的取名规则。如:int a10;定义了一个一维数组,数组名为a,数据类型为整型,数组中有10个元素,分别

3、是:a0,a1,a2,a3,a4,a5,a6,a7,a8,a9。,说明:不允许对数组的大小作动态定义。如下面对数组的定义是错误的。int n=10;int an;数组元素的下标从0开始。如数组a中的数组元素是从a0到a9。C语言对数组元素的下标不作越界检查。如:数组a中虽然不存在数组元素a10,但在程序中使用并不作错误处理,所以在使用数组元素时要特别小心。数组在内存分配到的存储空间是连续的,数组元素按其下标递增的顺序依次占用相应字节的内存单元。数组所占字节数为:sizeof(类型标识符)*数组长度。如数组a占用连续20个字节存储空间,为其分配的内存见图5.1。,图5.1,在函数内或函数外可以同

4、时定义多个数组,还可以同时定义数组和变量,如:float a10,b20,c,d,*p;但在函数的参数中一次只能定义一个数组。2一维数组初始化在定义数组的同时,可以对数组的全部元素或部分元素赋初值,称为数组的初始化。全部元素初始化。在对全部数组元素初始化时,可以不指定数组长度。,如:下面对数组a的初始化是等价的:int a10=0,1,2,3,4,5,6,7,8,9;int a=0,1,2,3,4,5,6,7,8,9;a0到a9的值分别为:0,1,2,3,4,5,6,7,8,9。Turbo C中,若数组的存储类型为static,且没有初始化,编译系统自动对数组初始化,将数值型数组的全部元素都初

5、始化为0,将字符型数组的全部元素都初始化为空(0)。如:static int a10;/*数组元素a0到a9的值都为0。*/部分元素初始化。部分元素初始化时,数组的长度不能省略,并且是赋值给前面的元素,没有被赋值的数组元素,数值型数组时值为0,字符型数组时值为0。如:int a10=1,2;/*a0的值为1,a1的值为2,a2到a9的值都为0*/,5.1.2 一维数组元素的下标法引用一维数组元素的下标表示形式为:数组名表达式其中,表达式的类型任意,一般为算术表达式,其值为数组元素的下标。用下标法引用数组元素时,数组元素的使用与同类型的普通变量相同。若有定义:int a10=1,2,3,4,5,

6、6,7,8,9,10,i=3;则下列对数组元素的引用都是正确的:ai/*表示a3*/a+i/*表示a4*/a3*2/*下标6的数组元素*/,a3.4/*下标为实型数据,系统自动取整,表示a3*/ab-a/*下标为表达式,表达式b-a的值为1,表示 a1*/a4+=10/*与a4=a4+10等价,表示将a4的原值加10*/a4+/*与a4=a4+1等价,表示将a4的原值加1*/,【例5.1】将整型数组a中的十个整型数逆序存放并输出。main()int a10,i,j,t;for(i=0;i10;i+)/*输入10个整型数存入数组a中*/scanf(%d,运行结果:1 2 3 4 5 6 7 8

7、9 1010 9 8 7 6 5 4 3 2 1,需要注意的是数值型数组不能用数组名输入输出它的全部元素,只能是单个元素输入,单个元素输出。如:例5.1中的程序段:for(i=0;i10;i+)scanf(%d,5.1.3 一维数组的指针 C语言规定,数组存储空间的首地址存放在数组名中,即数组名指向下标为0的数组元素。由此可知数组名不仅是一个标识名字,它本身又是个地址量。由于数组的存储位置是系统分配的,用户不能任意改变和设置,所以,表示数组存储起始位置的数组名是个地址常量。另外,数组中的每个元素都有地址,其表示形式为:&数组名下标,其值也是地址常量。如:数组a的首地址为a或&a0,数组元素a3

8、的地址为&a3。需要说明的是:虽然数组名代表数组存放的起始地址,但系统并不为数组名分配内存单元。另外,对数组名用取地址符“&”进行运算没有意义。,1指向一维数组元素的指针变量 上面介绍了指向数组元素的指针常量,C语言中还可以定义指向数组元素的指针变量。指向一维数组元素的指针变量的定义与前面介绍的指向变量的指针变量的定义相同。如:int*p;定义p为指向整型变量的指针变量,若有下面赋值语句:p=则把元素a3的地址赋给指针变量p。也就是说,指针变量p指向数组a中下标为3的元素。可以在定义指针变量的同时,把数组元素的地址初始化给指针变量。,如:int a10,*p=a;它等价于:int a10,*p

9、;p=a;其作用是把数组a的起始地址,即a0的地址赋给指针变量p。需要注意的是:指针变量的类型必须与它指向的数组元素的类型一致。,2指针运算 除了上面介绍的赋值运算外,指向一维数组元素的指针,还可以进行下列运算:指向数组元素的指针可以加(减)一个整型数。假设p是指向数组元素的指针,n是一个整型数,则:pn的含义是使p的原值(地址)加(减)n个数组元素所占的字节数,即pnd(其中d代表一个数组元素占用的字节数,如:int型为2,float型为4)。若有定义:int a10,*p;,则a+3实际代表a+3*2,即a+3指向a3;如果p指向a2,则p-1实际代表p-1*2,即p-1指向a1。,由此可

10、知,如果指针变量p的值为&a0,则:&ai、a+i和p+i是等价的,它们都表示数组元素ai的地址。指向数组元素的指针变量可以进行自加自减运算,自加后指向原来指向元素的下一个元素,自减后指向原来指向元素的上一个元素。假如指针变量p指向a2,则+p指向a3,-p指向a1。需要注意的是数组名是常量,不能进行自加自减运算。若两个指针指向同一个数组的元素,则两个指针可以进行减运算,其含义为两个指针之间的数组元素个数。假如p指向a2,则q-a=2,2表示p和a之间有两个数组元素。若两个指针指向同一个数组的元素,则可以进行关系运算。假设p指向a2,则pa为真,pa+4为假。,5.1.4 一维数组元素的指针法

11、引用由前面的介绍可知,若有定义:int a10,*p=a;则&ai、(a+i)和(p+i)是等价的,它们都表示数组元素ai的地址。由此可得下列等价关系:ai、*(a+i)和*(p+i)等价。它们都表示下标为i的数组元素。由此可知,一维数组元素除了可以用下标法引用外,还可以用指针法引用。1数组名法用数组名引用数组元素的一般形式为:*(数组名+表达式)其中,表达式类型任意,一般为算术表达式,其值为数组元素的下标。如:*(a+3-1)表示数组元素a2。,【例5.2】用数组名法实现例5.1。main()int a10,i,j,t;for(i=0;i10;i+)scanf(%d,a+i);for(i=0

12、,j=9;ij;i+,j-)t=*(a+i);*(a+i)=*(a+j);*(a+j)=t;for(i=0;i10;i+)printf(%4d,*(a+i);,2指针变量法用指针变量引用数组元素的一般形式为:*(指针变量+表达式)其中,指针变量为指向一维数组元素的指针变量。表达式类型任意,一般为算术表达式。若指针变量指向下标为0的数组元素,则表达式的值就是要引用的数组元素的下标,否则要引用的数组元素的下标为:指针变量-数组名+表达式。假如p指向a3,则下列用指针变量p对数组元素引用的都是正确的。*p=10/*与a3=10等价*/*(p+2*2)=20/*与a7=20等价*/*p+=40/*与*

13、p=*p+40等价*/,【例5.3】用指针变量法实现例5.1。main()int a10,*i,*j,t;for(i=a;ia+10;i+)scanf(%d,i);for(i=a,j=a+9;ij;i+,j-)t=*i;*i=*j;*j=t;for(i=a;ia+10;i+)printf(%4d,*i);,在编译时,编译系统将下标表示法转换为数组名表示法,所以用下标法和数组名法的执行效率是一样的,但用指针变量法既简捷,又能提高效率。,指向数组元素的指针变量也可用下标法表示数组元素,即*(p+i)和pi是等价的。,在使用指针变量引用数组元素时,应注意以下几种情况:*(p+)/*先用p指向的元素值

14、,然后p指向下一个元素*/*(+p)/*p先指向下一元素,然后用p指向的元素值*/*(p-)/*先用p指向的元素值,然后p指向上一个元素*/*(-p)/*p先指向上一元素,然后用p指向的元素值*/*p+/*与*(p+)等价*/*p-/*与*(p-)等价*/(*p)+/*先用p指向的元素值,然后将p指向的元素值加1*/(*p)-/*先用p指向的元素值,然后将p指向元的素值减1*/+(*p)/*先将p指向的元素值加1,然后再用p指向的元素值*/-(*p)/*先将p指向的元素值减1,然后再用p指向的元素值*/,【例5.4】main()int a=1,3,5;/*数组初始化,a0=1,a1=3,a3=

15、5*/int*p;p=/*p=1,p指向a0*/,p=/*p指向a1*/,printf(*p)-=%dn,(*p)-);/*(*p)-=4*/printf(*p=%dn,*p);/*p=3,即a1=3,p指向a1*/p=/*p=3,即a1=3,p指向a1*/,5.2一维字符数组及指针5.2.1 一维字符数组的定义和初始化1一维字符数组的定义C语言中没有专门的字符串变量,字符串的存放和处理可以用字符数组来实现。一维字符型数组定义的一般形式为:char 数组名常量表达式如:char str6;字符数组str有6个元素,分别为:str0,str1,str2,str3,str4,str5。字符数组中的

16、一个元素存放一个字符。如字符数组str只能存放6个字符。,2一维字符数组的初始化 字符数组初始化时,可以用字符常量,也可用字符串常量,全部元素初始化时,数组的长度可以省略。用字符常量初始化可以用字符常量对字符数组的全部元素初始化。如:char str3=U,S,A;等价于下面的初始化:char str=U,S,A;字符数组str中有3个元素,str0的值为U,str1 的值为S,str2的值为A。见图5.2。,图5.2,也可以用字符常量对字符数组的部分元素初始化。如:char str6=U,S,A;字符数组str中有6个元素,str0的值为U,str1 的值为S,str2的值为A,未初始化的元

17、素str3、str4和str5的值都为空(0)。见图5.3。,用字符串常量初始化可以用字符串常量对字符数组的全部元素初始化。如:char str=USA;可将花括号省略,即写成:char str=USA;等价于下面的用字符常量初始化:char str=U,S,A,0;。,字符数组str中有四个元素,str0的值为U,str1 的值为S,str2的值为A,str3的值为0。见图5.4。由此可知,用字符串常量初始化字符数组时,字符数组的长度至少要比字符串的最大长度多一,最后一个元素用来存放字符串结束标志0。也可以用字符串常量对字符数组的部分元素初始化。部分元素初始化时,长度不能省略。如:char

18、str6=USA;与下面的用字符常量初始化等价:char str6=U,S,A,0,0,0;见图5.5。,图5.4,图5.5,5.2.2字符数组的输入和输出1字符串输出函数puts()一般调用格式:puts(str)其中,参数str可以是地址表达式(一般为数组名或指针变量),也可以是字符串常量。功能:将一个以0为结束符的字符串输出到终端(一般指显示器),并将0转换为回车换行。返回值:输出成功,返回换行符(ASCII码为10),否则,返回EOF(-1)若有定义:char str=China;则:puts(str);的输出结果为:China puts(str+2);的输出结果为:ina,说明:使用

19、puts()函数的函数前面要有文件包含:#include stdio.h 或#include 输出的字符串中可以包含转义字符,并输出到第一个0为止,并将0转换为n,即输出完字符串后回车换行。如:char str=chinanliaoning0jinzhou;输出结果为:china liaoning puts()函数一次只能输出一个字符串。,2字符串输入函数gets()一般调用格式为:gets(str)其中,参数str是地址表达式,一般是数组名或指针变量。功能:从终端(一般指键盘)输入一个字符串,存放到以str为起始地址的内存单元。返回值:字符串在内存中存放的起始地址,即str的值。如:char

20、 str20;gets(a);把从键盘上输入的字符串存放到字符数组str中。说明:使用gets()函数的函数前面要有文件包含:#include stdio.h 或#include gets()函数一次只能输出一个字符串。系统自动在字符串后面加一个字符串结束标志0。,3字符数组的输出可以用两种方法输出字符数组:(1)单个字符输出。用格式输出函数printf()的%c的格式,或用字符输出函数putchar()。(2)将整个字符串一次输出。用格式输出函数printf()的%s格式,或用字符串输出函数puts()。将整个字符串一次输出时要注意以下几点:输出字符不包括字符串结束标志0。printf()的

21、%s格式的输出项参数和puts()的参数是地址表达式,而不是数组元素名。如:char str10=China;printf(%s,str);/*输出:China*/puts(str+2);/*输出:ina*/,如果数组长度大于字符串的实际长度,也只输出到0结束。如果一个字符数组中包含一个以上的0,则遇到第一个0 输出结束。如:char str10=china0usa;printf(%s,str);输出结果为:china,4字符数组的输入字符数组输入也有两种方法:(1)单个字符输入。可以用格式输入函数scanf()的%c格式,或用字符输入函数getchar()。(2)将整个字符串一次输入。可以用

22、格式输入函数scanf()的%s格式,或用字符串输入函数gets()。将整个字符串一次输入时要注意以下几点:用scanf()的%s格式不能输入含有空格的字符串,遇到空格系统认为输入结束,所以用scanf()函数一次能输入多个不含空格的字符串。用gets()函数能够输入含有空格的字符串,但一次只能输入一个字符串。,如:char str112;scanf(%s,str1);printf(%s,str1);数据输入:how are you输出结果:how字符数组str1的内容见图5.6。,图5.6,如果改为:char str112;gets(str1);printf(%s,str1);数据输入:ho

23、w are you输出结果:how are you,字符数组str1的内容见图5.7。(代表空格),图5.7,如果改为:char str14,str24,str34;scanf(%s%s%s,str1,str2,str3);printf(%sn%sn%s,str1,str2,str3);数据输入:how are you输出结果:how are you 字符数组str1、str2和str3的内容见图5.8。,系统自动在最后一个字符的后面加上一个字符串结束符0。scanf()的%s格式的输入项是数组名时,数组名前不能加取地址符“&”,因为数组名本身代表数组的首地址。,5.2.3 用字符数组实现字符

24、串若字符串存放在字符数组中,对字符串中字符的引用可以用下标法,也可用指针法。其引用形式和前面介绍的一维数组元素的引用相同。1用下标法引用【例5.5】将一个字符串逆置后接到原串的后面。#include stdio.hmain()char str81;int i,j;gets(str);i=0;while(stri!=0)i+;,j=i;i-;while(i=0)strj=stri;i-;j+;strj=0;puts(str);运行结果:abcabccba,2用数组名法引用【例5.6】将字符数组a中的字符串复制到字符数组b。#include stdio.hmain()char a81,b81;in

25、t i=0;gets(a);while(*(a+i)!=0)*(b+i)=*(a+i);i+;*(b+i)=0;puts(b);运行结果:chinachina,3用指针变量法引用【例5.7】删除字符串尾部空格。#include stdio.h main()char str80,*p;gets(str);p=str;while(*p)p+;p-;while(*p=)p-;p+;*p=0;printf(%s,str);,运行结果:abcdabcd/*光标在d的后一列上*/,5.2.4 用字符指针变量实现字符串除了能用字符数组处理字符串外,还可以用字符指针变量。如:char*str=china;等价

26、于:char*str;str=china;其含义为:定义了一个字符型指针变量str,并将字符串china“的首地址赋给它,即str指向字符串的第一个字符“c”。,【例5.8】#include stdio.hmain()char*p1=china;char*p2;puts(p1);p2=p1;puts(p2+2);运行结果:chinaina,虽然用字符数组和字符指针变量都能实现对字符串的处理,但它们之间是有区别的,主要注意以下几点:字符数组有若干个元素组成,每个元素中存放一个字符,而字符指针变量中存放的是字符串的首地址,而不是将字符串存放到指针变量中。不能用赋值语句将一个字符串常量或字符数组直接

27、赋给字符数组,但可以用赋值语句将一个字符串常量或字符数组的首地址直接赋给指针变量。如有定义:char str110=china,str210,*p1,*p2;下面的赋值是不合法的:str2=str1;str2=USA;,下面的赋值是合法的:p1=str1;/*把数组str1的首地址赋给p1*/p2=USA;/*把字符串USA的首地址赋给p2*/使用数组名可以安全地把从键盘上输入的字符串存放到字符数组中,但用未赋以地址值的指针是危险的。如:char*p;scanf(%s,p);虽然一般也能运行,但有可能破坏其他程序。使用字符指针变量处理字符串比用字符数组处理字符串节省内存。如:char*p=ch

28、ina;是把字符串常量china的地址赋给指针变量p,而char str=china;是将字符串常量china拷贝到字符数组,china的地址与数组str的地址不同。,5.2.5 常用字符串处理函数 在Turbo C的 string.h头文件中提供了一些专门用来处理字符串的函数,下面介绍其中几个最常用的函数。1字符串拷贝函数strcpy()一般调用格式:strcpy(str1,str2)其中,str1是地址表达式(一般为数组名或指针变量)str2可以是地址表达式(一般为数组名或为指针变量),也可以是字符串常量。功能:将str2指向的字符串拷贝到以str1为起始地址的内存单元。返回值:str1的

29、值。如:char str140,str2=china;strcpy(str1,str2);puts(str1);,输出结果为:china,说明:以str1开始的内存单元必须定义的足够大,以便容纳被拷贝的字符串。拷贝时连同字符串后面的0一起拷贝。不能用赋值语句将一个字符串常量赋给一个字符数组,也不能将一个字符数组赋给另一个字符数组,只能用strcpy()函数处理。如:char str110=china,str210;下面的赋值是不合法的:str2=str1;str2=USA;下面的赋值是合法的:strcpy(str2,str1);strcpy(str2,USA);,2字符串连接函数strcat(

30、)一般调用格式:strcat(str1,str2)其中,str1是地址表达式(一般为数组名或指针变量)。str2可以是地址表达式(一般为数组名或为指针变量),也可以是字符串常量。功能:把str2指向的字符串连接到str1指向的字符串的后面。返回值:str1的值。如:char str140=china,str2=beijing;strcat(str1,str2);puts(str1);输出结果为:chinabeijing,说明:以str1开始的内存单元必须定义的足够大,以便容纳连接后的字符串。连接后,str2指向的字符串的第一个字符覆盖了连接前str1指向的字符串的结束符0。只在新串的最后保留一

31、个0。连接后,str2指向的字符串不变。,3字符串比较函数strcmp()一般调用格式:strcmp(str1,str2)其中,str1和str2可以是地址表达式(一般为数组名或指针变量),也可以是字符串常量。功能:比较两个字符串。返回值:如果两个字符串相等,返回值为0;如果不相等,返回从左侧起第一次不相同的两个字符的ASCII码的差值。如:printf(%dn,strcmp(acb,aCb);输出结果为:32(c和C的ASCII码差值)说明:字符串比较是从左向右比较对应字符的ASCII码值。两个字符串比较不能用关系运算符,只能用strcmp()函数。不能用strcmp()函数比较其他型数据。

32、,4测试字符串长度函数strlen()一般调用格式:strlen(str)其中,str可以是地址表达式(一般为数组名或指针变量),也可以是字符串常量。功能:统计字符串str中字符的个数(不包括结束符0)。返回值:字符串中实际字符的个数。如:char str10=china;printf(%d,stren(str);输出结果是5,不是10,也不是6。,5字符串小写变大写函数strupr()一般调用格式:strupr(str)其中,str可以是地址表达式(一般为数组名或指针变量),也可以是字符串常量。功能:将字符串中的小写字母转换成大写字母。返回值:str的值,即字符串的首地址。如:puts(st

33、rupr(aB3c);输出结果为:AB3C。,6字符串大写变小写函数strlwr()一般调用格式:strlwr(str)其中,str可以是地址表达式(一般为数组名或指针变量),也可以是字符串常量。功能:将字符串中的大写字母转换成小写字母。返回值:str的值,即字符串的首地址。如:puts(strupr(aB3c);输出结果为:ab3c。【例5.9】有两个字符串,按由小到大的连接在一起。#include stdio.h#include string.h,main()char str120,str220,str360;gets(str1);gets(str2);if(strcmp(str1,str

34、2)0)strcpy(str3,str1);strcat(str3,str2);else strcpy(str3,str2);strcat(str3,str1);puts(str3);,运行结果ChinaAmericanAmericanChina,3.3 多维数组及指针除了一维数组外,C语言还允许使用二维、三维等多维数组,数组的维数没有限制。除了二维数组外,其他多维数组一般很少用到,所以下面重点介绍二维数组。3.3.1 二维数组的定义和初始化1二维数组的定义二维数组定义的一般形式为:类型标识符 数组名常量表达式1 常量表达式2其中,常量表达式1的值是行数,常量表达式2的值是列数。如:int a

35、34;,定义了一个整型的二维数组,数组名为a,行数为3,列数为4,共有12个元素,分别为:a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23。C语言中,对二维数组的存储是按行存放,即按行的顺序依次存放在连续的内存单元中。如二维数组a的存储顺序如图5.9所示。,C语言对二维数组a的处理方法是:把a看成是一个一维数组,数组a包含三元素:a0,a1,a2。而每个元素又是一个一维数组,各包含四个元素,如a0所代表的一维数组又包含四个元素:a00,a01,a02,a03。见图3.10。,由于系统并不为数组名分配内存,所以由a0、a1、a2组成的一维数组在内存并

36、不存在,它们只是表示相应行的首地址。C语言中,多维数组定义的一般形式为:类型标识符 数组名常量表达式1 常量表达式2 常量表达式n,2二维数组的初始化 全部元素初始化全部元素初始化时,第一维的长度,即行数可以省略,第二维的长度,即列数不能省略。可以用花括号分行赋初值,也可以整体赋初值。如:下列初始化是等价的:int a34=1,2,3,4,5,6,7,8,9,10,11,12;int a 4=1,2,3,4,5,6,7,8,9,10,11,12;int a 4=1,2,3,4,5,6,7,8,9,10,11,12;部分元素初始化部分元素初始化时,若省略第一维的长度,必须用花括号分行赋初值。没初

37、始化的元素,数值型数组时值为0,字符型数组时值为0。,如:下列初始化是等价的:int a34=1,2,3,4,0,5;int a34=1,2,3,4,0,5;int a 4=1,2,3,4,0,5;见图5.11。,下面是对二维字符型数组的初始化:char str36=china,USA,japan;三个一维数组str0,str1,str2各有6个元素,其值分别为:“china”、“USA”和“japan”。见图5.12。,5.3.2 二维数组元素的下标法引用 数组元素在使用时与同类型的普通变量相同,可以出现在表达式中,也可以被赋值。使用时要特别注意下标的范围。二维数组元素的下标表示形式为:数组

38、名表达式1 表达式2其中,表达式1和表达式2的类型任意,一般为算术表达式。表达式1的值是行标,表达式2的值是列标。【例3.10】求34矩阵的最小值,及其所在的位置(行号和列号)。,main()int a4=2,-8,20,0,9,5,-38,-34,10,32,4,-3;int i,j,row,col,min;min=a00;row=0;col=0;for(i=0;iaij)min=aij;row=i;col=j;printf(min=%d,row=%d,col=%d,min,row,col);运行结果:min=-38,row=1,col=2,5.3.3 二维数组的指针C语言规定,二维数组的数

39、组名代表整个二维数组的首地址,二维数组的数组名加1是加一行元素所占的字节数。二维数组元素的地址可以通过取地址符“,则a代表整个二维数组的首地址,a+i(0i2)是第i行的首地址。数组元素aij(0i2,j3)的地址为:&aij。根据前面介绍的二维数组的处理方法可知,a是由a0、a1和a2三个元素组成一维数组的数组名,而每个元素ai(0i2)又是由四个元素组成的一维数组的数组名,所以由一维数组元素的数组名表示法可以得到下列等价关系:*(a+i)与ai是等价的,代表一维数组ai的首地址,即第i行的首地址。ai+j,*(a+i)+j与&aij是等价的(0j3),代表数组元素aij的地址。,1指向数组

40、元素的指针变量指向二维数组元素的指针变量的定义与指向变量的指针变量的定义相同。如:int*p;定义p为指向整型变量的指针变量,若有下面赋值语句:p=a0;则把元素a00的地址赋给指针变量p,也就是说,指针变量p指向数组元素a00。,2指向由m个元素组成的一维数组的指针变量 指向数组元素的指针变量加(减)1,是加(减)一个数组元素所占的字节数,指向的元素是原来指向元素的下(上)一个元素。C语言中,也可以定义指向由m个元素组成的一维数组的指针变量,指针变量加(减)1,是加(减)整个一维数组所占的字节数,其定义的一般形式为:类型标识符(*指针变量名)常量表达式如:int(*p)4;其含义为:p是一个

41、指针变量,它指向包含4个整型元素的一维数组。p的值加(减)1,是加(减)4个整型数据所占的字节数。,用这种类型的指针变量可以指向二维数组中的一行,这时的m就是二维数组的列数。若有赋值语句:p=a;则p+i(0i2)是一维数组ai的首地址。由此可得到下列等价关系:*(a+i),*(p+i)和ai是等价的,即第i行的首地址。ai+j,*(a+i)+j,*(p+i)+j和&aij是等价的(0j3),即数组元素aij的地址。,5.3.4 二维数组元素的指针法引用1利用一维数组的数组名引用二维数组元素 因为ai+j和&aij是等价的,所以*(ai+j)和aij是等价的,其中ai是第i行一维数组的数组名。

42、因此,可以用一维数组名引用二维数组中的元素。其引用的一般形式为:*(一维数组名+表达式)其中,表达式的类型任意,一般为算术表达式,其值为二维数组元素的列标。如:*(a1+2-1)表示二维数组元素a11。另外,由于二维数组在内存中是按行连续存储,所以可以把二维数组a看成是数组名为a0的一维数组,二维数组元素aij对应的一维数组元素是:*(a0+i*列数+j)。如:*(a0+2*4+1)表示二维数组元素a21。,【例5.11】输出行标为1、列标为2的数组元素和行标为2、列标为1的数组元素。main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;printf(%4d

43、,*(a1+2);printf(%4dn,*(a0+2*4+1);运行结果 13 19,2利用指向二维数组元素的指针变量引用数组元素 用指向二维数组元素的指针变量引用二维数组元素的一般形式为:*(指针变量+表达式)其中,指针变量是指向二维数组元素的指针变量。表达式的类型任意,一般为算术表达式。若指针变量指向行标和列标都为0的数组元素,则引用的二维数组元素的行标为:(表达式)/列数,列标为:(表达式)%列数;否则引用的二维数组元素的行标为:(指针变量-数组名0+表达式)/列数,列标为:(指针变量-数组名0+表达式)%列数。,【例5.12】按行输出二维数组中的元素值。main()int a34=1

44、,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=运行结果:1 3 5 7 9 11 13 1517 19 21 23,3利用二维数组名引用数组元素*(a+i)+j和&aij等价*(*(a+i)+j)和aij等价。因此,可以利用二维数组的数组名引用二维数组中的元素。其引用的一般形式为:*(*(数组名+表达式1)+表达式2)其中,表达式1和表达式2的类型任意,一般为算术表达式。表达式1的值是行标,表达式2的值是列标。,【例5.13】计算44阶矩阵的周边元素值之和。main()int a44,i,j,sum;sum=0;for(i=0;i4;i+)for(j=0;

45、j4;j+)scanf(%d,*(a+i)+j);for(i=0;i4;i+)for(j=0;j4;j+)if(i=0|i=3|j=0|j=3)sum+=*(*(a+i)+j);printf(sum=%dn,sum);,运行结果:1 2 3 45 6 7 89 10 11 1213 14 15 16sum=102,4利用指向由m(二维数组列数)个元素组成的一维数组的指针变量引用二维数组元素由前面的讨论可知,若有定义:int a34,(*p)4=a;则*(p+i)+j和&aij等价,由此可得,*(*(p+i)+j)和aij等价。所以,二维数组元素可以用指向由多个元素组成的一维数组的指针变量引用,

46、其一般形式为:*(*(指针变量+表达式1)+表达式2)其中,指针变量是指向一维数组的指针变量,指向二维数组中的某一行。表达式1和表达式2的类型任意,一般为算术表达式。表达式2的值为要引用的二维数组元素列标。若指针变量指向第一行,则表达式1的值为要引用的二维数组元素行标;否则,要引用的二维数组元素行标为:,指针变量-二维数组名+表达式1若有定义:int a34,(*p)4=a+1;,则*(*(p+1)+3-1)表示数组元素a22。,【例5.14】输出44阶矩阵的任意一个元素的值main()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int row,col,(*p)4;p

47、=a;scanf(row=%d,col=%d,运行结果:row=2,col=1a21=10*(*(p+i)+j)与*(pi+j)和pij等价,5.4 指针数组,元素为指针类型的数组称为指针数组,也就是说,指针数组中的每个元素都是指针变量。指针数组的定义形式为:类型标识符*数组名常量表达式如:int*p4;定义了一个指针数组,数组名为p,它有4个元素,每个元素都是指向整型变量的指针变量。注意下列三种定义的区别:int p4;int(*p)4;int*p4;和普通数组一样,指针数组在内存中分配连续的存储空间,指针数组也可以初始化。指针数组元素在使用时与同类型的指针变量相同。,【例5.15】将5个字

48、符串按由小到大的顺序输出#define N 5#include string.hmain()char*name=China,Japan,USA,Russia,Canda;char*temp;int i,j;for(i=0;i0)temp=namei;namei=namej;namej=temp;for(i=0;iN;i+)printf(%sn,namei);,运行结果:CandaChinaJapanRussia USA,此程序的处理方法是:将字符串的地址按字符串由小到大的顺序重新存放到指针数组name中,即交换的是字符串的地址,而不是字符串本身。排序前后指针数组name的内容见图5.13(a)

49、和5.13(b)。,图5.13(a)交换前,图5.13(a)交换后,5.5 二级指针,在例5.14中,定义了一个指针数组name,它的元素是指针类型,其值为地址。既然name是数组,它的每一个元素都有相应的地址,name+i(0i4)是数组元素namei的地址。name+i就是指向数组元素namei的指针,name+i就是指向namei所指向对象的二级指针(指针常量)。见图5-13(a)。我们还可以定义指向指针变量的指针变量,其定义的一般形式为:类型标识符*变量名;如:char*p;p是指向字符型指针变量的指针变量,即指针变量p存储的内容是另一个字符型指针变量的地址。,二级指针变量可以初始化,

50、如:char*p=name;等价于char*p;p=name;把指针数组name的首地址赋给指针变量p,即p指向name0。使用二级指针变量可以存取和处理数据,在使用时,要注意其用法,如:int a=3,*p=输出结果:a=3,*p=3,*pp=3,【例5.16】用二级指针变量实现例5.15。#define N 5#include string.hmain()char*name=China,Japan,USA,Australia,Canda;char*temp;char*i,*j;for(i=name;i0)temp=*i;*i=*j;*j=temp;for(i=name;iname+N;i+

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号