第十二章 指针

59
第第第第 第第

Upload: jaxon

Post on 17-Mar-2016

112 views

Category:

Documents


6 download

DESCRIPTION

第十二章 指针. 变量 a. 变量 b. 变量 x. 变量 y. 变量 m. 变量 ch1. 1. 2000. 2002. 2. 2004. 3.4. 4.5. 2008. 3.124. 2012. 2020. a. 2021. b. 12.1  指针与指针变量 . 如: int a=1 , b=2 ; float x=3.4 , y = 4.5 ; double m=3.124 ; char ch1='a‘, ch2='b' ;. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第十二章    指针

第十二章 指针

Page 2: 第十二章    指针

第十二章 指针

12.1  指针与指针变量 如: int a=1 , b=2 ;   float x=3.4 , y = 4.5 ;    double m=3.124 ;   char ch1='a‘, ch2='b' ;

12

4.5

3.4

3.124

ab

20002002

2004

2008

2012

20202021

变量 a变量 b

变量 x

变量 y

变量 m

变量 ch1变量 ch2

一个地址唯一指向一个内存变量,我们称这个地址为变量的指针。如果将变量的地址保存在内存的特定区域,用变量来存放这些地址,这样的变量就是指针变量,通过指针对所指向变量的访问,也就是一种对变量的“间接访问”。

Page 3: 第十二章    指针

第十二章 指针

12

4.5

3.4

3.124

ab

20002002

2004

2008

2012

20202021

变量 a变量 b

变量 x

变量 y

变量 m

变量 ch1变量 ch2

1012

pa

1004

2012

2000200220042008

20202021

10001002

100610081010

10141016

pbpxpypm

pch1pch2

 设一组指针变量 pa 、 pb 、 px 、 py 、 pm 、 pch1 、 pch2 ,分别指向上述的变量 a 、 b 、 x 、 y 、 m 、 ch1 、ch2 ,指针变量也同样被存放在内存,二者的关系如图:

12.1  指针与指针变量 

Page 4: 第十二章    指针

第十二章 指针

指针定义的格式: 类型说明符 * 指针名; * 表示这是一个指针变量, 变量名即为定义的指针变量名; 类型说明符表示本指针变量所指向的变量的数据类型,也就是说一个指针变量只能指向同一类型的变量。 如: int *p1 ;  表示 p1 是一个指针变量,它的值是某个整型变量的地址。或者说 p1 指向一个整型变量。至于 p1 究竟指向哪一个整型变量,应由向 p1 赋予的地址来决定。

12.2  指针变量的定义与引用一、指针变量的定义 

Page 5: 第十二章    指针

第十二章 指针

赋值形式: & 变量名;  &:取地址符  &a 表示变量 a 的地址, &b 表示变量 b 的地址。变量本身必须预先说明。 指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。 指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。

12.2  指针变量的定义与引用二、指针变量的赋值 

Page 6: 第十二章    指针

第十二章 指针

设有指向整型变量的指针变量 p ,如要把整型变量 a 的地址赋予 p 可以有以下两种方式:1 )指针变量初始化的方法    int a ;   int *p=&a ;2 )赋值语句的方法    int a ;  int *p ;  p=&a ; 不允许把一个数赋予指针变量,下面的赋值是错误的: int *p ; p=1000 ; 被赋值的指针变量前不能再加“ *” 说明符,如写为 *p=&a 也是错误的。

12.2  指针变量的定义与引用二、指针变量的赋值 

Page 7: 第十二章    指针

第十二章 指针

指针变量只能进行赋值运算和部分算术运算及关系运算。(1) 取地址运算符 & :是单目运算符,其结合性为自右至左,其功能是取变量的地址。(2) 取内容运算符 * :是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在“ *” 运算符之后跟的变量必须是指针变量。 注意:在指针变量说明中,“ *” 是类型说明符,表示其后的变量是指针类型。而表达式中出现的“ *” 则是一个运算符用以表示指针变量所指的变量。

12.2  指针变量的定义与引用二、指针变量的运算 

Page 8: 第十二章    指针

第十二章 指针

[ 例 12.1] 指针变量程序举例。。main( ){ int *p1 , *p2 , i1 , i2 ; scanf(“%d , %d” , &i1 , &i2) ; p1=&i1 ; p2=&i2 ; printf(“%d , %d\n” , *p1 , *p2) ; p2=p1 ; printf(“%d , %d\n” , *p1 , *p2) ;} 若输入: 3 , 5则输出: 3 , 5 3 , 3

12.2  指针变量的定义与引用二、指针变量的运算 

Page 9: 第十二章    指针

第十二章 指针

[ 例 12.2] 从键盘输入两个整数,按由大到小的顺序输出。main( ){ int *p1 , *p2 , a , b , t ; scanf("%d , %d " , &a , &b) ; p1=&a ; p2=&b ; if(*p1<*p2) { t=*p1 ; *p1=*p2 ; *p2=t ; } printf("%d , %d\n" , a , b) ;}

12.2  指针变量的定义与引用二、指针变量的运算 

Page 10: 第十二章    指针

第十二章 指针

使用指针类型做函数的参数,实际向函数传递的是变量的地址。由于函数中获得了所传递变量的地址,在该地址空间的数据当函数调用结束后被物理地保留下来。因此,如果希望函数间传递的是地址,实参用变量的地址或指针变量,形参用指针变量。

12.3  指针变量做函数的参数

Page 11: 第十二章    指针

第十二章 指针

[ 例 12.3] 利用指针变量作为函数的参数,用函数的方法再次实现上述功能。main ( ){   void change() ; int *p1,*p2,a,b,*t ; scanf("%d , %d" , &a , &b) ; p1=&a ; p2=&b ; change(p1 , p2) ; / * 函数调用 * / printf("%d , %d\n" , *p1 , *p2) ;}void change(int *pt1 , int *pt2){ int t ; if(*pt1<*pt2) { t=*pt1 ; *pt1=*pt2 ; *pt2=t ; } return ;}

12.3  指针变量做函数的参数

Page 12: 第十二章    指针

第十二章 指针

指向数组元素的指针变量的定义与指向变量的指针变量的定义相同 如: int a[10] ;    int *p ; 对该指针元素赋值:  p=&a[0] ;  把 a[0] 元素的地址赋给指针变量 p ,即 p 指向

a 数组的第 0 号元素, 数组名代表数组的首地址,也就是第一个元素的地址。因此, p=&a[0] ;与 p=a ;等价。  

12.4  指针与数组一、指向数组元素的指针变量的定义与赋值

Page 13: 第十二章    指针

第十二章 指针

在定义指针变量时可以赋给初值:  int *p=&a[0] ;它等效于:  int *p ;  p=&a[0] ;   定义时也可以写成:    int *p=a ; 它的作用是将 a 的首地址(即 a[0] 的地址)赋给指针变量 p (而不是 *p )。

12.4  指针与数组一、指向数组元素的指针变量的定义与赋值

Page 14: 第十二章    指针

第十二章 指针

设 p 已定义为指针变量,并已给它赋了一个地址,使它指向某一个数组元素。如果有以下赋值语句:    *p=1 ; 表示对 p 当前所指向的数组元素赋以一个值(值为 1 )。 C 规定 p + 1 指向数组的下一个元素 ( 而不是将 p 值简单地加 1) 。 如,数组元素是实型,每个元素占 4 个字节,则 p + 1意味着使 p 的原值(地址)加 4 个字节,以使它指向下一元素。 p + 1 所代表的地址值实际上是 p + 1d ,

d 是一个数组元素所占的字节数(对整型, d=2 ;对实型, d = 4 ;对字符型, d = 1 )。

12.4  指针与数组二、通过指针引用数组元素

Page 15: 第十二章    指针

第十二章 指针

如果 p 的初值为& a[0] ,则: (1) p + i 和 a + i 就是 a[i] 的地址,或者说,它们指向 a数组的第 i 个元素。(2) *(p + i) 或 *(a + i) 是 p + i 或 a + i 所指向的数组元素,即 a[i] 。 (3) 指向数组的指针变量也可以带下标,如 p[i] 与 *(p + i)等价。(4) 当指针指向一串连续的存储单元时,可以对指针进行加上或减去一个整数,这种操作称为指针的移动。 (5) 指针不允许进行乘、除运算,移动指针时,不允许加上或减去一个非整数,对指向同一串连续存储单元的两个指针只能进行相减操作。

12.4  指针与数组二、通过指针引用数组元素

Page 16: 第十二章    指针

第十二章 指针

[ 例 12.4] 从键盘输入 10 个整数,存放在数组中,并输出数组的全部元素。用指针变量指向数组元素。main( ) { int i , a[10] , *p ; for (i=0 ; i<10 ; i ++ ) scanf("%d" , &a[i]) ; for(p=a ; p<a + 10 ; p ++ ) printf("%4d" , *p) ; printf("\n") ;}

12.4  指针与数组二、通过指针引用数组元素

Page 17: 第十二章    指针

第十二章 指针

注意:(1) 用 p ++使 p 的值不断改变,这是合法的,如果不用 p 而企图使 a 变化是不行的,如将上述程序的最后两行改为: for(p=a ; a<p + 10 ; a ++ ) printf("%d" , *a) ;(2) 要注意指针变量的当前值,请看下面的程序。

12.4  指针与数组二、通过指针引用数组元素

Page 18: 第十二章    指针

第十二章 指针

[ 例 12.5] 输出 a 数组的 10 个元素。main ( ) { int *p , i , a[10] ; p=a ; for(i=0 ; i<10 ; i ++ ) scanf ("%d" , p ++ ) ; for(i=0 ; i<10 ; i ++ , p ++ ) printf ("%d" , *p) ; printf ("\n") ;}输入: 1 2 3 4 5 6 7 8 9 0<回车 >运行结果 :22153 234 0 0 30036 25202 11631 8259 8237 28483

12.4  指针与数组二、通过指针引用数组元素

解决这个问题的办法是在第二个 for循环改为如下形式:for(i=0 , p=a ; i<10 ; i ++, p ++ ) printf("%d" , *p) ;

Page 19: 第十二章    指针

第十二章 指针

(3) 注意指针变量的运算。如果先使 p 指向数组 a( 即 p=a),则:①p++( 或 p+=1) , p 指向下一元素 a[1] ,若再执行 *p ,取了元素 a[1] 的值。②*p++ ,由于 ++ 和 * 同优先级,是自右而左的结合方向,因此它等价于 *(p++) 。作用是先得到 p 指向的变量的值( 即 *p) ,然后再使 p+1 。③* ( p++ )和 *++p 作用不同。前者是先取 *p 值。然后使 p移动,后者是先使 p移动,再取 *p 。若 p 的初值为 a (即& a[0] ),输出 * ( p++ )时,得 a[0] 的值,而输出 * ( ++p ),则得到 a[1] 的值。

12.4  指针与数组二、通过指针引用数组元素

Page 20: 第十二章    指针

第十二章 指针

④(*p)++ 表示 p 所指向元素值加 1 ,即 (a[0])++ ,如果 a[0]=3 ,则执行 (a[0])++ 后, a[0] 的值为4 。注意,是元素值加 1 ,而不是指针值加 1 。⑤如果当前 p 指向 a 数组中第 i 个元素,则:

*(p--) 相当于 a[i--] ,先取 p 值作“ *” 运算,再使 p 自减。 *(++p) 相当于 a[++i] ,先使 p 自加,再作 * 运算。 *(--p) 相当于 a[--i] ,先使 p 自减,再作 * 运算。

12.4  指针与数组二、通过指针引用数组元素

Page 21: 第十二章    指针

第十二章 指针

数组名可以用作函数的实参传给形参。由于数组名是一个地址值,对应的形参就应该是数组名或一个指针变量,但该指针必须与数组类型一致。

12.4  指针与数组三、数组名做函数参数

main ( )   f(int *arr) { int array[10] { ……        …… f(array)    }  ……   }

如:

Page 22: 第十二章    指针

第十二章 指针

数组名作为实参时,对应的函数首部可以写成如下三种形式: ①f( int *arr ) ②f( int arr[10] ) ③f( int arr[ ])

12.4  指针与数组三、数组名做函数参数

Page 23: 第十二章    指针

第十二章 指针

[ 例 12.6] 有一个一维数组 score ,内存放 10 个学生成绩,求平均成绩。float average(float * array){ int i ;   float aver , sum=0 ; for (i=0 ; i<10 ; i ++ ) sum=sum + array[i] ; aver=sum/10 ; return (aver) ;}main ( ){ float score[10] , ave ; int i ; printf ("Input 10 scores : \n") ; for (i=0 ; i<10 ; i ++ ) scanf("%f" , &score[i]) ; printf (“\n”) ; ave=average (score) ; printf ("Average score is %5.1f" , ave) ;}运行情况如下: Input 10 scores: 100 56 78 98.5 76 87 99 67.5

75 97<回车 >运行结果: Average score is 83.40

12.4  指针与数组三、数组名做函数参数

Page 24: 第十二章    指针

第十二章 指针

[ 例 12.7] 有程序如下:float average (float *array , int n){ int i ; float aver , sum=0 ; for(i=0 ; i<n ; i ++ ) sum=sum + array[i] ; aver=sum/n ; return (aver) ; }main ( ){ float score_1[5]={98.5,97,91.5,60,55} ; float score _2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,9

9.5}; printf ("A- average : %6.2f\n“,average (score_1,5)) ; printf ("B―average : %6.2f\n“,average (score_2,10)) ;}运行结果如下: A- average : 80.40 B- average : 78.20

12.4  指针与数组三、数组名做函数参数

Page 25: 第十二章    指针

第十二章 指针

[ 例 12.8] 定义长度为 10 的整型类型一维数组,并将数组中的元素按逆序存放后输出其值 (完成逆序存放操作时,只允许开辟一个临时存储单元 ) 。 main ( ){ int i , a[10] ; for(i=0 ; i<10 ; i ++ ) scanf("%d" , &a[i]) ; for(i=0 ; i<10 ; i ++ ) printf("%4d" , a[i]) ; printf(“\n”) ; fun(a , 10) ; for(i=0 ; i<10 ; i ++ )printf("%4d" , a[i]) ; printf("\n") ;}fun(int *a , int n){ int i , j , t ; for(i=0 , j=n- 1 ; i<j ; i ++, j-- ) { t=a[i] ; a[i]=a[j] ; a=[j]=t ; }}

12.4  指针与数组三、数组名做函数参数

Page 26: 第十二章    指针

第十二章 指针

[ 例 12.9] 已知一维数组中存放互不相同的 10 个整数,从键盘输入一个数,从数组中删除与该值相同的元素中的值。main ( ){ int i,t,a [10]={2,4,1,6,5,9,7,0,8,3} ; for(i=0 ; i<10 ; i ++ ) printf("%4d" , a[i]) ; printf(“\nlnput t:\n”) ; scanf("%d" , &t) ; del(a , t) ; for(i=0 ; i<9 ; i ++ ) printf("%4d" , a[i]) ; printf("\n") ;}del(int a[10] , int t ){ int i , j ; for(i=0 ; i<10 ; i ++ ) if(t== a[i]) break ; for(j=i ; j<9 ; j ++ ) a[j]=a[j + 1] ;}

12.4  指针与数组三、数组名做函数参数

Page 27: 第十二章    指针

第十二章 指针

[ 例 12.10] 用选择法对 10 个整数按由小到大顺序排列。main( ){ int i , a[10] ; for(i=0 ; i<10 ; i ++ ) scanf(“%d” , &a[i]) ; sort(a , 10) ; for(i=0 ; i<10 ; i ++ ) printf(“%d” , a[i]) ; printf("\n") ;} sort (int p[ ] , int n) { int i , j , k , temp ; for(i=0 ; i<n- 1 ; i ++ ) { k=i ;   for(j=k + 1 ; j<n ; j ++ ) if(p[j]<p[k]) k=j ; temp=p[i] ; p[i]=p[k] ; p[k]=temp ; }}

12.4  指针与数组三、数组名做函数参数

Page 28: 第十二章    指针

第十二章 指针

[ 例 12.11]假定 a 数组中已存放由小到大顺序排序的 10 个数,在 a 数组中插入一个数,插入后数组中的数仍有序。main ( ){ int I,x,a [11]={1,3,5,7,9,11,13,15,17,19} ; printf(“Input x : \n”) ; scanf("%d" , &x) ; for(i=0 ; i<10 ; i ++ )   printf ("%4d" , a[i]) ; printf(“\n”) ; insert(a , x) ; for(i=0 ; i<11 ; i ++ )   printf ("%4d" , a[i]) ; printf("\n") ;}insert(int *a , int x){ int i,j ; i=0 ; while(i<10 &&a[i]<x) i ++; for(j=9 ; j>=i ; j――) a[j + 1]=a[j] ; a[i]=x ;}

12.4  指针与数组三、数组名做函数参数

Page 29: 第十二章    指针

第十二章 指针

[ 例 12.12]求一维数组中值最大的那个元素的值,以及其所在的位置。main ( ){ int i , k , max ;  int a[10]={3,4,9,1,7,6,- 10,10,- 5,

2} ; for(i=0 ; i<10 ; i ++ ) printf("%d" , a[i]) ;   printf(“\n”) ;     max=find(a , &k) ;   printf("max=%d , k=%d\n" , max , k) ;}find(int a[10] , int *k){ int i , max ; max=a[0] ; *k=0 ;  for(i=0 ; i<10 ; i ++ ) if(max<a[i]) { max=a[i] ; *k=i ; }  return max ;  }

12.4  指针与数组三、数组名做函数参数

Page 30: 第十二章    指针

第十二章 指针

设已定义二维数组 a : int a[3][4]={{1,3,5,7},{9,11,13,15,15},{17,19,21,23}};( 1 ) a 是二维数组名,是二维数组的起始地址 ( 设地址为 200

0) 。即, a 指向 a 数组第 0 行, a 也是 0 行首地址。( 2 ) a + 1 是 a 数组第 1 行首地址,或者说 a + 1 指向第 1 行(地址为 2008 )。( 3 ) a[0],a[1],a[2] 是二维数组中三个一维数组(即三行)的名字,因此它们也是地址 ( 分别是 0 行, 1 行, 2 行的首地址 ) 。 ( 4 ) a[i]+j 是 i 行 j列元素的地址, *(a[i]+j) 是 i 行 j列元素的值。 ( 5 ) a[i] 与 *(a + i)无条件等价,这两种写法可以互换。

12.4  指针与数组四、指向多维数组的指针和指针变量

Page 31: 第十二章    指针

第十二章 指针

( 6 ) a[i][j] , *(a[i] + j) , *(*(a + i) + j)都是i 行 j列元素的值。( 7 )区别行指针与列指针的概念。例如 a + 1 和a[1]都代表地址 2008 。但 a + 1 是行指针。它指向一个一维数组。 a[1]( 即 *(a + 1)) 是列指针,它指向一个元素,它是 1 行 0列元素的地址。( 8 )可以定义指向一维数组的指针变量, 如:   int (*p)[4] ;    /* 称 p 为行指针 */ 定义 p 为指向一个含 4 个元素的一维数组的指针变量。

12.4  指针与数组四、指向多维数组的指针和指针变量

Page 32: 第十二章    指针

第十二章 指针

main ( ){ int a[3][4] ; int * p1 , (*p2)[4] ; p1=&a[3][4] ;     /*p1 是列指针 */ p2=a + 1 ;       /*p2 是行指针 */}不能写成:p1=a + 1 ; p2=&a[3][4] ; /* 类型不一致 */

12.4  指针与数组四、指向多维数组的指针和指针变量

Page 33: 第十二章    指针

第十二章 指针

12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式 可以用两种方法实现一个字符串:1. 用字符数组实现[ 例 12.13] 用字符数组实现的示例。main ( ) { char string [ ]= " I love China! " ; printf("%s\n" , string) ;}string 是数组名,它代表字符数组的首地址

Page 34: 第十二章    指针

第十二章 指针

2. 用字符指针实现可以不定义数组,而定义一个字符指针。用字符指针指向字符串中的字符。[ 例 12.14] 用字符指针实现的示例。main ( ){ char *string= " I love China! " ; printf("%s\n" , string) ;}注意:在内存中,字符串的最后被自动加了一个‘ \0’ ,因此在输出时能确定字符串的终止位置。通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组输出它的全部元素的,只能逐个元素输出。

12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式

Page 35: 第十二章    指针

第十二章 指针

[ 例 12.15] 将字符串 a复制到字符串 b (用指针变量来处理)。main ( ){ char a[ ] = "I am a boy. " , b[20] , *p1 , *p2 ; int i ; for(p1=a , p2=b ; *p1!= '\0' ; p1 ++, p2 ++ ) *p2=*p1 ; /* 只复制有效字符 */ *p2='\0' ;   /* 赋字符串结果标志 */ printf ("String a is : %s\n" , a) ; printf ("String b is : %s\n" , b) ;}

12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式

Page 36: 第十二章    指针

第十二章 指针

字符数组与字符指针变量的区别:( 1 )字符数组由若干个元素组成,每个元素存放一个字符,而字符指针变量中存放的是地址(字符串的首地址),决不是将字符串放到字符指针变量中。( 2 )对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。 char str[14] ; str="I love China!" ;  而对字符指针变量,可以采用下面方法赋值: char *a ; a="I love China! " ;  但注意赋给 a 的不是字符串,而是字符串的首地址。

12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组

Page 37: 第十二章    指针

第十二章 指针

( 3 )对字符指针变量赋初值时:char   *a="I love China! " ;  等价于:char   *a ; a="I love China! " ;而对数组初始化时:char str[14]={ " I love China! "} ;不等价于:char str[14] ; str[ ]="I love China! " ;即数组可以在变量定义时整体赋初值,但不能在赋值语句中整体赋值。

12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组

Page 38: 第十二章    指针

第十二章 指针

( 4 )在定义一个数组时,在编译时即已分配内存单元,有固定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以存放一个地址值,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋以一个地址值,则它并未具体指向哪一个字符数据。如:  char str [10] ;     scanf ("%s" , str) ; 是可以的,而下面的形式是错误的:     char * a ;     scanf(“%s” , a) ;( 5 )指针变量的值是可以改变的。

12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组

Page 39: 第十二章    指针

第十二章 指针

[ 例 12.16] 程序示例。main ( ){ char a=“I love China! ” ; /*a 指向存放字符 'I' 的存储单元 */ a=a + 7 ;    /*a 指向存放字符 'C' 的存储单元 */ printf("%s" , a) ;    /* 将输出 China! /*}数组名代表一个固定的地址,它的值是不能改变的。说明:定义一个指针变量并使它们指向一个字符串后,也可以用下标形式引用指针所指的字符串中的字符

( 与前面介绍的数组类似 ) 。

12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组

Page 40: 第十二章    指针

第十二章 指针

(6) 不要随意使用无确定指向的指针。有时为了防止无确定指向的指针破坏有用数据,给暂时不用的指针赋 NULL 。如:  int *p ; p=NULL ;其中 NULL 是在文件 stdio.h 中定义的符号常量,它的代码值为 0 ,这时称 p 为空指针。以下三种写法等价:   p=NULL ; p='\0' ; p=0 ;使用 NULL 时,应在程序的开头加 #include<stdio.h> 。当企图通过空指针访问一个存储单元时,将显示一个出错信息。

12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组

Page 41: 第十二章    指针

第十二章 指针

将一个字符串从一个函数传递到另一个函数,可以用地址传递的办法,即用字符数组名或用指向字符串的指针变量作参数。和数组一样,函数的首部有三种说明形式,而且形参也是指针变量。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了字符串。

12.6 字符串指针做函数参数

Page 42: 第十二章    指针

第十二章 指针

[ 例 12.17] 将字符数组中的字符串按逆序存放后输出。 #include<stdio.h> #include<string.h> main( ) {   int i , j ; char ch [80] ;   gets(ch) ; puts (ch) ; j=strlen (ch)- 1 ; fun(ch , j) ;   puts (ch) ; } fun (char *p , int j) { int i ;   char t , *q ;   q=p + j ;  for( ; p<q ; p ++, q-- )   { t=*p ; *p=*q ; *q=t ;} } 运行结果是:asdfgh<回车>asdfgh hgfdsa

12.6 字符串指针做函数参数

Page 43: 第十二章    指针

第十二章 指针

[ 例 12.18] 从键盘输入一个字符串,计算该字符串的长度。不要用 strlen 函数。 #include< stdio.h> main ( ) { int len ; char a [80] ;  gets (a) ;  puts (a) ; len=lenth(a) ; printf("%d\n" , len) ; }lenth(char *p){ char *q=p ;   /* p 和 q都指向数组 a*/  while (*q!= '\0') q ++; /* 只移动 q , p 不变 */ return q- p ;   /*q- p 表示共移动几个存储单元 */}运行结果是  asdfgh<回车>  asdfgh 6

12.6 字符串指针做函数参数

Page 44: 第十二章    指针

第十二章 指针

[ 例 12.19]编一程序,将两个字符串连接起来。不要用 strcat 函数。 #include< stdio.h> main ( ) { char sl [80] , s2[40] ;    printf("\n Input string1: ") ;   gets(s1) ;     printf("\n Input string2:) ;   gets(s2) ;  scat(s1 , s2) ;  printf("\n New string : %s" ,

s1) ; }scat(char *s1 , char *s2) { while(*s1!='\0') s1 ++;   while(*s2!='\0') { *s1=*s2 ; s1 ++ ; s2 ++; } *s1='\0' ;}运行情况: Input string 1 : country<回车>   Input string 2 : side <回车> New string : countryside

12.6 字符串指针做函数参数

Page 45: 第十二章    指针

第十二章 指针

[ 例 12.20]编写一个程序,将字符数组 from 中的全部字符拷贝到字符数组 to 中。不要用 strcpy 函数。拷贝时, '\0' 也要拷贝过去。 '\0' 后面的字符不拷贝。#include< stdio.h>#include< string.h>main ( ){ char from [80] , to[80] ;   printf("Input , string : ") ;  scanf("%s , from) ;   strcopy(from , to) ;     printf("Copied string : %s/n" , to) ; }strcopy(char *from , char *to){ int i ;  for(i=0 ; i< =strlen (from) ; i ++ ) to[i]=from[i] ; }运行结果:   Input string : student<回车>   Copied string : student

12.6 字符串指针做函数参数

Page 46: 第十二章    指针

第十二章 指针

[ 例 12.21]编写一个程序,比较字符数组 s1 和 s2 。不要用 strcmp 函数。#include< stdio.h>main ( ){   int a ; char s1[80] , s2[80] ; gets (s1) ; gets(s2) ; puts(s1) ; puts(s2) ; a=strcomp(s1 , s2) ; if(a>0) printf("(s1 : %s)>(s2 : %s)\n" , s1 , s2) ; if(a= = 0) printf("(s1 : %s)=(s2 : %s)\n" , s1 , s2) ; if(a<0) printf("(s1 : %s)<(s2 : %s)\n" , s1 , s2) ;}strcomp(char *s1 , char *s2){ while(*s1= = *s2&&. *s1!= '\0') {s1 ++; s2 ++; }  return *s1- *s2 ;}运行结果是: boy<回车> girl<回车> boy girl (s1 : boy)< (s2 : girl)

12.6 字符串指针做函数参数

Page 47: 第十二章    指针

第十二章 指针

可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配一个入口地址。这个入口地址就称为函数时的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。

12.6 字符串指针做函数参数一、用函数指针变量调用函数

Page 48: 第十二章    指针

第十二章 指针

main ( ){ int max (int , int ) ;  int (*p) (int , int ) ;     int a,b,c ; p=max ;   scanf (“%d , %d “,&a,&b) ; c=(*p)(a,b) ; printf("max=%d\n " , c) ;}int max (int x , int y)   /* 定义 max 函数 */{ int z ;  if(x > y) z = x ;  else z=y ;  return (z) ;}main ( ){ int max (int , int ) ; int (*p) (int , int ) ; int a,b,c ; p=max ;   scanf (“%d,%d”,&a,&b) ; c=(*p)(a,b) ; printf("max=%d\n " , c) ;}int max (int x , int y)   /* 定义 max 函数 */ { int z ;  if(x > y) z = x ;  else z=y ;  return (z) ;}

12.6 字符串指针做函数参数一、用函数指针变量调用函数

Page 49: 第十二章    指针

第十二章 指针

说明:(1) 指向函数的指针变量的一般定义形式为: 数据类型标识符 (* 指针变量名 )( 类型 参数 1, 类型 参数 2, ….) “ 数据类型标识符”是指函数返回值的类型,旧版本允许省略后一括号中的内容。(2) 函数的调用可以通过函数名调用。也可以通过函数指针调用 ( 即用指向函数的指针变量调用 ) 。(3) (*p)(int , int ) 表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。

12.6 字符串指针做函数参数一、用函数指针变量调用函数

Page 50: 第十二章    指针

第十二章 指针

(4) 在给函数指针变量赋值时,只需要给出函数名而不必给出参数。如: p=max ; 因为是将函数入口地址赋给 p ,而不牵涉到实参与形参的结合问题。不能写成“ p=max (a ,b) ;”形式。

(5) 用函数指针变量调用函数时,只需将( *p )代替函数名即可( p 为指针变量名),在( *p )之后的括弧中根据需要写上实参,

(6) 对指向函数的指针变量,象 p+n 、 p++ 、 p--等运算无意义的。(7) 函数指针变量常用的用途之一是把指针作为参数传递到其它函数。

12.6 字符串指针做函数参数一、用函数指针变量调用函数

Page 51: 第十二章    指针

第十二章 指针

函数的指针变量也可以作为参数,以便实现函数地址的传递,也就是将函数名传给形参。 它的原理可以简述如下:有一个函数(假设函数名为 sub ),它有两个形参( x1 和 x2 ),定义 x1 和 x2 为指向函数的指针变量,在调用函数

sub 时,实参用两个函数名 f1 和 f2 给形参传递函数地址,这样在函数 sub 中就可以调用 f1 和 f2 函数了。

12.6 字符串指针做函数参数二、把指向函数的指针变量作为函数参数

Page 52: 第十二章    指针

第十二章 指针

一个函数不仅可以带回简单类型的数据,而且可以带回指针型的数据,即地址。如:#include < stdio.h>char *fun (char *) ;    /* 指针类型也要原型说明 */main ( ){ char ch ='a' , *p , *q ; p=&ch ; q=fun(p) ;   /* 调用结束后 q才有确定的指向,相当于 q="bag" ; */ puts (q)}char * fun (char *s){ char *t="big" ; *( t + 1 ) = *s ;     /* *s 相当于主函数中的 *p 即 ch   */ return t ;      /*返字符串的首地址 */}输出结果是:bag

12.7 返回指针值的函数

Page 53: 第十二章    指针

第十二章 指针

一个数组,其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都是指针变量。 形式:类型标识符  * 数组名 [ 数组长度说明 ] ;如: int *p[4] ; 注意:不要写成 int ( *p ) [ 4 ] ;这是指向一维数组的指针变量。指针数组使字符串处理更方便灵活。

12.8 指针数组和指向指针的指针一、指针数组

Page 54: 第十二章    指针

第十二章 指针

[ 例 12.22] 在五个字符串中,找出最大者,并使下标为 0 的指针数组元素指向它。#include < stdio.h>#include < string.h> main ( ) { int i , k ; char *temp,*str [ ]={ "Follow”,"QBASIC”,"Great”,"FORTRA

N”,"Computer"}; k=0 ; for ( i =1 ; i< 5 ; i ++ )   if(strcmp(str[k],str[i])< 0)    k=i ;  if (k!=0) { temp=str[0] ; str[0]=str[k] ; str[k]=temp ; } printf("The largest string is\n%s\n" , str[0]) ; }运行结果是: QBASIC

12.8 指针数组和指向指针的指针一、指针数组

Page 55: 第十二章    指针

第十二章 指针

指针变量也有地址,这地址可以存放在另一个指针变量中。如果变量 p 中存放了指针变量 q的地址,那末 p 就指向指针变量 q 。指向指针数据的指针变量,简称为指向指针的指针。 定义一个指向字符型指针数据的指针变量,形式如下: char * * p ; 如果有 char *q="abc" ;则 p=&q ;是合法的。 *p 相当于 q , **p 相当于 *q ,因此, **p 中的值为 'a' ,

12.8 指针数组和指向指针的指针二、指向指针的指针

Page 56: 第十二章    指针

第十二章 指针

[ 例 12.23] 写出下面程序地运行结果。main ( ) { char *str [ ] ={“ENGLISH”,“MATH”,“MUSIC”, “PHYS

ICS”,"CHEMISTRY"} ; char **q ; int num ; q=str ; for(num=0 ; num<5 ; num ++ ) printf("%s\n" , *(q ++ )) ;}运行结果是:ENGLISHMATH MUSIC PHYSICS CHEMISTRY

12.8 指针数组和指向指针的指针二、指向指针的指针

Page 57: 第十二章    指针

第十二章 指针

main 函数可以有参数,形式:   main (int argc , char **argv )  argc 和 argv 是 main 函数形参。实参从命令行得到。 命令行形式:命令名 参数 1 参数 2 …… 参数 n  argc 是指命令行中参数的个数,参数含文件名,因此 argc≥1 。 argv 是指向字符指针数组的指针

( 即指向指针的指针 ) ,它指向的指针数组的每一元素都指向一个字符串,

12.8 指针数组和指向指针的指针三、 main 函数的命令行参数

Page 58: 第十二章    指针

第十二章 指针

[ 例 12.24] 下面程序的文件名为 file.c ,写出程序的运行结果。 main ( int argc , char * argv [ ] ) { argc-- ; argv++ ;   while(argc> 0) { printf("%s" , *argv) ;     argc-- ; argv++ ;   }}如果命令输入:   c :> file Computer and C Language<回车>则输出:    Computer and C Language

12.8 指针数组和指向指针的指针三、 main 函数的命令行参数

Page 59: 第十二章    指针

第十二章 指针

如有命令行: filel China Beijing   argc 的值等于 3 , argv[0] 指向‘ filel’ ,

argv[1] 指向‘ China’ , argv[2] 指向‘ Beijing’ 。

12.8 指针数组和指向指针的指针三、 main 函数的命令行参数