C语言程序设计课件10 指针_第1页
C语言程序设计课件10 指针_第2页
C语言程序设计课件10 指针_第3页
C语言程序设计课件10 指针_第4页
C语言程序设计课件10 指针_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

第十章

指针

1本章知识点:本章知识点:一维数组的指针二维数组的指针指针数组指向指针的指针函数指针指针函数单链表的使用210.1数组、地址与指针

10.1.1数组、地址与指针的关系在前面我们曾提到过,数组名可以代表数组的首地址。因此,下面的两种表示是等价的:

a,&a[0]即数组的首地址也就是数组中第1个元素的地址。由于在内存中数组中的所有元素都是连续排列的,即数组元素的地址是连续递增的,所以通过数组的首地址加上偏移量就可得到其它元素的地址。【例10.1】输出数组中的元素。10.1.2一维数组中的地址与指针数组元素的访问主要有三种形式下标法、地址法和指针法。

下标法:即以a[i]的形式存取数组元素。

地址法:用*(a+i)的形式存取数组元素,这种方法和下标法实质上是一样的。

指针法:用一个指针指向数组的首地址,然后通过移动指针访问数组元素。4【例10.2】设一数组有10个元素,要求输出所有数组元素的值。5方法一:通过下标法存取数组元素,程序如下:#include<stdio.h>intmain(){inta[10]={1,2,3,4,5,6,7,8,9,10};inti;for(i=0;i<10;i++) printf("%d",a[i]);/*通过数组下标访问数组元素*/printf("\n");return0;}

6方法2:通过数组名计算数组元素的地址存取数组元素#include<stdio.h>intmain(){inta[10]={1,2,3,4,5,6,7,8,9,10};inti;for(i=0;i<10;i++) printf("%d",*(a+i));/*数组名a表示数组的首地址*/printf("\n");return0;}

7方法3:通过指针变量存取数组元素#include<stdio.h>intmain(){inta[10]={1,2,3,4,5,6,7,8,9,10};inti,*p;for(p=a;p<(a+10);p++) printf("%d",*p);/*通过指向数组元素的指针访问数组元素*/printf("\n");return0;}

10.1.3二维数组中的地址与指针在C语言中,二维数组是按行优先的规律转换为一维线性存放在内存中的,因此,可以通过指针访问二维数组中的元素。

例如:inta[M][N];

则将二维数组中的元素a[i][j]转换为一维线性地址的一般公式是:

线性地址=a+i×M+j其中:a为数组的首地址,

M和N分别为二维数组行和列的元素个数。8【例10.3】给定某年某月某日,将其转换成这一年的第几天并输出。问题分析:此题的算法很简单,若给定的月是i,则将1、2、3、……、i-1月的各月天数累加,再加上指定的日。但对于闰年,二月的天数29天,因此还要判定给定的年是否为闰年。为实现这一算法,需设置一张每月天数列表,给出每个月的天数,考虑闰年非闰年的情况,此表可设置成一个2行13列的二维数组,其中第1行对应的每列(设1~12列有效)元素是平年各月的天数,第2行对应的是闰年每月的天数。程序中使用指针作为函数day_of_year的形式参数。910.2.1指针数组1、指针数组的定义指针数组是一种特殊的数组,指针数组的数组元素都是指针变量。指针数组的定义形式如下:

类型名称*数组名称[数组长度];

例如:int*p[5];因为下标运算符[]的优先级高于指针运算符*,上述定义等价于:int*(p[5])说明:(1)p是一个含有5个元素的数组,数组元素为指向int型变量。(2)指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。102、指针数组的使用指针数组最常用的是一维指针数组,常用于处理二维数组或多个字符串,尤其是字符串数组,(1)指针数组与二维数值数组例如下程序段:inta[3][4],*p[3];inti;...for(i=0;i<3;i++) p[i]=a[i];1112【例10.4】输出一个N×N的矩阵,要求非对角线上的元素值为0,对角线元素值为1。问题分析:(1)定义一个二维数组,存储矩阵的各元素值;(2)定义指针数组,和二维数组的各行元素相关联;(3)通过指针数组访问二维数组各元素值;(4)先将所有元素置0,然后再将对角线上的元素置1。如果当前元素的下标满足关系i==j或j==n-1-i时,说明此元素是主对角线获次对角线上的元素,则置1。【例10.5】

输入一个表示月份的整数,输出该月的名字。【例10.6】利用字符指针数组对字符串进行按字典排序。10.2.2指向指针的指针指针变量也有地址,存放指针变量地址的指针变量称为指向指针变量的指针或称指针变量的指针、多级指针。指针变量的指针在说明时变量前有两个*号。例如

char**lineptr;说明:lineptr是指向一个字符指针变量的指针,因为单目运算符*是自右向左结合的运算符,

因而说明符**lineptr应说明为:(*(*lineptr))。【例10.7】使用指向指针的指针输出若干个字符串。13多级间址的对应关系如图10.5所示:14m的地址m的值指针变量p变量m(a)单级间址(b)二级间址(c)多级间址m的地址m的值指针变量p1变量mP1的地址指针变量p2m的地址m的值指针变量p1变量mP(n-1)的地址指针变量pnP1的地址指针变量p2…10.3指针数组作main函数的参数带参数main函数的定义格式如下:intmain(intargc,char*argv[]){ …}argc和argv是main函数的形式参数。这两个形式参数的类型是系统规定的。如果main函数要带参数,就是这两个类型的参数;否则main函数就没有参数。变量名称argc和argv是常规的名称,当然也可以换成其他名称。15【例10.8】回显命令行参数的程序。#include"stdio.h"intmain(intargc,char*argv[]){ inti; for(i=1;i<argc;i++) printf("%s%c",argv[i],(i<argc-1)?'':'\n'); return0;}1610.4指向函数的指针----函数指针通常,程序中的每一个函数经编译连接后,其目标代码在计算机内存中是连续存放的,函数体内第一个可执行语句的代码在内存的地址就是函数执行时的入口地址,一个函数的入口地址由函数名表示。C语言可以声明指向函数的指针,指向函数的指针是存放函数入口地址的变量。把函数名赋给一个指向函数的指针,就可以用指向函数的指针来调用函数。

10.4指向函数的指针----函数指针假设有一个函数func,则其内存映射方式如下图所示:函数func所占内存单元

指令1指令2指令3......指令n函数指针内存示意图func10.4指向函数的指针----函数指针函数指针的说明形式:

[存储类型区分符]类型区分符(*

标识符)(参数表),…;标识符是指向函数的指针名

“(*

标识符)(参数表)”

是函数指针说明符,例如

int(*comp)(char*,char*);说明:comp是指向有两个char*参数的整型类型函数的指针,与指向数组的指针说明类似,说明符中用于改变运算顺序的()不能省。10.4指向函数的指针----函数指针关于函数指针有几点需要说明:(1)指向函数的指针变量一般形式为数据类型(*指针变量名)();(2)函数的调用可以通过函数名调用,也可以通过函数指针调用。(3)如果定义了int(*p)(),则(*p)()表示定义一个指向整型函数的指针变量,但它不固定指向哪一个函数,而只是表示定义了这样一个类型的变量,是专门用来存放函数的入口地址的。(4)在给函数指针变量赋值时,只需给出函数名而不必给出参数。(5)用函数指针变量调用函数时,只需将(*p)代替函数名即可,在

(*p)之后的括弧中需要写上实参。(6)对指向函数的指针变量,像p++、p--、p+n等运算是无意义的。10.4指向函数的指针----函数指针函数指针主要应用于将函数名传给另一个函数,C语言允许将函数的名字作为函数参数传给其他函数。由于参数传递是传值,相当于将函数名赋给形参。因此在被调用函数中,接收函数名的形参是指向函数的指针。例(下页):

10.4指向函数的指针----函数指针#include<stdio.h>floatadd(floatx,floaty){returnx+y;}intmain(){float(*p)(float,float);p=add;printf("2=3=%g\n",add(2,3));

printf("2=3=%g\n",p(2,3));printf("2=3=%g\n",(*p)(2,3));

return0;}程序运行结果为:

2+3=52+3=52+3=510.4指向函数的指针----函数指针例10-9(P281)用函数指针数组来实现对一系列函数的调用。10.5指针作为函数的返回值---指针函数C的函数可以返回除数组和函数外的任何类型数据和指向任何类型的指针,如数组的指针,函数的指针,也可是void指针,返回指针的函数称为指针函数。指针函数说明的一般形式为[存储类型区分符]类型区分符*函数名(参数表),…;其中“*函数名(参数表)”是指针函数说明符,例如

int*a(int,int);说明:a是一个整型指针函数,它有两个参数,返回值是一个指向整型数据的指针。注意:不可以将int*a(int,int)写成int(*a)(int,int)

二者说明的对象是完全不同的两个概念。后者表示a是一个指针变量。

10.5指针作为函数的返回值---指针函数例:写一个指针函数strstr(s,t),在字符串s中查找子串t,如果找到,返回t在s中第一次出现的起始位置,否则返回0。

char*strstr(char*s,char*t){char*ps=s,*pt,*pc; while(*ps!='\0') {for(pt=t,pc=ps;(*pt!='\0')&&(*pt==*pc);pt++,pc++);if(*pt=='\0')returnps; ps++;}return0;}10.5指针作为函数的返回值---指针函数例10-11(P282)

输入长度不超过100个字符的一行正文和长度不超过10个字符的一个字符串,在输入行中查找字符串的第一次出现,若找到则输出这一行,否则输出未找到的信息。10.5指针作为函数的返回值---指针函数注意:使用指针函数时要避免返回的指针所对应的内存空间因该指针函数的返回而被释放掉。返回的指针通常有以下几种:(1)函数中动态分配的内存(通过malloc等函数实现)的首地址;(2)通过指针形参所获得的实参的有效地址;(3)函数中的静态变量或全局变量所对应的存储单元的首地址;

10.6链表1.链表的概念链表是一种常用的数据结构。它是一种动态地进行存储分配的数据结构。它不同于数组,它不必事先确定好元素的个数,它可以根据当时的需要来开辟内存单元,它的各个元素不要求顺序存放,因此,它克服使用数组存放数据的一些不足。2.链表的实现链表是由若干个称为结点的元素构成的。每个结点包含有数据字段和链接字段。数字字段是用来存放结点的数据项的;链接字段是用来存放该结点指向另一结点的指针的。每个链表都有一个“头指针”,它是存放该链表的起始地址,即指向该链表的起始结点,它是识别链表的标志,对某个链表进行操作,首先要知道该链表的头指针。链表的最后一个结点,称为“表尾”,它不再指向任何后继结点,表示链表的结束,该结点中链接字段指向后继结点的指针存放NULL。单向链表单向链表仅有一个指向后继结点的指针双向链表单向链表仅有一个指向后继结点的指针链表的分类单向链表的操作(1)链表的建立(2)链表的输出(3)链表的删除(4)链表的插入(5)链表的存储(6)链表的装入使用一个学生成绩表,该表是由若干个学生的成绩组成,每个结点是一个学生的成绩。建立链表函数的算法如下:stuctstudent{char*namelongnum;intscorestructstudent*next;}建立链表函数内容如下:structstudent*creatlist(){structstudent*head,*p,*q;head=NULL;p=q=(structstudent*)malloc(sizeof(student));n=o;printf("Inputnodedata:");scanf("%d%s%d",&p->num,p->name,&p->score);while(p->num!=0){n++if(n==1){head=phead->next=NULL}elseq->next=pq=pp=(structstudent*)malloc(sizeof(structstudent));printf("Inputnodedata:")scanf("%1d%s%d",&p->num.p->name,&p->score);}q->next=NULLreturn(head);}链表输出函数链表输出函数算法如下:首先要知道输出链表的头指针。假定一个指向链表结点个数的结构指针P,使它指向链表的第一个结点,即将头指针赋给它。输出P所指结点的数据内容。再使P后移一个结点,输出该结点数据,直到链表的最后一个结点为止。链表输出函数内容voidprintlist(head)structstudent*head{structstudent*pprintf("\nNow,there%dnodedataare:\n",n)p=head;if(head!=NULL)do{printf("%ld,%s,%d\n",p->num,p->name,p->score);p=p=>next;}while(p!=NULL);elseprintf("Thereareaemptylist!\n");}应用程序举例:例

已有定义inta[10]={2,4,6,8,10,12,14,16,18},要求通过指针完成在数组a中插入一个x,使插入后仍然有序。程序分析:在main()函数中定义数组时,要多开辟一个用于存放插入数据的存储单元。如例中定义含10个整型元素的一维数组a并初始化。在用户自定义函数sort()中,定义一个基类型为int的指针变量p,并将数组a的首地址赋给指针p。为了将x插入到数组中,应从有序数组中找到插入的位置,然后将该位置起以后的所有元素依次后移,将插入位置腾出来。最后把x插入到插入的位置。源程序:#include"stdio.h"voidsort(int*p,intn,intx){ inti,j; for(i=0;i<n;i++) if(*(p+i)>x)break

温馨提示

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

最新文档

评论

0/150

提交评论