320 likes | 443 Views
第16讲 数组的指针和字符串的指针. 一、数组的指针 1.数组与地址 2.数组元素的访问 二、字符串指针 1.字符串指针的定义 2.字符指针与字符数组的区别 三、指针作为函数参数 1.数组名作为函数参数 2.字符指针作为函数参数. 一、数组的指针. C 语言规定: 数组名代表数组(元素)的首地址,即第一个元素的地址。 若有: int a[10], *p=a; 则: a 与 & a[0] 是等价的 指针变量 p 为数组的指针
E N D
第16讲 数组的指针和字符串的指针 • 一、数组的指针 • 1.数组与地址 • 2.数组元素的访问 • 二、字符串指针 • 1.字符串指针的定义 • 2.字符指针与字符数组的区别 • 三、指针作为函数参数 • 1.数组名作为函数参数 2.字符指针作为函数参数
一、数组的指针 • C语言规定: • 数组名代表数组(元素)的首地址,即第一个元素的地址。 • 若有:int a[10], *p=a; • 则: a 与 &a[0] 是等价的 • 指针变量 p 为数组的指针 • 数组的指针:数组的起始地址,即数组元素的首地址。 • 数组元素的指针:数组元素的地址。
1.数组与地址 • 对数组的首地址加上偏移量x就可以得到其它元素的地址。 • 例: &a[1] 表示数组元素a[1]的地址 • 等价于 a+1、 p+1 • &a[x] 表示数组元素a[x]的地址 • 等价于 a+x、 p+x
2.数组元素的访问 • 下标法: • 用 a[i] 的形式存取数组元素。 • 地址法: • 用 *(a+i)的形式存取数组元素。 • 指针法: • 用指针变量p指向数组的首地址,然后通过移动指针存取数组元素。 • 如p=a, p+i。
例a 用下标法存取数组元素 • main( ) { int a[10], i; • for ( i=0; i<10; i++ ) scanf("%d", &a[i]); • for ( i=0; i<10; i++ ) printf("%d", a[i]); • printf("\n"); }
例b用地址法存取数组元素 • main( ) { int a[10], i; for ( i=0; i<10; i++ ) scanf("%d", a+i ); • for ( i=0; i<10; i++ ) printf("%d", *(a+i)); • printf("\n"); }
数组元素的访问举例 • 例c用指针法存取数组元素。(即通过指针指向数组的首地址,然后通过移动指针存取数组元素。) main( ) { int a[10], *p, i; for (i=0, p=a; i<10; i++) scanf("%d", p+i); for (i=0, p=a; i<10; i++) printf("%d", *(p+i)); printf("\n"); } main( ) { int a[10], *p; for ( p=a; p<a+10; p++) scanf("%d", p); for ( p=a; p<a+10; p++) printf("%d", *p); printf("\n"); }
0 0 2 2 *p p++ 等价于 4 4 6 6 8 8 例c 说明 p = & a *p++
注意: • 数组名是一个常量,不允许重新赋值。 • 指针变量是一个变量,可以重新赋值。 • p+i和a+i均表示数组元素a[i]的地址,均指向a[i]。 • *(p+i)和*(a+i)均表示p+i和a+i所指对象的内容,即a[i]。 • *p++:等价于*(p++)。其作用:先得到*p,再使p=p+1。
(*p)++:表示将p所指向的变量(元素)的值加1。即等价于 a[i]++ 。 • 例:int a[5]={0, 2, 4, 6, 8}, *p; • p=a+2; • (*p)++; • printf("%d\n",*p ); • 程序段输出为:5
例 • main( ) • { int a[5]={0,2,4,6,8},*p,x; • p=a; (*p)++; • p=a+1; ++(*p); • p=a+2; (*p)--; • p=a+3; --(*p); • for (x=0;x<=4;x++) • printf("%d ", a[x] ); • printf("\n"); • } 程序运行结果: 1 3 3 5 8
指向数组元素的指针也可以表示成数组的形式,即允许指针变量带下标,如*(p+i)可以表示成p[i]。指向数组元素的指针也可以表示成数组的形式,即允许指针变量带下标,如*(p+i)可以表示成p[i]。 • 但需注意,如果p不指向a[0],则p[i]和a[i]是不一样的。 • 如 p=a+3; • 由于p指向a[3],所以p[3]就相当于a[6]而不是a[3]。 • 这种方式容易出错,一般不提倡使用。
二、字符串指针 • 字符串的处理是用字符型数组来实现的。 • 用char型数组处理的字符串都可以用char型指针来处理。通常把char型指针称为字符串指针或字符指针。
1.字符串指针的定义 • 在程序中定义一个字符指针变量,并将字符串的首地址赋给它,然后通过字符指针变量来访问字符串。 • 例如: • char str[ ]="C programming"; • char *p; • p=str; • 或: • char *str="C programming";
例: • /* 用字符数组实现字符串操作 */main( ) { • char str[]="Welcome to study C !"; int i; printf("%s\n",str); for (i=0;i<=7;i++) printf("%c",str[i]); printf("\n"); } 程序运行结果为:Welcome to study C !Welcome
例 • /* 用字符指针实现字符串操作 */main() { char *str="Welcome to study C !"; int i; printf("%s\n",str); for(i=0;i<=7;i++) printf("%c",*(str+i)); printf("\n"); }
字符指针与字符数组的区别 • 字符数组是由若干个元素组成,每个元素存放一个字符;而字符指针变量存放的是字符串的首地址。 • 赋值方式不同。字符数组只能对各个元素分别赋值,而字符指针只需赋给字符串的首地址就可以了。 • 字符指针占用的内存要少于字符数组。 • 指针变量的值是可以改变,而字符数组的数组名虽然代表地址,但它的值是不会变化。
区别举例: • 如: char *str; • str="Welcome to study C !"; • 以下对字符数组的赋值是错误的: • char str[80]; • str[ ]="Welcome to study C !";
例 将字符串s1复制到字符串s2。 • main( ) • { char s1[ ]=“copy string”, s2[30]; • char *p1=s1, *p2=s2; • int i; • for ( ; *p1!=‘\0’; p1++,p2++) *p2=*p1; • *p2=‘\0’; • printf(“string s2=”); • for (i=0; s2[i]!=‘\0’; i++) • printf(“%c”, s2[i]); • printf(“\n”); • } 程序运行结果为:string s2=Copy string
三、指针作为函数参数 1.数组名作为函数参数 • 特点: • 数组名表示数组元素的首地址。 • 在函数调用时,传递的是数组元素的首地址。 • 实参与形参的传递是“值传递”。 • 实参数组与形参数组共用一段存储单元。 • 可以用指向数组的指针变量作函数的参数。
以下列出实参和形参使用数组名或指针变量的四种情况:以下列出实参和形参使用数组名或指针变量的四种情况: • 实参: 数组名 数组名 指针变量 指针变量 • 形参: 数组名 指针变量 数组名 指针变量
例:已知一个一维数组a[11]中有10个数,求出其中前n个数的和, 并放入a[10]中。其中n由键盘输入。 #include <stdio.h> sum(int *q,int n) { int i,s=0; int *t; t=q; /* t与q都指向数组a的第一个元素 */ for (i=0;i<n;i++,q++) s+=*q; *(t+10)=s; /* t+10指向数组元素a[10] */ }
main() { int num, a[11]={1,2,3,4,5,6,7,8,9,10}; int *p=a; scanf ("%d",&num); sum(p,num); printf("%d\n",a[10]); }
2.字符指针作为函数参数 • 将一个字符串从一个函数传递到另一个函数,可以使用地址传递的方法,即用字符数组名作为参数或用指向字符串的指针变量作为参数。 • 在被调用函数中可以改变字符串的内容,而在主调函数中可以得到被改变了的字符串。 • 由于字符串是按照字符数组形式存储的,所以对字符串中字符的引用也可以用下标法或指针法。
例设有两个字符串"Hello"和" World!",试将它们连接在一起成为一个字符串。 • main( ) { char str1[15]="Hello",str2[]=" World!"; int i; strcat(str1,str2); printf("String str1=%s\n",str1); } • strcat(char *s,char *t) • { while(*s!='\0') s++; /* 使s指向字符串str1的末尾 */while(*t!='\0') { *s=*t; t++; s++; } *s='\0'; /* 在s后加上字符串结束标志 */ } 程序运行结果为:String str1=Hello World!
例输入一串小写字符将其转换为大写字符 utol( char *x ) { int i; for ( i=0; *(x+i)!='\0'; i++ ) *(x+i)-=32; } • main() • { int i; • char a[100]; • printf(“Input\n”); • scanf(“%s”,a); • utol( a ) ; • printf( "%s\n", a ); • }
例:编写一个函数string_cut(char *str,char c),如果字符串str 中包含字符变量c,则输出其后的字符序列,否则输出空字符。 #include <stdio.h> string_cut(char *str , char c) { for (;*str!='\0'&&*str!=c;str++); puts(str); }
void main() { char string[20]="Beijing"; char ch; scanf("%c",&ch); string_cut(string,ch); }
例:有3个字符串存放在一维指针数组中,编写一个程序,找出3个串中ASCII码最大的一个字母并输出。例:有3个字符串存放在一维指针数组中,编写一个程序,找出3个串中ASCII码最大的一个字母并输出。 分析:类似于二维数组,在每个字符串中查找最大的字母。
#include <stdio.h> char max(char *s[ ]) {int i; char ch,*p; ch=s[0][0]; for (i=0;i<3;i++) { p=s[i]; for (; *p;p++) if(*p>ch) ch=*p; } return ch;}
void main( ) { char *str [ ]={“sfawe”,”fghj”,”abcrs”}, c; c=max(str); printf(“Max=%c\n”,c); } 程序运行结果为:Max=w