《C语言编程 第8章指针.ppt》由会员分享,可在线阅读,更多相关《C语言编程 第8章指针.ppt(83页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第八章第八章 指指 针针关键:关键:(1)变量使用的两种方式)变量使用的两种方式(2)指针定义与使用时形式相同但含义不同)指针定义与使用时形式相同但含义不同(3)指针的各种运算)指针的各种运算(4)数组名与指针变量的区别)数组名与指针变量的区别(5)要通过一个函数改变多个值的方法)要通过一个函数改变多个值的方法预预 备备 知知 识识内存:内存:就是内部存储器,是由存储单元组成 的。它的特点是存储单元是线性连续 的。存储单元的最小单位是字节。1.内存的概念内存的概念地址:地址:为了访问内存中的某个存储单元,我们 要为它编号,这种编号称为内存地址。通过地址我们就能够访问该地址所标 识的存储单元。2
2、.地址的概念地址的概念变量的地址变量的地址:变量在内存中总占用几个连续的:变量在内存中总占用几个连续的 字节,开始字节的地址,就是变量的地址。字节,开始字节的地址,就是变量的地址。20072007存储单元u指针为函数提供修改变量值的手段指针为函数提供修改变量值的手段 u指针为指针为C的动态内存分配系统提供支持的动态内存分配系统提供支持 u指针为动态数据结构(如例链表、队列、二叉树等)指针为动态数据结构(如例链表、队列、二叉树等)提供支持提供支持 u指针可以改善某些子程序的效率指针可以改善某些子程序的效率 为什么引入指针的概念为什么引入指针的概念u学习原则学习原则一定要学会一定要学会其实通常的应
3、用很简单与使用变量几乎无异其实通常的应用很简单与使用变量几乎无异u使用原则使用原则永远要清楚每个指针指向了哪里永远要清楚每个指针指向了哪里永远要清楚指针指向的位置是什么永远要清楚指针指向的位置是什么关于指针的原则关于指针的原则 8.1 8.1 指针及其相关概念指针及其相关概念 指针:指针:一个变量的地址称为该变量的指针。一个变量的地址称为该变量的指针。指针变量:指针变量:若一个变量专用于存放另一个变量若一个变量专用于存放另一个变量 的地址(指针),则该变量称为指针变量。的地址(指针),则该变量称为指针变量。指针的指向:指针的指向:当把变量的地址存入指针变量后,当把变量的地址存入指针变量后,我们
4、就可以说我们就可以说这个指针指向了该变量这个指针指向了该变量。变量的存取方法:变量的存取方法:直接存取和间接存取。直接存取和间接存取。直接存取:直接存取:直接根据变量名存取数据。直接根据变量名存取数据。间接存取:间接存取:通过指针变量存取相应变量的数据通过指针变量存取相应变量的数据。88.2.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量一、指针变量的定义一、指针变量的定义 一般形式:一般形式:类型标识符类型标识符 *变量名变量名 ;例如:int*ptr1,*ptr2;指针变量的类型:指明了该指针指向的内存空指针变量的类型:指明了该指针指向的内存空 间所存储的数据类型。间所存
5、储的数据类型。在定义指针变量时要注意以下几个问题在定义指针变量时要注意以下几个问题:变量名变量名ptr2前面的前面的“*”不能省略,如果写成不能省略,如果写成 int*ptr1,ptr2;则则ptr2被定义为整型变量,而非整型指针变量。被定义为整型变量,而非整型指针变量。定义中的定义中的“*”表示所定义的变量是指针变量,但表示所定义的变量是指针变量,但 指针变量名是指针变量名是ptr1、ptr2,而非,而非*ptr1、*ptr2。指针变量只能指向定义时所规定类型的变量。指针变量只能指向定义时所规定类型的变量。这个规定的类型称为该指针变量的这个规定的类型称为该指针变量的“基类型基类型”。如:上例
6、中ptr1、ptr2只能指向整型变量,不 能指向实型或字符型变量。其“基类型”相同,都是整型。定义指针变量后,并未确定该变量指向何处。定义指针变量后,并未确定该变量指向何处。也就是说该变量的值是不确定的。也就是说该变量的值是不确定的。在引用指针在引用指针 变量前必须首先让它指向一个变量,这一点非变量前必须首先让它指向一个变量,这一点非 常重要。常重要。u共性共性在内存中占据一定大小的存储单元在内存中占据一定大小的存储单元先定义,后使用先定义,后使用u特殊性特殊性 它的内容只能是地址,而不能是数据它的内容只能是地址,而不能是数据必须初始化后才能使用,否则指向不确定的存储单元必须初始化后才能使用,
7、否则指向不确定的存储单元只能指向同一基类型的变量只能指向同一基类型的变量可参与的运算:加、减一个整数,自增、自减、关系、可参与的运算:加、减一个整数,自增、自减、关系、赋值赋值指针变量与其它类型变量的对比指针变量与其它类型变量的对比二、指针变量的运算二、指针变量的运算 指针运算符指针运算符(“&”和和“*”)“&”(地址运算符地址运算符):取变量的存储地址。取变量的存储地址。“*”(引用运算符引用运算符):是取指针所指向变量的内容是取指针所指向变量的内容。例如:&a 是求变量a的地址。ptr指向了i变量,*ptr表示i的值,即3 我们还可以用这种方法实现对变量的改变:我们还可以用这种方法实现对
8、变量的改变:*ptr=15;等价于等价于 i=15;由由此此可可见见:通过指针运算符“*”可以引用一个变量。如:当ptr已经指向变量i后,*ptr就等同于i。进一步理解进一步理解“&”和和“*”:“&”运算和运算和“*”运算是一对互逆运算。运算是一对互逆运算。&*ptr&i ptr *&i *ptr i等价于 指针的赋值运算指针的赋值运算(=)指针的赋值运算指针的赋值运算:就是把地址赋值给指针变量。:就是把地址赋值给指针变量。指针的赋值运算可以是以下三种方式指针的赋值运算可以是以下三种方式:使用取地址运算符,把地址值赋值给指针变量。使用取地址运算符,把地址值赋值给指针变量。如:int i,*p
9、i;pi=&i;把指针变量的值赋给另一个指针变量。把指针变量的值赋给另一个指针变量。如:int i,*pa,*pb;pa=&i;pb=pa;给指针变量赋值为符号常量给指针变量赋值为符号常量NULL。说说明明:NULL是是一一个个空空指指针针,表表示示该该指指针针变变量量的的值值没没有有意意义义。作作用用是是为为了了避避免免对对没没有有被被初初始始化化的的指指针针变变量的非法引用。量的非法引用。NULL 的定义在的定义在“stdio.h”中。中。如:int*pi;pi=NULL;说明:说明:在定义指针变量时,可以立即将一个地址值在定义指针变量时,可以立即将一个地址值 赋给指针变量,这就是指针变量
10、的初始化。赋给指针变量,这就是指针变量的初始化。指针变量的初始化也是指针的赋值运算。指针变量的初始化也是指针的赋值运算。如:如:float flt,*f_ptr=&flt;注意:这不是给注意:这不是给*f_ptr赋值赋值。指针变量间的赋值和引用应保证基类型相同。指针变量间的赋值和引用应保证基类型相同。若有定义:若有定义:int*p,i;float*q,x;则:则:q=&i;p=&x;移动指针的运算移动指针的运算 指针的加减运算(指针的加减运算(+、)、)指针的自加自减运算(指针的自加自减运算(+,-,+=,-=)1 1指针的指针的+、运算、运算 指针整数指针指针+、说明说明:指针与整型值加减的
11、结果是指针指针与整型值加减的结果是指针,表示使该指针,表示使该指针指向该指针下移或上移存储单元个数指向该指针下移或上移存储单元个数(整型值整型值)之后之后的内存地址。存储单元的大小就是该指针的数据类的内存地址。存储单元的大小就是该指针的数据类型所需的内存大小。型所需的内存大小。例如:ptr+n(指针ptr,n为整数)这个指针值代表的内存单元的地址是:ptr+n*d(其中d是指针所指向变量的数据类型所占内存字节数),即指针移动了n个元素。指针与指针的加运算毫无意义,所以指针与指针的加运算毫无意义,所以指针与指针指针与指针 没有加运算没有加运算。指针与指针的减运算要求相减的两个指针属于同指针与指针
12、的减运算要求相减的两个指针属于同 一类型,其结果是整数,表示两个指针之间的数一类型,其结果是整数,表示两个指针之间的数 据的个数。其结果值的计算公式是:据的个数。其结果值的计算公式是:ptr1-ptr2=(ptr1的值-ptr2的值)/指针的数据类型所占的字节数 例如:int*ptr1,*ptr2,*ptr3,x;int ary5=2,4,8,16,32;ptr1=&ary0;ptr2=&ary3;ptr3=ary;x=ptr2-ptr1;x 的值是32 2指针的指针的+、-、+=+=、-=-=运算运算 +、+=+=:是移动指针到下一个或下几个存储单元。是移动指针到下一个或下几个存储单元。-、
13、-=-=:是移动指针到上一个或上几个存储单元。是移动指针到上一个或上几个存储单元。例如:例如:int*ptr,ary5=2,4,6,8,10;ptr=ary;ptr+=3;ptr-;想一想:想一想:*ptr+和(和(*ptr)+有什么有什么 的区别的区别?关系运算关系运算 基类型相同的两个指针进行比较运算,其意义是两个指针的位置比较,结果是逻辑值。指针运算的程序举例:指针运算的程序举例:把把a,b按大小顺序输出。按大小顺序输出。main()int*p1,*p2,*p,a,b;a=45;b=76;p1=&a;p2=&b;if(*p1*p2)p=p1;p1=p2;p2=p;printf(a=%d,
14、b=%d,max=%d,min=%d,a,b,*p1,*p2);输出结果:a=45,b=76,max=76,min=45n 用简单变两作函数的参数只能有用简单变两作函数的参数只能有一个一个返回值返回值n 用指针变量作函数的参数可有用指针变量作函数的参数可有多个多个返回值返回值n 用数组名作函数的参数也可有用数组名作函数的参数也可有多个多个返回值返回值函数的返回值函数的返回值字符串字符串(String)(String)字符数组、字符指针字符数组、字符指针u字符串字符串一串以一串以00结尾的字符在结尾的字符在C C语言中被看作字符串语言中被看作字符串用双引号括起的一串字符是字符串常量,用双引号括起
15、的一串字符是字符串常量,C C语言自动为其添语言自动为其添加加00终结符终结符C C语言并没有为字符串提供任何专门的表示法,完全使用字语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理符数组和字符指针来处理u字符数组字符数组每个元素都是字符类型的数组每个元素都是字符类型的数组ncharchar string100;string100;u字符指针字符指针指向字符类型的指针指向字符类型的指针nChar Char*p;*p;u数组和指针可以等同看待,上面三者本质上是一回事数组和指针可以等同看待,上面三者本质上是一回事u定义方法不同定义方法不同 char str10;char*p
16、tr;u赋值方法和含义不同赋值方法和含义不同 char str10;strcpy(str,”china”);/*正确正确*/str=”china”;/*错误错误*/char*ptr;ptr=”china”;字符指针变量与字符数组的区别字符指针变量与字符数组的区别u在定义一个数组时,在编译时即分配单元,有确定地在定义一个数组时,在编译时即分配单元,有确定地址,而定义一个字符指针变量时,如未对它赋初值,址,而定义一个字符指针变量时,如未对它赋初值,则其所指数据是不定的,因而使用是危险的则其所指数据是不定的,因而使用是危险的。u例如,输入字符串时例如,输入字符串时 char char str10;s
17、tr10;scanfscanf(%s(%s,strstr););/*/*正确正确*/char char*a;*a;scanfscanf(%s(%s,a);,a);/*/*错误错误*/应为:应为:charchar*a;*a;char char str10;str10;a=a=strstr;scanf(%sscanf(%s,a);,a);/*/*正确正确*/字符指针变量与字符数组的区别字符指针变量与字符数组的区别字符指针变量与字符数组的区别u初始化含义不同初始化含义不同 char *pstr=”china”;等价于等价于 char *pstr;pstr=”china”;char str6=”chi
18、na”;不等价于不等价于 char str6;str=”china”;u字符指针是字符指针是变量变量,而数组名是地址,而数组名是地址常量常量三、指针变量作为函数参数三、指针变量作为函数参数 指针可以用作函数参数,这在调用函数希望指针可以用作函数参数,这在调用函数希望改变参数的值时非常有用。改变参数的值时非常有用。例如:用指针变量编写实现两个数的交换的函数例如:用指针变量编写实现两个数的交换的函数void swap(int*p1,int*p2);main()int x1=100,x2=200;printf(x1=%d,x2=%dn,x1,x2);swap(&x1,&x2);printf(x1=%
19、d,x2=%dn,x1,x2);void swap(int*p1,int*p2)int temp;temp=*p1;*p1=*p2;*p2=temp;图示交换过程中存储单元内容的变化:图示交换过程中存储单元内容的变化:123456想一想:想一想:如果函数的参数不用指针而用整数,如果函数的参数不用指针而用整数,能否实现值的交换?为什么?能否实现值的交换?为什么?通过函数调用得到通过函数调用得到n个要改变的值的方法:个要改变的值的方法:在主调函数中设在主调函数中设n个变量,用个变量,用n个指针变量指向它们;个指针变量指向它们;将指针变量作实参,将这将指针变量作实参,将这n个变量的地址传给所调用个变
20、量的地址传给所调用 的函数的形参;的函数的形参;通过形参指针变量,改变该通过形参指针变量,改变该n个变量的值;个变量的值;主调函数中就可以使用这些改变了值的变量。主调函数中就可以使用这些改变了值的变量。注意:注意:不能企图通过改变指针形参的值而使指不能企图通过改变指针形参的值而使指 针实参的值改变。针实参的值改变。如:上例如:上例swap函数中不能写成:函数中不能写成:temp=p1;p1=p2;p2=temp;8.3 8.3 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量 一、数组的指针和指向数组的指针变量的概念一、数组的指针和指向数组的指针变量的概念 数组的指针数组的指针:是
21、数组的起始地址。是数组的起始地址。数组元素的指针数组元素的指针:是数组元素的地址。是数组元素的地址。当指针变量指向数组或数组元素时,它就当指针变量指向数组或数组元素时,它就是是指向数组的指针变量指向数组的指针变量。C规定规定:数组名代表数组的首地址(起始地址),数组名代表数组的首地址(起始地址),也就是第一个元素的地址。也就是第一个元素的地址。当指针变量当指针变量p指向数组时,指向数组时,p+1指向数组指向数组 的下一个元素。假设一个整型元素占两的下一个元素。假设一个整型元素占两 个字节,个字节,p+1是使是使p的地址加的地址加2个字节。个字节。如:如:int a10,*p;则:则:p=a;与
22、与 p=&a0;等价等价称指针变量称指针变量p指向数组元素指向数组元素a0 p+i、a+i、&ai 都是都是ai的地址。的地址。二、数组元素的引用二、数组元素的引用 1.用下标法引用数组元素用下标法引用数组元素如:如:a3=45;b25=200;2.用指针法引用数组元素用指针法引用数组元素 假如:假如:int a10,*p,i;p=a;则:则:*(p+i)、*(a+i)则代表元素则代表元素ai *(p+i)也可以写成也可以写成pi *(p+i)、*(a+i)、ai、pi 等价,等价,都代表数组都代表数组a的第的第i+1个元素。个元素。程序举例:输出程序举例:输出10个元素数组中的全部元素。个元
23、素数组中的全部元素。方法二:通过数组名计算数组元素地址,找出元素的方法二:通过数组名计算数组元素地址,找出元素的 值。值。main()int a10=54,65,8,2,3,56,8,21,57,98,i;for(printf(n),i=0;i10;i+)printf(%4d,*(a+i);方法一:下标法。方法一:下标法。main()int a10=54,65,8,2,3,56,8,21,57,98,i;for(printf(n),i=0;i10;i+)printf(%4d,ai);方法三:用指针变量指向数组元素方法三:用指针变量指向数组元素 main()int a10=54,65,8,2,3
24、,56,8,21,57,98,*p,i;p=a;for(printf(n),i=0;i10;i+)printf(%4d,*p+);以上三种方法,利用指针变量效率最高。以上三种方法,利用指针变量效率最高。说明:说明:指针变量与数组名的区别:指针变量与数组名的区别:指针变量是地址变量,指针变量是地址变量,数组名是地址常量数组名是地址常量。即。即指针变量的内容可以在程序运行过程中被改变;而指针变量的内容可以在程序运行过程中被改变;而数组名一旦被定义,它的值就不能被改变了。数组名一旦被定义,它的值就不能被改变了。例如:int i,*p,a6;则:p=&i;a=&i;a+;a+=i;不能给常量赋值利用指
25、针变量编程时特别要注意指针变量利用指针变量编程时特别要注意指针变量 的当前值。的当前值。例如:通过指针变量输入输出a数组元素。main()int*p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);for(printf(“n”),i=0;i10;i+)printf(“%6d”,*p+);应插入语句 p=a;注意:注意:*p+、*(p+)、(*p)+、*(+p)的含义的含义 n 实参是实参是数组名数组名,形参也是形参也是数组名数组名n 实参是实参是数组名数组名,形参是形参是指针变量指针变量n 实参是实参是指针变量指针变量,形参是形参是数组名数组名n 实参是实参是指针变
26、量指针变量,形参也是形参也是指针变量名指针变量名以下四种情况是等价的以下四种情况是等价的三、数组名作函数的参数三、数组名作函数的参数 例如:f(int arr,int n)main()int array10;f(array,10);现在解释:实际上,能够接受并存放地址值的只能是指针变量。因此,C编译系统都是将形参数组名作为指针变量来处理的。上例中f(int arr,int n)等价于等价于 f(int*arr,int n)。使用形参数组的概念只是为了与实参数组对应,直观,便于理解而已。例:从例:从10个数中找出其中最大值和最小值。个数中找出其中最大值和最小值。void max_min(int
27、a,int n,int*max,int*min);main()int i,a=2,4,1,6,7,32,45,75,45,90,max,min;for(printf(The original array=),i=0;i10;i+)printf(%5d,ai);max_min(a,10,&max,&min);printf(max=%d min=%d,max,min);void max_min(int a,int n,int*max,int*min)int i;*max=*min=a0;for(i=0;in;i+)if(*maxai)*min=ai;上例中如果形参数组用指针变量,则程序如下:上例中
28、如果形参数组用指针变量,则程序如下:void max_min(int*x,int n,int*max,int*min);main()int i,a10=2,4,1,6,7,32,45,75,45,90,max,min;for(printf(The original array=),i=0;i10;i+)printf(%5d,ai);max_min(a,10,&max,&min);printf(=%d min=%d,max,min);void max_min(int*x,int n,int*max,int*min)int i;*max=*min=*x;for(i=1;in;i+,x+)if(*m
29、ax*x)*min=*x;数组名做函数参数小结数组名做函数参数小结:如果有一个实参数组,想在函数中改变此数组如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参都可用数组名或指针变量的元素的值,实参与形参都可用数组名或指针变量其对应关系有以下其对应关系有以下4种情况:种情况:实参与形参都用数组名;实参与形参都用数组名;实参用数组名,形参用指针变量;实参用数组名,形参用指针变量;实参、形参都用指针变量;实参、形参都用指针变量;实参为指针变量,形参用数组名。实参为指针变量,形参用数组名。注意:注意:用指针变量作实参时一定要有确定的值。用指针变量作实参时一定要有确定的值。例:实参、形参都用
30、指针变量的形式例:实参、形参都用指针变量的形式main()int a10,*p;p=a;f(p,10);f(int*x,int n)例:实参为指针变量,形参用数组名。例:实参为指针变量,形参用数组名。main()int a10,*p;p=a;f(p,10);f(int x,int n)四、二维数组的指针四、二维数组的指针 1二维数组的指针概念二维数组的指针概念 在在C语言中,一个二维数组可以看成是一语言中,一个二维数组可以看成是一个一维数组,其中每个元素又是一个包含若干个一维数组,其中每个元素又是一个包含若干元素的一维数组。元素的一维数组。假如有定义:假如有定义:int a23;则则C语语言言
31、编编译译程程序序认认为为a数数组组是是由由a0,a1两两个个元元素素组组成成的的一一维维数数组组,a0和和a1分分别别是是包包含含三三个个元元素素的的一一维维数数组组名名,分分别别代代表表a数数组组元元素素的的起起始始地地址址(即即a0是是第第0行行元元素素的的首首地地址址,a1是是第第1行行元元素素的的首首地地址址)。因因此此,a和和a0是是两两个个基基类型不同的指针常量类型不同的指针常量。指针与二维数组一维数组一维数组a a1 a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23行地址行地址列地址列地址列地址列地址列地址列地址a0+0 a0+1 a
32、0+2 a0+3a2+0 a2+1 a2+2 a2+3a1+0 a1+1 a1+2 a1+3一维数组一维数组a2一维数组一维数组a1一维数组一维数组a0a0 a2 a+0&a0 a+1&a1 a+2&a2 指针与二维数组na 代表代表二二维数组的首地址,维数组的首地址,第第0行行的地址的地址na+i 代表代表第第i行行的地址的地址n*(a+i)即即 ai 代表代表第第i行第行第0列列的地址的地址n*(a+i)+j 即即 ai+j 代表代表第第i行第行第j列列的地址的地址n*(*(a+i)+j)即即 aij 代表代表第第i行第行第j列列的的元素元素行地址行地址行地址行地址转变成转变成转变成转变成
33、列地址列地址列地址列地址指针与二维数组u与元素与元素aijaij 的的地址地址等价的几种引用方式等价的几种引用方式n&aijaij nai+jai+j n*(a+i)+j*(a+i)+j n&(*(&(*(a+i)ja+i)j u与元素与元素aijaij 的几种等价的引用方式的几种等价的引用方式naijaij n*(ai+j)*(ai+j)n*(*(a+i)+j)*(*(a+i)+j)n(*(*(a+i)ja+i)j 2通过指针引用二维数组元素通过指针引用二维数组元素假如有定义:假如有定义:int a35,i,j;(其中(其中0i 3,0j 5)则:则:ai和和*(a+i)(无条件等价)都是第
34、(无条件等价)都是第i行第行第0列列 元素的地址,那么元素的地址,那么ai+j、*(a+i)+j、&a00+5*i+j都是第都是第i行第行第j列元素的地址。列元素的地址。数组数组a中任意元素中任意元素aij的引用可以表示成如的引用可以表示成如 下几种形式:下几种形式:aij、*(ai+j)、*(*(a+i)+j)、(*(a+i)j、*(&a00+5*i+j)3通过一个行指针变量引用二维数组的元素通过一个行指针变量引用二维数组的元素 定义一个由定义一个由m个元素组成的一维数组的指个元素组成的一维数组的指针变量的一般形式:针变量的一般形式:类型标识符类型标识符 (*(*指针变量名指针变量名)m;)
35、m;例如:假若有语句例如:假若有语句 int a23,(*p)3;p=a;注意:注意:*p两侧的圆括号不可缺少。两侧的圆括号不可缺少。则:则:p是一个指向由是一个指向由3个整型元素组成的一个整型元素组成的一 维数维数 组的指针变量。组的指针变量。p指向指向a数组,数组,p+1指向数组指向数组a的下一行首地的下一行首地 址,址,a和和p的基类型相同,则的基类型相同,则a数组中任意元数组中任意元 素素aij还可以如下表示:还可以如下表示:*(pi+j)、*(*(p+i)+j)、(*(p+i)j、pij 例:使用行指针变量访问数组元素。例:使用行指针变量访问数组元素。main()float fa51
36、0,(*pf)10=fa;int i,j;for(i=0;i5;i+)for(j=0;j10;j+)*(*(pf+i)+j)=i*j;for(i=0;i5;i+)for(puts(),j=0;j10;j+)printf(%.0f,faij);例u任意输入英文的星期几,在查找星期表后输出其对应的任意输入英文的星期几,在查找星期表后输出其对应的数字。数字。char weekDay710=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;表表表表7-1 7-1 星期表的内容星期表的内容星期表的内容星期表的内容0Sunday1Monday
37、2Tuesday3Wednesday4Thursday5Friday6SaturdayweekDay0weekDay0weekDay1weekDay1weekDay2weekDay2weekDay3weekDay3weekDay4weekDay4weekDay5weekDay5weekDay6weekDay6Sunday0Monday0Tuesday0Wednesday0Thursday0Friday0Saturday0#include main()int i,pos;int findFlag=0;char x10;char weekDay10=Sunday,Monday,Tuesday,We
38、dnesday,Thursday,Friday,Saturday;printf(Please enter a string:);scanf(%s,x);for(i=0;iy)z=x;else z=y;return z;8.7 8.7 指针数组和指向指针的指针指针数组和指向指针的指针 一、指针数组一、指针数组 指针数组:指针数组:就是数组中每个元素是基类型相同就是数组中每个元素是基类型相同 指针变量。指针变量。定义指针数组的一般形式定义指针数组的一般形式:类型标识符类型标识符*指针变量名指针变量名 常量表达式常量表达式;例如:例如:int*p2;含意:含意:p是一个一维指针数组,每个元素都是是一
39、个一维指针数组,每个元素都是 一个指向整型变量的指针变量。可以将一个指向整型变量的指针变量。可以将 整型变量的地址赋值给元素整型变量的地址赋值给元素p0或或p1。注意:注意:区别区别 int*p2 、int (*p)2 的含意。的含意。二、指针数组的应用二、指针数组的应用 1.利用指针数组处理多个串利用指针数组处理多个串 方法方法:先用指针数组指向字符数组:先用指针数组指向字符数组,再处理。再处理。main()char name80=aaa,bbb,ccc,ddd,eee;char*pname10,i;for(i=0;i5;i+)pnamei=namei;for(i=0;i5;i+)puts(
40、pnamei);main()/*与用行指针解决上述问题比较与用行指针解决上述问题比较*/char name80=aaa,bbb,ccc,ddd,eee;char(*pname)80=name,i;for(i=0;i5;i+)puts(pnamei);方法方法:用指针数组指向字符串常量。:用指针数组指向字符串常量。main()char *pname10=aaa,bbb,ccc,ddd,eee;int i;for(i=0;i5;i+)puts(pnamei);2.用指针数组指向动态内存用指针数组指向动态内存 void指针类型介绍:指针类型介绍:新标准增加了新标准增加了void指针类型,它用于定义一
41、个指指针类型,它用于定义一个指针变量,但不指定它是指向哪种类型数据。在将它针变量,但不指定它是指向哪种类型数据。在将它的值赋给另一个指针变量时要进行强制类型转换使的值赋给另一个指针变量时要进行强制类型转换使之适合于被赋值的变量的类型。之适合于被赋值的变量的类型。例如:例如:char *p1;int a=2;void *p2;p2=&a;p1=(char*)p2;强制类型转换强制类型转换void指针变量定义指针变量定义 同样,可用同样,可用 p2=(void*)p1;将将p1的值转换成的值转换成void 指针类型。指针类型。可以将一个函数定义为可以将一个函数定义为void 指针类型。表示指针类型
42、。表示该函数返回的是一个地址,它指向空类型,如需该函数返回的是一个地址,它指向空类型,如需要引用此地址,也需要根据情况进行类型转换。要引用此地址,也需要根据情况进行类型转换。如如,库函数:库函数:void*malloc(unsigned size);功能:分配功能:分配size字节的存储区。字节的存储区。函数调用例函数调用例:char*p;p=(char*)malloc(60);分配分配60字节的存储区,并返回该字节的存储区,并返回该内存区的地址,并赋值给内存区的地址,并赋值给p。void sort(char*ps,int n);#define N 5main()char*ps100,i;fo
43、r(i=0;iN;i+)psi=(char*)malloc(60);for(i=0;iN;i+)gets(psi);sort(ps,N);for(i=0;iN;i+)puts(psi);void sort(char*ps,int n)int i,k;char*p,s100;for(i=0;in-1;i+)for(k=i+1;kn;k+)if(strcmp(psi,psk)0)p=psi;psi=psk;psk=p;例:用指针数组指向动态内存,进行字符串的排序。例:用指针数组指向动态内存,进行字符串的排序。3.指针数组作指针数组作main函数的形参函数的形参 main函数是由系统调用的,可以有参
44、数。函数是由系统调用的,可以有参数。可执行文件名可执行文件名 参数参数1 1 参数参数2 2 参数参数n n 实参是和命令一起给出的,也就是在实参是和命令一起给出的,也就是在DOS提提示符下,输入本程序的可执行文件名和需要传给示符下,输入本程序的可执行文件名和需要传给main函数的参数,命令行的一般形式为:函数的参数,命令行的一般形式为:main函数实参函数实参:带参数的带参数的main函数的原型是:函数的原型是:main(int argc,char*argv);命令行参数命令行参数(包括包括可执行文件名)可执行文件名)的数目的数目n+1指针数组,各元素分别指向命令指针数组,各元素分别指向命令
45、行中的各参数(包括可执行文件行中的各参数(包括可执行文件名),即字符串的首址名),即字符串的首址例:若以下面程序编译后生成可执行程序例:若以下面程序编译后生成可执行程序 file.exe,在在DOS提示符下按下述形式执行程序:提示符下按下述形式执行程序:file China(参数(参数1)Bejing(参数(参数1)Shenyang(参数(参数1)写出程序运行结果。写出程序运行结果。#include main(int argc,char*argv)while(argc0)printf(“%sn”,argvargc);运行结果:运行结果:ShenyangBejingChina三、指向指针的指针变
46、量三、指向指针的指针变量 指指向向指指针针的的指指针针变变量量(也也称称多多级级指指针针)只只能存放指针变量的地址能存放指针变量的地址。定义形式:定义形式:类型标识符类型标识符 *指针变量名指针变量名;例如:例如:int*q,*p,i=5;p=&i;q=&p;5i20002000p4000q4000注意:注意:要使用一个多级指针要使用一个多级指针指向目标值,必须连续使用指向目标值,必须连续使用指针运算符指针运算符“*”。例如:上例中例如:上例中*q就是就是i的值。的值。含意:使指针变量含意:使指针变量p指向指向i,指针变量,指针变量q指向指向p。main main()()intint i;i;
47、char char*ptrptr=Pascal,Basic,FortranPascal,Basic,Fortran,Java,VisualJava,Visual C;C;char char*p;*p;p=p=ptrptr;for for(i=0;i5;i+)(i=0;i*p2)swap(p1,p2);if(*p1*p3)swap(p1,p3);if(*p2*p3)swap(p2,p3);printf(n%6d%6d%6d,*p1,*p2,*p3);void swap(int*p,int*q)int x;x=*p;*p=*q;*q=x;习题习题8.2:输入:输入3个字符串,按由小到大的顺序输出。
48、个字符串,按由小到大的顺序输出。void swap(char*ps1,char*ps2);main()char s1=abc,s2=rst,s3=xyz;if(strcmp(s1,s2)0)swap(s1,s2);if(strcmp(s1,s3)0)swap(s1,s3);if(strcmp(s2,s3)0)swap(s2,s3);printf(n%10s%10s%10s,s1,s2,s3);void swap(char*ps1,char*ps2)char ps100;strcpy(ps,ps1);strcpy(ps1,ps2);strcpy(ps2,ps);习题习题8.9:写一函数,将一个:
49、写一函数,将一个33的矩阵转置。的矩阵转置。main()int a33=1,2,3,4,5,6,7,8,9,i,j;for(i=0;i3;i+)for(puts(),j=0;j3;j+)printf(%6d,aij);move(a);for(i=0;i3;i+)for(puts(),j=0;j3;j+)printf(%6d,aij);move(int(*p)3)int i,j,t;for(i=0;i3;i+)for(j=0;j=A&*p=a&*p=0&*p=9)num+;else if(*p=)space+;p+;printf(n upc=%d lowc=%d num=%d space=%d,
50、upc,lowc,num,space);习题习题8.11:对:对10个等长的字符串排序并输出。个等长的字符串排序并输出。void sort(char(*p)60);main()char s1060,i;for(i=0;i10;i+)gets(s+i);sort(s);for(i=0;i10;i+)puts(s+i);void sort(char(*p)60)int i,j;char s60;for(i=0;i9;i+)for(j=i+1;j10;j+)if(strcmp(pi,pj)0)strcpy(s,pi);strcpy(pi,pj);strcpy(pj,s);8.12:用指针数组处理上一