Download presentation
Presentation is loading. Please wait.
1
第八章 指针
2
第八章 指针 8.1 指针的基本知识 8.2 指针与维数组 8.3 指针与字符串 8.4 指针数组与指向多级指针 8.5 指针与函数
3
第八章 指针 本章学习目标 理解指针的概念 学会使用指针 理解指针作为函数参数的特点 学会用指针作为函数的参数 理解指针与数组之间的关系
第八章 指针 本章学习目标 理解指针的概念 学会使用指针 理解指针作为函数参数的特点 学会用指针作为函数的参数 理解指针与数组之间的关系 学会用指针引用数组 理解指针与字符串之间的关系 学会用字符串指针处理字符串 学会定义函数其返回值为指针 了解函数指针的用法
4
8.1 指针的基本知识 计算机内存储器是由字节组成。内存中字节是连续排列并按一定的规则编号,这个编号通常称为地址。
8.1 指针的基本知识 计算机内存储器是由字节组成。内存中字节是连续排列并按一定的规则编号,这个编号通常称为地址。 在C语言中,定义的每个对象(如变量、数组、函数等)编译系统都为它分配了足够大的内存单元,内存单元占一个或多个字节,每个对象所占的字节数由对象的类型决定,内存单元第一个字节的地址称为首地址,在C程序中称为指针。
5
8.1 指针的基本知识 程序中: int a=10; double k=23.5; 变量a 变量k 10 23.5 地址 内存 …...
8.1 指针的基本知识 地址 内存 程序中: int a=10; double k=23.5; …... ... 2000 2001 变量a 2002 10 2003 2004 2005 23.5 变量k 2011 …...
6
8.1 指针的基本知识 1。指针变量的定义: 类型 *变量名; 例: int *p; 2。定义指针变量并初始化
8.1 指针的基本知识 1。指针变量的定义: 类型 *变量名; 例: int *p; 35 x &x p 2。定义指针变量并初始化 int x=35, *p=&x; // 如果指针变量p存储了x的地址,通常称p指向x,或称p的对象是x。图表示了指针变量p、变量x之间的指向关系。
7
8.1 指针的基本知识 指针基本操作 py y (2000) 1.取地址操作 &运算符求变量的地址, 如,&x 运算结果是变量x的地址。
8.1 指针的基本知识 指针基本操作 1.取地址操作 &运算符求变量的地址, 如,&x 运算结果是变量x的地址。 2. 间接访问操作 *运算符,间接访问指针所指向的对象。 如: int y, *py; py=&y; *py=23;//将23赋给py指向的对象(即变量y) py y (2000) &y (2000) 23
8
8.1 指针的基本知识 例8.1 取地址运算符“&”和间接访问运算符“*”的使用示例 #include<stdio.h>
8.1 指针的基本知识 例8.1 取地址运算符“&”和间接访问运算符“*”的使用示例 #include<stdio.h> void main() { int a=100,*p; p=&a; // 取变量a的地址赋给p printf("a=%d, *p=%d\n",a,*p); *p=200; // 给p所指向的变量赋值 *p+=1; // pa所指向的变量加1 } 程序执行: a=100,*p=100 a=200,*p=200 a=201,*p=201
9
8.1 指针的基本知识 例8.2 用指针变量使指针所指向的变量交换值。 /* 例8.2源程序,利用指针修改变量值。 */
8.1 指针的基本知识 例8.2 用指针变量使指针所指向的变量交换值。 /* 例8.2源程序,利用指针修改变量值。 */ #include<stdio.h> void main() { int a=10,b=20,t; int *p1=&a,*p2=&b; printf("a=%d,b=%d,*p1=%d,*p2=%d\n",a,b,*p1,*p2); t=*p1; *p1=*p2; *p2=t; } 程序执行: a=10,b=20,*p1=10,*p2=20 a=20,b=10,*p1=20,*p2=10
10
8.1 指针的基本知识 3.赋值操作 同类型指针变量之间可以进行赋值。 float x,*p1=&x,*p2;
8.1 指针的基本知识 3.赋值操作 同类型指针变量之间可以进行赋值。 float x,*p1=&x,*p2; char ch,*q1=&c,*q2; p2=p1; q2=q1; p2=q1; 错误 q2=p1; 错误
11
8.1 指针的基本知识 指针作函数的参数 在函数中通过指针操作,间接访问指针所指向的变量,达到修改主调函数中变量值的目的。
12
8.1 指针的基本知识 例8.3下面程序定义了两个函数swap1和swap2,它们分别是用变量和指针变量作为函数的参数。在主函数中,分别调用这两个函数,观察主函数中变量a、b值的变化。 #include <stdio.h> void swap1(int x,float y) // 用整型变量作为函数参数 { int t; t=x; x=y; y=t; } void swap2(int *p,int *q) // 用指针变量作为函数的参数 { int t; t=*p; *p=*q; *q=t;
13
8.1 指针的基本知识 void main() { int a=3,b=5; swap1(a, b); //函数调用时,把a、b的值传给形参
8.1 指针的基本知识 void main() { int a=3,b=5; swap1(a, b); //函数调用时,把a、b的值传给形参 printf("After calling swap1:a=%d b=%d\n",a,b); a=3; b=5; swap2(&a, &b); //函数调用时,把a、b的地址传给形参 printf("After calling swap2:a=%d b=%d\n",a,b); } 程序执行 After calling swap1:a=3 b=5 After calling swap2:a=5 b=3
14
8.1 指针的基本知识 例8.4 编函数,求一元二次方程a·x2+b·x+c=0的根(a≠0)的两个实根,并返回1或0分别表示方程有实数解或无实数解。 用两个指针变量作为函数参数,函数调用时使它指向主函数中存储方程根的变量。 int root(float a,float b,float c,float *p1,float *p2) //p1,p2指针变量 { float d; d=b*b-4*a*c; if(d>=0) { *p1=(-b+sqrt(d))/(2*a); //方程根存到p1指向的对象中 *p2=(-b-sqrt(d))/(2*a); return 1; // 方程有实数解 } else return 0; // 表示方程无实数解
15
8.1 指针的基本知识 void main() { float a,b,c, x1, x2; //x1,x2存放方程的根 int flag;
8.1 指针的基本知识 void main() { float a,b,c, x1, x2; //x1,x2存放方程的根 int flag; scanf(“%f %f %f”,&a,&b,&c);// 输入 flag=root(a,b,c,&x1,&x2); if ( flag==1) printf(“x1=%.2f x2=%.2f\n”,x1,x2); else printf("方程无实数解\n"); }
16
8.2 指针与数组 指针与一维数组 在C语言中,如果定义了一个数组,则在编译时系统会为数组分配足够大的内存单元,按元素的下标顺序依次存储所有元素。数组名就是内存单元的起始地址即指针值,指向数组的第1个元素(即下标0)。因此数组元素的访问可以用指针访问。
17
8.2 指针与数组 a数组 1 2 3 4 5 a p a[0] 指针与一维数组 1. 用指针引用数组元素 a[1] 假设给出数组如下定义:
8.2 指针与数组 a数组 2000 a p 1 2 3 5 4 a[0] a[1] a[2] a[3] a[4] a[5] 指针与一维数组 1. 用指针引用数组元素 假设给出数组如下定义: int a[6]={1,2,3,4,5,6},*p; p=a; 或 p=&a[0]; // 使指针p指向数组a[0]。 根据指针的间接引用的方法,*p实际就是数组元素a[0]。 数组名或指针访问数组元素的两种形式: 下标法a[i] 指针法*(a+i)。 a[0]=10; a[3]=10; // 下标法引用第1个和第4个元素分别赋值10 *a=10; *(a+3)=10; // 指针法引用第1个和第4个元素分别赋值10 p+2 2008
18
8.2 指针与数组 例 8.5 定义一个有6个元素的整型数组,并输入6整数存储到数组中,利用指针计算各元素的和并输出和。
8.2 指针与数组 例 8.5 定义一个有6个元素的整型数组,并输入6整数存储到数组中,利用指针计算各元素的和并输出和。 #include <stdio.h> void main() { int a[6],i,s,*p; printf("Please input data:\n"); for(i=0; i<6; i++ ) scanf("%d", &a[i] ); s=0; for(p=a; p<a+6; p++) s+=*p ; // 累加各元素值 printf("s=%d\n",s); // 输出和 }
19
8.2 指针与数组 一维数组作函数的参数 一维数组作函数参数通常是将数组名作函数参数,而数组名是第一个元素的地址,所以数组名作函数参数其实质就是指针作函数参数。 例 8.5 定义一个有6个元素的整型数组,并输入6个整数存储到数组中,利用指针计算各元素的和并输出和。 #include <stdio.h> int sum(int *b,int n) { int m=0,*p; for(p=b; p<b+6; p++) m+=*p ; return m; }
20
8.2 指针与数组 void main() { int a[6],s,i; printf("Please input data:\n");
8.2 指针与数组 void main() { int a[6],s,i; printf("Please input data:\n"); for(i=0; i<6; i++ ) scanf("%d", &a[i] ); s=sum(a,6); // 调用sum函数求数组元素的和 printf("s=%d\n",s); }
21
8.2.2数组元素指针作为函数的参数 例 s8-8'.cpp 编写函数,将数组中的n个元素值设置为3
#include<stdio.h> void change( int *b, int n ) { int i; for(i=0;i<n;i++) *(b+i)=3; } b a数组 a a[0] a[1] a[2] a[3] void main() { int i,a[10]={0}; change( a+6, 3); // 6号元素指针作实参 for(i=0;i<10;i++) printf("%d ", a[i]); } a[4] a[5] a+6 a[6] a[7] a[8] a[9] 1. void change(int *b, int n) 等价 void change( int b[ ],int n) 2.两种不同的写法,但两个形参b的性质完全一样,都是指针变量,存放地址。 3.函数调用时实参是某个元素指针或数组名。
22
8.2 指针与数组 b a 例 8.7 定义一个排序函数,完成对n个整数按从小到大排序。 #include <stdio.h>
8.2 指针与数组 b a b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] 9 5 10 6 8 2 1 7 4 3 例 8.7 定义一个排序函数,完成对n个整数按从小到大排序。 #include <stdio.h> void sort(int *a,int n) // 排序函数定义 { int i,j,k,t; for(i=0; i<n-1; i++) for(j=0; j<n-i-1; j++) if(*(a+j)>*(a+j+1)) { t=*(a+j); *(a+j)=*(a+j+1); *(a+j+1)=t; } void main() { int b[10]={5,10,6,9,8,2,7,4,3,1}; int i; sort(b,10); // 调用排序函数 for( i=0; i<10; i++) printf("%4d ",b[i]);
23
8.2 指针与数组 指针运算: 如: float x,y,*pf; char ch,c,*pch; int m,n,*pi; pf=&x;
8.2 指针与数组 指针运算: 1. 指针之间赋值运算。 如: float x,y,*pf; char ch,c,*pch; int m,n,*pi; pf=&x; pch=&ch; pi=&y //编译出错
24
8.2 指针与数组 指针运算: 指针类型的数据,除了间接引运算、赋值运算等操作外,当指针指向数组时,指针可以做加减整数、指针相减及指针比较运算。 1.指针与整数的加、减运算 如果指针p是指向数组中的某个元素,加上整数n后,新指针p+n指向后续的第n个元素。 2.指针相减运算 两个指向同个数组的同类型指针作相减运算,其绝对值表示它们之间相隔的元素数目。 3.指针之间作关系运算 两个相同类型指针可作关系运算比较指针大小。例8.5程序循环控制是通过 p<a+6 判断指针p是否指在a数组元素上。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] p p+3 p+9 a数组 4 1 2 3 5 2000 2012 2036
25
例8-8编函数,完成将若干个数按值从小到大排序。
void sort(float *a, int n) //排序函数 { int i,j,k; float t; for(i=0; i<n-1; i++) { k=i; for(j=i+1; j<n; j++) if( *(a+j)<*(a+k) ) k=j; t=*(a+i); *(a+i)=*(a+k); *(a+k)=t; } void main() { float b[10]={5.3,1.2,2.3,-3,-1.4,1,0.3,8.4,6.2,2.1}; int i; sort(b+2, 5); //函数调用, 实参是2号元素指针(地址) for( i=0; i<10; i++) printf("%.2f ",b[i]); printf("\n"); a b 5.3 b[0] 1.2 b[1] 2.3 b[2] -3 b[3] -1.4 b[4] 1 b[5] 0.3 b[6] 8.4 b[7] 6.2 b[8] 2.1 b[9]
26
8.2 指针与数组 指针与二维数组 1.二维数组的存储方式 假设给出二维数组的定义:int a[3][4];
8.2 指针与数组 指针与二维数组 1.二维数组的存储方式 假设给出二维数组的定义:int a[3][4]; C语言把二维数组a的每一行作为一个一维数组来处理,因此数组a的三行看作三个一维数组,其中a[0]、a[1]和a[2]分别是这三个数组的数组名。 编译时系统为数组分足够大的内存单元,存储数组的所有元素。 内存单元的首地址由数组名表示,各元素在内存单元的排列方式是按行顺序存放。 二维数组名指向数组的第1行而不是第1个元素。
27
8.2 指针与数组 若定义二维数组 int a[3][4]; a a a[0][0] a[0][1] a[0][2] a数组 a[0][3]
8.2 指针与数组 a 2000 a[0][0] 2004 若定义二维数组 int a[3][4]; a a[0][1] 第1行 2008 a[0][2] a数组 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] a[0] a[1] a[2] 2012 a[0][3] a+1 2016 a[1][0] 第2行 2020 a[1][1] 2024 a[1][2] 2028 a[1][3] a+2 2032 a[2][0] 第3行 2036 a[2][1] 2040 a[2][2] 2044 a[2][3]
28
8.2 指针与数组 指针与二维数组 2.二维数组中的两类指针 元素指针:每个元素的地址即为元素指针。
8.2 指针与数组 指针与二维数组 2.二维数组中的两类指针 元素指针:每个元素的地址即为元素指针。 a[i][j]元素指针: 可用&a[i][j]或用a[i]+j表示 行指针:数组中每一行的地址即为行指针。行指针指向的是整个一行。 数组名a是一个行指针指向二维数组的首行,数组名加1即a+1指向数组第2行。 元素指针与行指针的区别 元素指针指向的是一个元素,指针加1后指向下一个元素; 行指针指向的是整个一行(它包含有若干个元素)。
29
8.2 指针与数组 要注意的是p、q虽然都是行指针变量,但类型不同。 行指针作函数参数 1.定义行指针变量
8.2 指针与数组 行指针作函数参数 1.定义行指针变量 类型标识符 (*变量名)[常量表达式]; 例如:int (*p)[4],(*q)[3]; int a[4][3],x[5][4]; p=x; // 使p指向数组x的第1行 q=a+1; // 使q指向数组a的第2行 要注意的是p、q虽然都是行指针变量,但类型不同。 2.用行指针引用数组元素 例如:int a[3][4],(*p)[4]; p=a; 用行指针表示数组元素a[i][j]的三种形式: a[i][j]、*(*(a+i)+j) 和*(a[i]+j)。 p[i][j]、*(*(p+i)+j) 和*(p[i]+j)。 用行指针表示数组元素a[i][j]地址的三种形式: &a[i][j]、*(a+i)+j 和a[i]+j。 &p[i][j]、*(p+i)+j 和p[i]+j。
30
8.2 指针与数组 例8.8 输入一个3×4的矩阵到二维数组中,计算所有元素的和。 #include <stdio.h>
8.2 指针与数组 例8.8 输入一个3×4的矩阵到二维数组中,计算所有元素的和。 #include <stdio.h> void main() { int a[3][4], i,j,s=0; int (*p)[4]; printf("Please input data:\n"); for(i=0; i<3; i++) for(j=0; j<4; j++) scanf("%d",*(p+i)+j); // 给a[i][j]元素输入数据 for(p=a,i=0; i<3; i++) s+=*(*(p+i)+j); // 累加所有元素 printf("s=%d\n",s); }
31
8.2 指针与数组 3.行指针作函数参数 用行指针作为函数参数,在函数中不仅可以访问主函数中的二维数组,更重要的是可以修改这个二维数组中各元素值。 例 8.9 定义一个函数将5×5矩阵中的右上三角元素都设置成0,其余元素值不变。 #include<stdio.h> void change(int (*x)[5],int n , int m) //p是行指针变量 { int i,j; for(i=0; i<n; i++) for(j=0; j<m; j++) if (i<j) *(*(p+i)+j)=0; // 将右上三角元素都设置成0 }
32
8.2 指针与数组 a // 调用 change(a+2,3,3) 7 6 5 4 3 2 1 void main()
8.2 指针与数组 void main() { int a[5][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}, {4,5,6,7,8},{5,6,,7,8,9}}; int i,j; printf("Matrix:\n"); for(i=0;i<5;i++){ //输出原矩阵 for(j=0; j<5; j++) printf("%3d",a[i][j]); printf("\n"); } change(a,5,5); // 调用change函数 printf("\nNew Matrix:\n"); for(i=0; i<5; i++){ //输出新矩阵 第1行 第2行 第3行 第4行 a 7 6 5 4 3 2 1 // 调用 change(a+2,3,3)
33
8.3 指针与字符串 a // 调用 change(a+2,3,3) 7 6 5 4 3 2 1 void main()
8.3 指针与字符串 void main() { int a[5][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}, {4,5,6,7,8},{5,6,,7,8,9}}; int i,j; printf("Matrix:\n"); for(i=0;i<5;i++){ //输出原矩阵 for(j=0; j<5; j++) printf("%3d",a[i][j]); printf("\n"); } change(a,5,5); // 调用change函数 printf("\nNew Matrix:\n"); for(i=0; i<5; i++){ //输出新矩阵 第1行 第2行 第3行 第4行 a 7 6 5 4 3 2 1 // 调用 change(a+2,3,3)
34
8.3 指针与字符串 字符串是由若干个字符组成的字符序列,以‘\0’作为字符串的结束符。 字符串常量的表示
8.3 指针与字符串 字符串是由若干个字符组成的字符序列,以‘\0’作为字符串的结束符。 字符串常量的表示 用双引号括起来的若干字符序列,即字符串常量。 字符串常量通常是被存储在特定的内存单元中。 字符串一般存储在字符数组中,对字符串的访问可以逐个访问数组元素中的字符,或者利用指针访问字符串。 用指针对字符串的处理要比用字符数组对字符串的处理方便得多。
35
8.3 指针与字符串 字符串指针 字符串第一个字符的地址,即为字符串指针
8.3 指针与字符串 字符串指针 字符串第一个字符的地址,即为字符串指针 字符串常量的值是一个字符串指针,是该字符串在特定内存单元中第一个字符的地址。 例 printf("%x\n","Hello"); 若字符串存放在字符数组,数组名即为字符串指针。 字符串指针实际是一个字符指针,指向字符串的第一个字符,而不是整个字符串。 对一个字符串而言,只要知道了字符串指针,就确定了第一个字符的位置及字符串中的各个字符,‘\0’的位置字决定了字符串的结束位置。
36
8.3 指针与字符串 用字符指针指向一个字符串 用字符指针指向一个字符串,就是使字符指针指向字符串的第一个字符。例如:
8.3 指针与字符串 用字符指针指向一个字符串 用字符指针指向一个字符串,就是使字符指针指向字符串的第一个字符。例如: char *s="Hello,Everyone "; // 定义字符指针变量s,并初始化。 char *s; //定义字符指针变量s s="Hello,Everyone"; // "Hello,Everyone"的地址赋值给s 程序段1: char *p,*q; // 定义字符型指针变量 p="Hello,Everyone"; q=p+6; // q指向字符串"Everyone " 程序段2: char a[10]= "Hello,Everyone"; // 数组名a指向字符串 char *q; q=a+12; // q指向字符串"one"
37
8.3 指针与字符串 程序执行: HappyNewYear! NewYear! 字符串的引用
8.3 指针与字符串 字符串的引用 字符串一般放在字符数组中或用指针指向一个字符串,可以用字符数组名或指针引用字符串。 例8.10 用"HappyNewYear!"字符串对字符数组初始化,输出这个字符串及这个字符串的后半部分“NewYear!”。 #include<stdio.h> void main() { char s[]="HappyNewYear!",*p; printf("%s\n",s); //输出s指向的字符串 p=s+5; // 使p指向字符串"Everyone " printf("%s\n",p); // 输出p指向的字符串 } 程序执行: HappyNewYear! NewYear!
38
8.3 指针与字符串 程序执行: Hello,World 123!↙ Lello,Aorld 123!
8.3 指针与字符串 例8.11 输入一个字符串,将该字符串译成密码输出。密码规律:对大写英文字母用原字母后面的第4个字母代替原字母,若遇到大写字母‘W’、‘X’、‘Y’、‘Z’则分别用‘A’、‘B’、‘C’、‘D’代替,其余字符不变。 #include <stdio.h> void main() { char s[80],*p; int i,n; gets(s); // 输入字符串存放在数组s中 for(p=s ; *p!='\0'; p++) { if( *p>='A'&& *p<='Z' ) if( *p>='W'&& *p<='Z' ){ n=*p-'W'; *p='A'+n; } else *p=*p+4; puts(s); 程序执行: Hello,World 123!↙ Lello,Aorld 123!
39
8.3 指针与字符串 字符串指针作函数参数 程序执行: the length1 is :15 the length2 is : 5
8.3 指针与字符串 字符串指针作函数参数 例8.12 定义一个计算字符串长度的函数。字符串长度是字符串中字符个数,不计字符结束符'\0'。 #include<stdio.h> int mystrlen(char *s ) { int k=0; while(*s!='\0'){ k++; s++; } return k ; void main() { char *p; char a[80]={"Windows98\nVista"}; printf("the length1 is :%d\n",mystrlen(a)); p=a+10; //p指向字符串"Vista" printf("the length2 is :%d\n",mystrlen(p)); 程序执行: the length1 is :15 the length2 is : 5
40
8.3 指针与字符串 程序执行: Good,↙ Happy↙ Good,Happy 字符串指针作函数参数
8.3 指针与字符串 字符串指针作函数参数 例8.13 输入两个字符串s1、s2,将字符串s2连接到字符串s1后面,成为一个新字符串,并输出这个新串。要求定义一个函数,功能是把两个字符串连接成一个字符串。 #include<stdio.h> void mystrcat(char *s,char *t) {for( ; *s!='\0'; s++); for( ; *t!='\0' ; s++,t++) *s=*t; *s='\0'; return; } void main() { char a[80],b[40]; printf(“Plese Input strings:”); gets(a); // 输入a字符串 gets(b); // 输入b字符串 mystrcat(a,b); // a、b两字符串连接等 printf("New string: %s\n", a); 程序执行: Good,↙ Happy↙ Good,Happy
41
8.3 指针与字符串 常用字符串函数 程序执行: HangZhou HangChina
8.3 指针与字符串 常用字符串函数 C语言提供了一些字符串处理函数。这些函数用于字符串处理,包括字符串的拷贝、连接和比较等,对应的头文件为string.h。 1.字符串拷贝函数 strcpy char strcpy(char *s1,char *s2) 功能:字符串s2复制到s1中,从s1指针指的位置开始依次存储字符串2,函数返回值为s1指针。 例如:strcpy的用法: char c[11]=" "; strcpy(c,"HangZhou"); puts(c); strcpy(c+4,"China"); 程序执行: HangZhou HangChina
42
8.3 指针与字符串 常用字符串函数 2.字符串连接函数strcat char strcat(char *s1,char *s2);
8.3 指针与字符串 常用字符串函数 2.字符串连接函数strcat char strcat(char *s1,char *s2); 功能:把s2字符串(包括‘\0’),复制到字符串s1串后,函数返回值为s1。 例如:strcat的用法: char c[18]="HangZhou "; char a[]="China"; strcat(c,a); puts(c);
43
8.3 指针与字符串 常用字符串函数 3.字符串比较函数strcmp 字符串大小的定义:
8.3 指针与字符串 常用字符串函数 3.字符串比较函数strcmp 字符串大小的定义: 两个字符串中对应位置上的字符都相等,且串的长度也相等,则两个字符串相等。 两个字符串不等:两个字符串从首字符开始依次比较,第一次出现对应位置上字符不相等,则两个字符串不相等,且由这两个不相等的字符ASCII码值决定字符串大小,ASCII码值大的字符串大。 字符串比较函数: char strcmp(char s1,char s2), 其中s1、s2是字符串。 功能: 比较s1和2两个字符串的大小。函数返回值0则两字符串相等;返回值为1则字符串s1>s2;返回值为-1 则字符串s1<s2。
44
8.3 指针与字符串 常用字符串函数 3.字符串比较函数strcmp 例如: strcmp("abc","abc")的返回值为0;
8.3 指针与字符串 常用字符串函数 3.字符串比较函数strcmp 例如: strcmp("abc","abc")的返回值为0; strcmp("abc","abcd")的返回值为–1; strcmp("abc","aBc") 的返回值为1; strcmp("ABC","BBC")的返回值为-1。
45
8.3 指针与字符串 常用字符串函数 4.求字符串长度函数strlen char strlen(char *s) , 其中s是字符串。
8.3 指针与字符串 常用字符串函数 4.求字符串长度函数strlen char strlen(char *s) , 其中s是字符串。 功能:计算字符串中字符的个数(不计‘\0’)。 例如:strlen("China")的返回值为5。 例如:定义语句char a[15]="ab\110\\cd\'\\ne";则strlen(a)的返回值为10(注意转义字符);strlen(a+2)的返回值为8。
46
8.3 指针与字符串 程序执行: Input strings:
8.3 指针与字符串 例8.14 输入6个字符串,输出最大字符串。 #include <stdio.h> #include <string.h> void main() { char s[80],max[80]; int i; printf("Input strings:\n"); scanf("%s",s); strcpy(max,s); for(i=1;i<=5;i++){ if(strcmp(s,max)>0) } printf("Max-string: %s\n",max); 程序执行: Input strings: elephant finsh tigre apple pear banana↙ Max-string: tigre
47
8.4 指针数组与多级指针 指针数组与多字符串 C语言允许任何类型的数组,也允许数组元素是指针类型。
8.4 指针数组与多级指针 指针数组与多字符串 C语言允许任何类型的数组,也允许数组元素是指针类型。 如果数组的所有元素都是指针类型,那么这个数组就是指针数组。 指针数组较多的应用于多字符串处理。 1.指针数组定义 类型标识符 *数组名[数组长度]; 例如,int *p[10]; 即定义了数组p是指针数组。 数组p的每个元素是指针类型,存储int型变量的地址。
48
8.4 指针数组与多级指针 例8.15 读程序,区别指针数组与普通数组。 #include<stdio.h>
8.4 指针数组与多级指针 程序执行: Output x-arry: Output object of px-arry: Output px-arry: 13ff6c 13ff70 13ff74 13ff78 例8.15 读程序,区别指针数组与普通数组。 #include<stdio.h> void main() { int i; int x[4]={1,2,3,4}, *px[4]; // 定义数组x和指针数组px for(i=0;i<4;i++) px[i]=x+i; // 使px[i]指向x[i] printf("Output x-arry:\n"); for(i=0;i<4;i++) // 输出x数组各元素值 printf("%3d",x[i]); printf("\nOutput object of px-arry:\n"); for(i=0;i<4;i++) // 输出px数组各元素对象值 printf("%3d ",*px[i]); printf("\nOutput px-arry:\n "); for(i=0;i<4;i++) // 输出px数组各元素值(数组x各元素的地址) printf("%x ",px[i]); }
49
8.4 指针数组与多级指针 程序执行1: Input name: Fox↙ Fox is here 2.多字符串
8.4 指针数组与多级指针 2.多字符串 通常可以用字符指针数组来表示多个字符串,即将指针数组中每个元素指向一个字符串。 例8.16 输入一个学生姓名,在含有10个学生名单中查找该学生是否存在,并输出查找结论。 #include<stdio.h> void main() { static char *name[10]= {"Betty","Tom","Smith","Ellen","Fox", "Shakespeare","Steven,Owen,Marie,Arids"}; char sn[20]; int i; printf("Input name:\n"); scanf("%s",sn); // 输入查找人姓名 for(i=0;i<10;i++) if (strcmp(sn,name[i])==0) break; if (i<10) printf("%s is here\n",sn); else ("Sorry,Not found"); } 程序执行1: Input name: Fox↙ Fox is here
50
8.4 指针数组与多级指针 Tailand\0 Zambia\0 Italy\0 Mauritiania\0 France\0
8.4 指针数组与多级指针 *例8.17 将Tailand, Zambia, Itlay, Mauritania, France,Romania 这6个国家的英文名称按字符串大小排序输出。 char *p[6]={"Tailand", "Zambia", "Itlay", "Mauritania", "France","Romania"}; Tailand\0 Zambia\0 Italy\0 Mauritiania\0 France\0 Romania\0 p[0] p[1] p[2] p[3] p[4] p[5] p[0] p[1] p[2] p[3] p[4] p[5] Tailand \0 Zambia\0 Italy\0 Mauritiania\0 France\0 Romania\0
51
8.4 指针数组与多级指针 #include <stdio.h> #include <string.h>
8.4 指针数组与多级指针 #include <stdio.h> #include <string.h> void main() { char *p[6]={ "Singapore","Zambia","China","Mexico", "Canada","Romania" }; char *t; int i,j,k; for(i=0; i<5; i++){ k=i; for(j=i+1; j<6; j++) if(strcmp(p[j],p[k])<0) //比较p[j]与p[k]指针指向的字符串大小 k=j; t=p[k]; // 三条语句交换指向 p[k]=p[i]; p[i]=t; } for(i=0; i<6; i++) puts(p[i]);
52
8.4 指针数组与多级指针 指向指针的指针 pp &p &x p 56 x 二级指针变量定义的一般形式: 类型标识符 **变量名; 例如:
8.4 指针数组与多级指针 指向指针的指针 二级指针变量定义的一般形式: 类型标识符 **变量名; 例如: int x=56; // 定义整型变量x,放整数,初始化56 int *p=&x; // 定义一级指针变量p,放普通变量地址,初始化&x int **pp=&p; // 定义二级指针变量pp,放指针变量p的地址,初始化&p pp、p、x之间的关系是pp指向p,p指向x,x值56 pp &p &x p 56 x
53
8.4 指针数组与多级指针 ppi &pi &x pi 3 a 例8.18 二级指针变量的定义与引用。
8.4 指针数组与多级指针 例8.18 二级指针变量的定义与引用。 #include <stdio.h> void main() { int a=3,*pi,**ppi; // pi为一级指针变量、ppi为二级指针变量 pi=&a; // 使pi指向a ppi=π // 使ppi指向指针变量pi printf("a=%d\n",a); printf("a-address: %x\n",pi); printf("pi-address: %x\n",ppi); printf("ppi-address: %x\n",&ppi); printf("a=%d,*pi=%d,**ppi=%d\n",a,*pi,**ppi); } 程序执行: a=3 a-address: 12ff7c pi-address: 12ff78 ppi-address: 12ff74 a=3, *pi=3, **ppi=3 ppi &pi &x pi 3 a
54
8.4 指针数组与多级指针 *例8.19 用指针数组指向6个国家的英文名字,分别用指针数组,指针的指针输出这6个国家名及每个国家名的首字符。
8.4 指针数组与多级指针 *例8.19 用指针数组指向6个国家的英文名字,分别用指针数组,指针的指针输出这6个国家名及每个国家名的首字符。 #include <stdio.h> void main() { char *p[6]={ "Singapore","Zambia","Itlay" ,"China", "America","Romania" }; char **q; // q指针的指针 (二级指针) int i; for(i=0; i<6; i++){ printf("%10s, %c ",p[i],*p[i]); // 用指针数组输出国家名及首字母 q=p+i; printf("%10s, %c\n",*q,**q); // 用指针的指针输出国家名及首字母 } 程序执行: Singapore,S Singapore,S Zambia,Z Zambia,Z Itlay,I Itlay,I China,C China,C America,A America,A Romania,R Romania,R
55
8.4 指针数组与多级指针 * main函数的参数 main函数可以带参数的。 当C程序运行时,通过命令行输入参数给main函数。
8.4 指针数组与多级指针 * main函数的参数 main函数可以带参数的。 当C程序运行时,通过命令行输入参数给main函数。 C语言规定main函数的参数只能有两个,习惯上将这两个参数名写为argc和argv。 带参数的main函数首行的一般形式为: void main(int argc,char *argv[ ]) 第一个形参argc存放程序执行时的参数个数,至少是一个(这个参数就是该程序的可执行文件名); 第二个形参argv为指针数组,存放指向实参的指针。其中,argv[0]指向第一个实参,即该程序的可执行文件名,argv[1]指向第二个实参,argv[2]指向第三个实参……
56
8.4 指针数组与多级指针 * main函数的参数 用简单的程序说明如何给main函数传递实参的方法。
8.4 指针数组与多级指针 * main函数的参数 用简单的程序说明如何给main函数传递实参的方法。 例8.20 输出main函数执行时的各参数。 程序的文件名为prg.c。 #include<stdio.h> void main(int argc,char *argv[]) { int i; printf("参数个数为:%d\n",argc); // 输出argc值 i=0; while (i<argc){ printf("第%d个参数:%s\n", i+1,argv[i]); // 输出各参数值 i++; } 程序执行1:将上面的程序经编译、连接后得到可执行文件prg.exe,在Windows的命令提示符环境下,输入命令行: prg.exe Hello, Everyone!↙ 参数个数为:3 第1个参数:prg.exe 第2个参数:Hello, 第3个参数:Everyone!
57
8.5 指针与函数 指针作为函数的返回值 类型标识符* 函数名(类型标识符 形参, 类型标识符 形参,…) { 函数体 }
8.5 指针与函数 指针作为函数的返回值 类型标识符* 函数名(类型标识符 形参, 类型标识符 形参,…) { 函数体 } 例8.21 输入两个字符串s1、s2,将字符串s2连接到字符串s1后面,成为一个新字符串,并输出这个新串。要求定义一个连接两个字符串的函数,并且函数返回指向连接后新字符串的指针。
58
8.5 指针与函数 #include<stdio.h> char *mystrcat(char *s,char *t)
8.5 指针与函数 #include<stdio.h> char *mystrcat(char *s,char *t) { char *p; for(p=s ; *s!='\0'; s++) ; for( ; *t!='\0' ; s++,t++) *s=*t; *s='\0'; return p; // 返回连接后的新字符串的指针。 } void main() { char s1[80],s2[80]; printf("Please input two strings:\n"); gets(s1); // 输入s1字符串 gets(s2); // 输入s2字符串 printf("New string is:”); printf("%s\n", mystrcat(s1,s2)); // 输出连接后的新字符串 程序执行: Please input two strings: Windows↙ XP↙ The new string: WindowsXP
59
8.5 指针与函数 例8.22 输入一个学生姓名,在10个学生名单中查找该学生是否存在,并输出查找结论是或否。
8.5 指针与函数 例8.22 输入一个学生姓名,在10个学生名单中查找该学生是否存在,并输出查找结论是或否。 #include<stdio.h> #include<string.h> char *search(char *s, char *sname[],int n) { int i; for(i=0;i<n;i++) if (strcmp(s,sname[i])==0) return sname[i]; //返回找已到的字符串指针 return NULL; // 没有找,返回空指针 }
60
8.5 指针与函数 例8.22 输入一个学生姓名,在10个学生名单中查找该学生是否存在,并输出查找结论是或否。 void main()
8.5 指针与函数 例8.22 输入一个学生姓名,在10个学生名单中查找该学生是否存在,并输出查找结论是或否。 void main() { static char *name[10]= {"Betty", "Tom","Smith","Ellen", "Shakespeare","Fox","Steven,Owen,Marie,Arids"}; char sn[20],*p; int i; printf("Please input name:\n"); scanf("%s",sn); // 输入一个欲查找的姓名 p = search(sn, name,10); if(p==NULL) printf("Not Found\n"); else printf("%s\n",p); // 输出找到的人名 } 程序执行1: Please input name: Fox↙ Fox
61
8.5 指针与函数 指向函数的指针 C语言是由函数组成,每个函数是一段程序。
8.5 指针与函数 指向函数的指针 C语言是由函数组成,每个函数是一段程序。 编译后函数被翻译成一组机器指令。系统为函数分配确定的基地址和足够大的内存空间存储这组指令。 基地址就是函数的指针,指向函数的第一条指令,由函数名表示。 函数被执行时,就从这基地址开始,逐条执行指令,直到区域中的指令执行完。
62
8.5 指针与函数 指向函数的指针 1.函数指针变量的定义与赋值 类型标识符 (*变量名)(形参类型列表); 例如:
8.5 指针与函数 指向函数的指针 1.函数指针变量的定义与赋值 类型标识符 (*变量名)(形参类型列表); 例如: char (*f1)(float); int (*f2)(int,float); 为函数指针变量赋值 double (*f)(double); double (*q)(double,double); f=sqrt; // 使f指向sqrt函数 q=pow; // 使q指向sqrt函数 可以用指针变量f、q分别调用sqrt、pow函数。 f(5)、q(5,3),即分别调用了sqrt和pow函数。
63
8.5 指针与函数 指向函数的指针应用 例8.23 用指向函数的指针调用函数的应用举例。 #include <stdio.h>
8.5 指针与函数 指向函数的指针应用 例8.23 用指向函数的指针调用函数的应用举例。 #include <stdio.h> #include <math.h> double max(double x,double y) { return x>y? x:y; } void main() { double (*p)(double,double); // 定义p为函数指针变量 double y1,y2; p=pow; y1=p(5,3); // 调用函数pow(5,3) printf("y1=%.2f\n",y1); p=max; y2=p(5,3); // 调用函数max(5,3) printf("y2=%.2f\n",y2); 程序执行: y1=125.00 y2=5.00
64
8.5 指针与函数 f(x) f(b) f(c) c a b f(a)
8.5 指针与函数 *例8.24 用二分法编写求f(x)=0在[a,b]区间内一个根的通用函数。 程序设计分析 若函数f(x)在[a,b]区间连续,且满足条件f(a)*f(b)<0,则在区间[a,b]中必有根ξ,使f(ξ)=0。求f(x)=0在[a,b]区间内的一个实根的二分法。基本步骤如下: 1)c=(a+b)/2。 2)|f(c)|<ε,则输出c作为近似解,并终止程序。 3)缩小求根区间, [a,c]或[c,b]作为新的求根区间[a,b],使新[a,b]仍然满足f(a)*f(b)<0,再继续执行第1步。 f(x) f(b) c f(c) a b f(a)
65
8.5 指针与函数 */* 例8.24源程序,用函数指针作为函数的参数 */ #include <stdio.h>
8.5 指针与函数 */* 例8.24源程序,用函数指针作为函数的参数 */ #include <stdio.h> #include <math.h> double root(double a,double b,double eps,double(*f)(double)) { double c; do{ c=(a+b)/2; if(f(a)*f(c)<0) b=c; else a=c; }while(fabs(b-a)>eps&&fabs(f(c))>eps); return c; }
66
8.5 指针与函数 double f(double x) // 定义f(x)方程 { return x*x-2*x+1; }
8.5 指针与函数 double f(double x) // 定义f(x)方程 { return x*x-2*x+1; } void main() double x1,x2; x1=root(0,5,1e-4,sin); // 求函数sin(x)=0在[0,5]的一个实根 printf("x1=%.2f\n",x1); x2=root(0,2,1e-5,f); // 求函数f(x)=0在[0,2]的一个实根 printf("x2=%.2f \n",x2);
Similar presentations