数学指针进阶PPT课件_第1页
数学指针进阶PPT课件_第2页
数学指针进阶PPT课件_第3页
数学指针进阶PPT课件_第4页
数学指针进阶PPT课件_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、qsort()函数 排序是最常用的预处理技术 qsort包含在头文件中 函数根据你给的比较条件进行快速排序 排序之后的结果仍然放在原数组中 使用qsort函数必须自己写一个比较函数。第1页/共59页qsort()函数使用 函数原型 void qsort ( void *base, int n, int size, int *cmp ); 数组名base,数组元素个数n,每个元素的字节数size,比较函数指针cmp cmp的函数原型 int cmp( const void *, const void * ) cmp函数指针功能是返回相邻两个元素的序关系,若符合正序关系,则返回一个负数;若二者逆序

2、,返回一个正数。例如要元素进行升序排列,则定义cmp所指向的函数为:如果其第一个参数比第二个参数小,则返回一个小于0的值,反之则返回一个大于0的值,如果相等,则返 回0。第2页/共59页一、对整型数组排序Int main() int a10=4,2,7,3,6,1,5; int i,n=7; qsort(a, n,sizeof(a0),cmp); for(i=0;in;i+) printf(“%d “,ai);int cmp ( const void *a , const void *b )int *c=(int *)a; /(int*)是强制类型转换Int *d=(int *)b;retur

3、n *c-*d;return *(int *)a - *(int *)b;如果要降序排序,只需要改变cmp函数:return *(int *)b - *(int *)a;第3页/共59页整型数组排序练习输入n和n个整数,先升序输出,再降序输出,最后按绝对值升序输出。第4页/共59页二、对char类型数组排序(同int类型) Int main() char str10=“gjlfjsder”; int i,n; n=strlen(str); qsort(a, n,sizeof(a0),cmp); puts(str); int cmp ( const void *a , const void *b

4、 )char *c=(char *)a; /(char*)是强制类型转换char *d=(char *)b;return *c-*d;return *(char *)a - *(char *)b;第5页/共59页三、对double类型数组排序 Int main() double a10=5, 2.5, 1.3, 3.2; int i,n=4; qsort(a, n,sizeof(a0),cmp); for(i=0;i*d ? 1 : -1; /不是return *c-*breturn *(double*)a *(double *)b ? 1:-1;不能写成 return *(double*)a

5、 - *(double *)b ;为什么?第6页/共59页关于数组的两个事实:(1)c语言只有一维数组,而数组的元素可以是任何类型的对象,比如是一个数组。(2)对于数组,我们只能做两件事:获取数组的大小、获取下标为0的元素的地址。 有关数组的所有操作,都是通过指针进行的,虽然看似是通过下标进行的。7.4 指针与二维数组第7页/共59页数组名a代表下标为0的元素的地址,但不仅仅如此#includeint main()double a4=1,2,3,4;double* p;p= a; /或p=&a0;printf(数组a的所占字节数sizeof(a):%dn,sizeof(a);print

6、f(指针变量p的所占字节数sizeof(p):%dn,sizeof(p);printf(指针p所指变量的字节数sizeof(*p):%dn, sizeof(*p);return 0;数组名a代表着指向下标为0的元素的指针, 但只有一种情况例外,sizeof(a)的结果是数组 整个数组a的大小,而不是一个整型指针变量的大小第8页/共59页下标运算的本质#include#includeint main()int a2=1,2,i;i=0; printf(“%dn”,*(a+i);printf(%dn,ai); printf(“%dn”,*(i+a);printf(%dn, ia );return

7、0;下标运算在本质上是指针运算:ai在本质上是*(a+i)ia之所以能通过编译,是因为编译器将ia当做*(i+a)来理解了第9页/共59页二维数组的本质0 0101020201 1111121212 2121222223 313132323aa a00a a11a a22aa+1a+2int a34;声明一个二维数组时,编译器就会创建一个大小为3的数组,每个元素a0,a1,a2都是一个大小为4的数组a0,a1,a2是一个一维数组名,也代表着一个一维数组的起始地址,a0代表着指向a00的指针,a1代表着指向a10的指针。a代表着指向a0的指针。第10页/共59页int a33;一个int型数据占

8、4个字节,若a00的地址是2010,问a12的地址是多少? aij的地址是多少?2010+i*3+j2010+1*3+27.4.1用一级指针访问多维数组a00a00a22a22a01a01 . . . . . . . . . . . .1 12 23 34 45 56 67 78 89 9二维数组是按行顺序存储int a33=1,2,3;求数组a中所有元素的累加和int *p,i,sum=0;p=&a00;for(i=0;in*n; i+,p+) sum=sum + *p;求数组a中所有元素的累加和int i,sum=0;int* p;p=&a00;for(i=0;in;i+)

9、 for(j=0;jn;j+) sum=sum + *(p+i*n+j);本质上都是利用二维数组顺序存储的特点,顺序访问二维数组第11页/共59页上例中能否把二维数组名a赋给p? 求数组a中所有元素的累加和 int a33=1,2,3,4,5,6,7,8,9, int i, sum=0; int* p; p=&a00; /能否写成p=a? for(i=0;in;i+) for( j=0;in;j+) sum=sum+*(p+i*n+j); 不可以,p是整型指针,指向整型变量a指向a0, a0是一维数组n/能否写成*(a+i*n+j)不可以,a指向一维数组,每增加1,移动一行数据第12页

10、/共59页7.4.2 1. 指向指针的指针(二级指针) 类型名* 变量名int a = 10;int* p = &a;int* dp = &p; &apa10*p&pdp*dp*dpdp中存储的是指针变量p的地址,我们说,dp指向指针变量p, dp是指向指针(p)的指针(变量)第13页/共59页0 0101020201 1111121212 2121222223 313132323a 二维数组的地址 例如:int a34; 二维数组名a是数组的首地址。 二维数组a包含三个行元素:a0、a1、a2 。 a a00a a11a a22a三个行元素的地址分别是:a a

11、、a+1a+1、a+2a+2。而行元素a a00、a a11、a a22也是地址量,是一维数组名即* *( (a+0)a+0)、* *(a+1)(a+1)、* *(a+2)(a+2)是一维数组首个元素地址。a+1a+2第14页/共59页a0、a1、a2是一维数组名所以ai+j是数组元素aij的地址。 数组元素a aiijj的地址可以表示为下列形式: & &a aiijj、a aii+j+j 、* *( (a a+ +i i) )+ +j j0 0101020201 1111121212 2121222223 313132323a0数组a1数组a2数组 二维数组元素的地址第15页

12、/共59页数组元素可用下列形式表示: aij、*(ai+j)、*(*(a+i)+j) a a 是二维数组,根据C C的地址计算方法,a a经过两次 * * 操作才能访问到数组元素。所以 * * a a 是 a a00,* * * * a a 才是 a a0000。 a a00是a a0000的地址, ,* *a a00是a a0000。0 0101020201 1111121212 2121222223 313132323a a00a a11a a22a 二维数组元素的表示法第16页/共59页(4)指向一维数组的指针变量(注意:是指向数组,不是指向数组元素 “*”表示其后的变量名为指针类型,元

13、素个数表示目标变量是一维数组,并说明一维数组元素的个数。由于“*”比“ ”的运算级别低,“*变量名”作为一个说明部分,两边必须加括号。 “数据类型标识符”是定义一维数组元素的类型。指向一维数组指针变量的定义形式: 数据类型标识符 (*变量名)元素个数int a44;int (*lp)4;lp=&a0;定义lp是一个指向一维数组(长度为4)的指针a0是一个一维数组(长度为4)的数组,故lp可以指向a0,即把a0的地址赋给lp第17页/共59页【例7.14】用指向一维数组的指针变量输出数组元素。 main( ) int a34=0,1,2,3,10,11,12,13,20,21,22,23

14、; int (*lp)4, i, j; for (lp=a, i=0; i3; i+) for (j=0; j4; j+) printf(“%4d”,*(*(lp+i)+j); /也可以写成pij; printf(n); 0 0101020201 1111121212 2121222223 313132323alplp+1lp+2第18页/共59页7.4.3 指针数组的概念类型名* 数组名数组长度数组元素是指针类型,用于存放内存地址int a10; a是一个数组,它有10个元素 每个元素的类型都是整型char* color5; color是一个数组,它有5个元素 每个元素的类型都是字符指针指针

15、数组就是数组中的每个元素均为指针类型 第19页/共59页例7.15 动态申请和释放二维数组 输入整数m m和n n,然后输入m m行n n列的矩阵。然后输出矩阵。 要求动态申请和释放二维数组第20页/共59页方法1:用动态一维数组的方法存储二维数组 int* p; p=(int*)malloc(m*n*sizeof(int); 矩阵中第i行第j列元素,映射到一维数组,是第i*n+j个元素(下标都从0开始)第21页/共59页#include#includeint main() int i, j,m,n; int* p; scanf(%d%d,&m,&n); p=(int *)ma

16、lloc(m*n*sizeof(int); for(i=0;im;i+) for(j=0;jn;j+) scanf(%d,p+i*n+j); /scanf(%d,&pi*n+j); for(i=0;im;i+) for(j=0;jn;j+) printf(%d ,pi*n+j); printf(n); 第22页/共59页方法2:用指针数组实现 (1)声明一个一维指针数组,存放每一行的首地址 (2)用malloc为每一行元素申请空间 (3)读入m*n个元素 (4)输出矩阵 (5)释放每一个行指针所指空间。第23页/共59页详细实现 (1)申请一个一维指针数组,存放每一行的首地址 int*

17、 aN; (2)用malloc为每一行元素申请空间 for(i=0;im;i+) ai=(int *)malloc(n*sizeof(int); (3)为m*n个元素赋值 (4)输出矩阵 (5)释放每一个行指针所指空间。 for(i=0;im;i+) free(ai);请完善本程序请完善本程序int *a;a=(int *)malloc(m*sizeof(int *);第24页/共59页a101010502030105010102030for(i=0;im;i+) ai=(int *)malloc(n*sizeof(int);int* aN;a0a1a2第25页/共59页a1010105020

18、30105010102030for(i=0;im;i+) ai=(int *)malloc(n*sizeof(int);int* a;a=(int *)malloc(m*sizeof(int *);24802480第26页/共59页程序运行输出结果如下:1 2 3 41 2 3 45 6 7 85 6 7 89 10 11 129 10 11 12123456789101112a00a03a20a23a1a1a3a注意,二维动态数组的全部存储空间不是一次申请的,所以二维动态数组的每一维数组在物理上是连续的,而全部二维动态数组在物理上不一定是连续的。第27页/共59页课堂练习1 int main

19、() char str 8=“Hello”,“Beijing”,*p=str; printf(“%sn”,p+8);该程序运行后的输出结果是( )。A)Hello B)Beijing C)jing D)ijing题目有问题吗?会有语法错误吗?str是二级指针,p是一级指针,不能赋值的*p=&str00;或*p=*str;或*p=str0;答案:B第28页/共59页 2.以下程序的输出结果是( )。int main( ) char ch25= “6937”,“8254”,*p2; int i, j, s=0; for(i=0;i2;i+)pi=chi; for(i=0;i 0;j+=2)

20、 s=10*s+pij- 0; printf(%dn,s); A)69825 B)63825 C)6385 D)693825答案:C528396p0p147第29页/共59页 3 若有以下定义和语句: int s45,(*ps)5; ps=s; 则对s数组元素的正确引用形式是 A) ps+1 B) *(ps+3) C) ps02 D) *(ps+1)+3答案:C第30页/共59页 4 以下程序将输出的字符是( )。 #include stdio.h int main() char c; char (*p)3; char s23 =a,b,c,d,e,f; p=&s0; c=*(p1+1

21、); printf(%c,c); A)b B)d C)e D)f答案:Cabcdefs0s1pp1即s1*(p1+1)即s11第31页/共59页7.4.4. 用指针数组处理多个字符串指针数组的主要应用是字符串处理,前面只是为了讲明白概念(1) 二维字符数组存储多个字符串char ccolor 7 = red, blue, yellow, green, purple;第32页/共59页指针数组char* pcolor = red, blue, yellow, green, purple;(2)使用指针数组存储多个字符串42006442005c42005442004c420044pcolor0pc

22、olor1pcolor2pcolor3pcolorred0blue0yellow0green0purple0pcolor4为每个字符串分配空间,然后将字串首地址存入colori这些字符串的存储位置不一定相邻更节省内存空间第33页/共59页例7.16 字符串排序(1)已知5个字符串:“red”, “blue”, “yellow”, “green”, “purple”,请排序后输出第34页/共59页多个字符串排序red0blue0yellow 0green0purple0blue0green0purple0red0yellow0(1)用二维字符数组处理排序前:排序后:如何实现两个字符串的交换?te

23、mp r e d 0 b l u e 0 r e d 0 涉及到字符的大量移动!第35页/共59页pcolor0pcolor1pcolor2pcolor3pcolorred0blue0yellow0green0purple0pcolor4排序前0064005c0054004c0044pcolor0pcolor1pcolor2pcolor3pcolorpcolor4排序后red0blue0yellow0green0purple0005c004c0044 00640054(2)使用指针数组处理字符串的存储位置不变排序的本质是改变pcolor中存储的地址比如,因”red”大于”blue”, pcol

24、or0与pcolor1互换005c0064第36页/共59页int main(void) int i,k; char temp7; char color57= red, blue, yellow,green, purple ; for(i = 1; i n; i+) for(j = 0; j 0) strcpy(temp, colorj); strcpy(colorj, colorj+1); strcpy(colorj+1,temp); for(i = 0; i 5; i+) printf(%s , colori); 例7.16(1)二维字符数组实现字符串排序字符串整体复制、交换不能写成 te

25、mp = colorj;因为temp和colorj都是地址常量第37页/共59页int main(void) int i,k; char *temp; char* pcolor5= red, blue, yellow,green, purple ; for(i = 1; i n; i+) for(j = 0; j 0) temp = pcolorj; pcolorj = pcolorj+1; pcolorj+1 = temp; for(i = 0; i 5; i+) printf(%s , pcolori); 例7.16(2)指针数组实现字符串排序只交换字符串的地址pcolor是指针数组, p

26、colori是数组元素,其值可以改变第38页/共59页例7.17 字符串排序(2)输入n和n个字符串(每个字符串不超过80个字符),请排序后输出,要求使用指针数组(而不是二维字符数组)处理第39页/共59页int main(void) int i, k, n; char *pcolor100,str81; scanf(%d,&n); for(i=0;in;i+) scanf(%s,str); strcpy(pcolori, str); /排序过程略 for(i = 0; i 5; i+) printf(%s , pcolori); 本程序有什么问题?将str的内容,存入pcolori所

27、指向的内存空间?pcolori中有值吗?它指向什么地址?第40页/共59页int main(void) int i, k, n; char* pcolor100; char str81; scanf(%d,&n); for(i=0;in;i+) scanf(%s,str); pcolori=str; /排序过程略 for(i = 0; i 5; i+) printf(%s , pcolori); 本程序有什么问题?str是数组名,是一个常量,循环进行n次,str始终是一个常量,每个pcolori中存的地址相同,指向同一个字符串,就是第n次输入的那个字符串第41页/共59页int mai

28、n(void) int i, k, n; char *pcolor100; char str81; scanf(%d,&n); for(i=0;in;i+) pcolori=(char *) malloc ( 81*sizeof (char) ); scanf(%s , pcolori); /排序过程略 for(i = 0; i 5; i+) printf(%s , pcolori); 正确实现方法先申请内存空间,再读入字符串更节省空间的写法是:先读入字符串,按每一个字符串的实际长度申请空间,再将字串拷入scanf(%s,str);pcolori = (char *) malloc (

29、 sizeof (char) * ( strlen(str) + 1 ) );strcpy(colori, str);第42页/共59页pcolor101010502030105010102030char* pcolor100;for(i=0;in;i+) scanf(%s,str); pcolori = (char *) malloc ( sizeof (char) * ( strlen(str) + 1 ) ); strcpy(pcolori, str); str:yellow y e l l o w 0red r e d 0white w h i t e 0第43页/共59页用qsort

30、对字符串数组排序 qsort(a, n,sizeof(a0),cmp); int cmp ( const void *a , const void *b )char *c,*d;c=(char *)a; d=(char *)b;return strcmp(c, d);return strcmp(char*)a , (char*)b);第44页/共59页字符串排序练习 1、输入n个字符串,按字典序升序排序 2、输入n个字符串,按字典序升序排序 3、输入n个字符串,升序排序,大小规则如下:先以长度论大小,长度相同,以字典序论大小。第45页/共59页7.5带参main()函数 C语言源程序经编译和连

31、接处理,生成可执行程序后,才能运行。 在DOS环境的命令窗口中,输入可执行文件名,就以命令方式运行该程序。 test命令名命令名无命令行参数无命令行参数#include /* test.c */int main( ) /无参的main()函数 printf(Hello World!); return 0;第46页/共59页带参数的main()函数#include /* test.c */int main(int argc, char *argv ) printf(Hello ); printf(%s, argv1); return 0;test Liling运行结果: Hello Linlin

32、g命令名命令名命令行参数命令行参数第47页/共59页命令行参数命令名 参数1 参数2参数n 命令名和各个参数之间用空格分隔,也可以没有参数 使用命令行的程序不能在编译器中执行,需要将源程序经编译、链接为相应的命令文件(一般以.exe为后缀),然后回到命令行状态,再在该状态下直接输入命令文件名。 第48页/共59页带参数的main()函数int main( int argc, char *argv ) .#include /* test.c */int main(int argc, char *argv ) printf(Hello ); printf(%s, argv1); return 0;

33、在命令行输入:test Lilingargc: 2*argv : test, “Liling第1个参数 argc 接收命令行参数(包括命令名)的个数第2个参数 argv 接收以字符串常量形式存放的命令行参数(命令名本身也作为一个参数) 运行结果Hello Liling第49页/共59页例10-7 输出命令行参数例7.18 编写C程序echo,它的功能是将所有命令行参数在同一行上输出。 #include int main(int argc, char *argv ) int k; for(k = 1; k argc; k+) /* 从第1个命令行参数开始 */ printf(%s , argvk

34、); /* 打印命令行参数 */ printf(n); return 0;在命令行状态下输入:echo How are you?How are you?argc的值为4第50页/共59页在其它程序中调用应用程序 #include int main() system(d:/aa.exe liye); return 0; #include /aa.cppint main(int argc, char *argv ) printf(“Hello); puts(*(argv+1); return 0;第51页/共59页7.6 指向函数的指针 每个函数都占用一段内存单元,有一个入口地址(起始地址) 函数名:函数的入口地址 函数指针:一个指针变量,接收函数的入口地址,让它指向函数 通过函数指针调用函数 做为函数的参数 指令1指令2指令3指令n入口地址入口地址第52页/共59页函数指针的定义和赋值 定义类型名 (*变量名)(形参表);所指向函数的返回值的类型 int (*funptr)(形参表 ); 定义一个函数指针funptr funptr指向一个返回值类型为int的函数 赋值funptr = fun

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论