从问题到程序课件.ppt

上传人(卖家):三亚风情 文档编号:3511794 上传时间:2022-09-09 格式:PPT 页数:108 大小:337.51KB
下载 相关 举报
从问题到程序课件.ppt_第1页
第1页 / 共108页
从问题到程序课件.ppt_第2页
第2页 / 共108页
从问题到程序课件.ppt_第3页
第3页 / 共108页
从问题到程序课件.ppt_第4页
第4页 / 共108页
从问题到程序课件.ppt_第5页
第5页 / 共108页
点击查看更多>>
资源描述

1、从问题到程序从问题到程序第七章,指针第七章,指针程序执行中数据存于内存。程序执行中数据存于内存。在可用期间数据有确定存储位置,占据一些存储单元。在可用期间数据有确定存储位置,占据一些存储单元。内存单元的编号:内存单元的编号:地址地址。机器语言通过地址访问数据。高级语言用变量等作为机器语言通过地址访问数据。高级语言用变量等作为存储单元存储单元/地址的抽象。地址的抽象。建立变量就是安排存储。赋值时存入,用值时从中提取建立变量就是安排存储。赋值时存入,用值时从中提取外部变量外部变量/静态变量有全局存在期,程序执行前安排存储静态变量有全局存在期,程序执行前安排存储位置,保持到程序结束。位置,保持到程序

2、结束。自自动变量在函数调用时安排存储,至函数结束。再调用动变量在函数调用时安排存储,至函数结束。再调用时重新安排存储时重新安排存储。7.1 地址与指针地址与指针变量变量存在期存在期就是它占据所安排存储的期间。就是它占据所安排存储的期间。任何变量在存在期间总有确定存储位置,有固定任何变量在存在期间总有确定存储位置,有固定地址地址。寄存器变量可能放在寄存器,无地址。本章不考虑寄存器变量。寄存器变量可能放在寄存器,无地址。本章不考虑寄存器变量。变量存在时有地址,地址用二进制编码,因此可能成为变量存在时有地址,地址用二进制编码,因此可能成为程序处理的程序处理的数据数据。问题:地址作为数据有什么用?问题

3、:地址作为数据有什么用?若程序可以处理对象地址,就可通过地址处理相关对象。若程序可以处理对象地址,就可通过地址处理相关对象。对象(如变量)地址也被作为对象(如变量)地址也被作为数据数据,地址值地址值/指针值指针值。以地址为值的变量称为以地址为值的变量称为指针变量指针变量/指针指针(pointer)。指针是一种访问其他对象的手段指针是一种访问其他对象的手段,利用这种机制能更灵,利用这种机制能更灵活方便地实施对各种对象的操作。活方便地实施对各种对象的操作。指针的主要操作指针的主要操作 指针赋值:将程序对象的地址存入指针变量。指针赋值:将程序对象的地址存入指针变量。间接访问:通过指针访问被指对象。间

4、接访问:通过指针访问被指对象。指针还能保存其他对象的地址。下面讨论以变量为例。指针还能保存其他对象的地址。下面讨论以变量为例。指针指针p保存着变量保存着变量x地址,也说指针地址,也说指针p指向指向x。图示:。图示:指针变量 p变量 x图 7.1指针与被指的变量在在C中使用指针常能写出更简洁有效的程序。有些问题中使用指针常能写出更简洁有效的程序。有些问题必须用指针处理。必须用指针处理。指针在大型复杂软件中使用广泛。指针使用的水平是评指针在大型复杂软件中使用广泛。指针使用的水平是评价人的价人的C程序设计能力的重要方面。程序设计能力的重要方面。C指针灵活指针灵活/功能强。掌握有难度,易用错,应特别注

5、意。功能强。掌握有难度,易用错,应特别注意。应特别注意使用指针的常见错误,应特别注意使用指针的常见错误,注意!注意!指针是变量,可赋值,其指向可以改变。指针是变量,可赋值,其指向可以改变。现在现在p指向指向x,以后可能指向,以后可能指向y。通过通过p访问被指对象的访问被指对象的语句语句目前访问目前访问x,后来就访问,后来就访问y。这种新的灵活性很有用。这种新的灵活性很有用。7.2 指针变量的定义和使用指针变量的定义和使用指针有类型,只能保存特定类型的变量的地址指针有类型,只能保存特定类型的变量的地址指向指向int的指针的指针p只能指向只能指向int变量。变量。p所指也看作所指也看作int,从从

6、p间接访问当作间接访问当作int。常说。常说int指针指针p1等。等。定义指针需指明定义指针需指明指向类型指向类型。定义指向。定义指向int的的指针变量指针变量:int*p,*q;指针变量可以与其他变量一起定义:指针变量可以与其他变量一起定义:int*p,n,a10,*q,*p1,m;指针是指针是变量变量,可赋值取值,有定义域与存在期。应赋给,可赋值取值,有定义域与存在期。应赋给类型正确的指针值,取出的值是特定类型的指针值。类型正确的指针值,取出的值是特定类型的指针值。用用(int*)表示整型指针的类型,其他类似。表示整型指针的类型,其他类似。指针操作指针操作取地址运算符取地址运算符&和间接访

7、问操作和间接访问操作*。都是一元运算符。都是一元运算符指针变量 p变量 n图 7.2两个指针指向同一个变量的情况指针变量 q取地址运算取地址运算&写在变量描述写在变量描述(如变量名)前(如变量名)前取取变量地址,是对应类变量地址,是对应类型的指针值,可赋给类型合适的指针。例:型的指针值,可赋给类型合适的指针。例:p=&n;q=p;p1=&a1;多个指针可能同时指向同一变量。变量相等是值相等,多个指针可能同时指向同一变量。变量相等是值相等,两个指针变量相等说明它们指向程序里同一东西。两个指针变量相等说明它们指向程序里同一东西。间接运算间接运算间接运算得到被指针所指的变量,这种表达式可以像普间接运

8、算得到被指针所指的变量,这种表达式可以像普通变量一样使用。设通变量一样使用。设p指向指向n。间接赋值:。间接赋值:*p=17;这里写这里写*p相当于直接写相当于直接写n。另一个赋值:。另一个赋值:m=*p+*q*n;/*访问访问n三次三次*/+*p;/*使变量使变量n的值加的值加1,变成,变成18*/(*p)+;/*使变量使变量n的值再加的值再加1,变成,变成19。*/*p+=*q+n;/*变量变量n被赋以新值被赋以新值57*/q=&a0;/*指针指针q指向了数组指向了数组a的元素的元素*/指针作为函数参数指针作为函数参数指针作为函数参数有特殊意义,利用这种参数可写出能修改调用指针作为函数参数

9、有特殊意义,利用这种参数可写出能修改调用时环境的函数。时环境的函数。函数调用处的环境函数调用处的环境指在调用函数的位置能访问的变量全体。指在调用函数的位置能访问的变量全体。前面函数的特点:可使用调用处环境中变量的值(通过参数),前面函数的特点:可使用调用处环境中变量的值(通过参数),但不能修改这些变量(数组参数除外)。但不能修改这些变量(数组参数除外)。在函数在函数f里调用里调用g,可将,可将f的局部变量作为实参。但用的局部变量作为实参。但用g改变改变f局部局部变量的唯一方法是将变量的唯一方法是将g的返回值赋给的返回值赋给f的局部变量。的局部变量。这种方法局限性太强,例如无法在一个函数调用中修

10、改两个局部这种方法局限性太强,例如无法在一个函数调用中修改两个局部变量的值。利用变量的值。利用指针可以改变这种情况。指针可以改变这种情况。例:定义函数例:定义函数swap,希望用它交换两个变量的值。,希望用它交换两个变量的值。因因为要改变两个变量,无法通过返回值解决。为要改变两个变量,无法通过返回值解决。下面定义不行:下面定义不行:void swap0(int x,int y)int t=x;x=y;y=t;int f()int a=5,b=10;swap0(a,b);/*不行不行*/函数内修改形参,不会改变调用时的实参。函数内修改形参,不会改变调用时的实参。分析分析:要(在一函数里)通过:要

11、(在一函数里)通过调用函数调用函数g修改调用处的修改调用处的变量(如局部变量),必须在变量(如局部变量),必须在g里里掌握掌握这个这个变量。变量。用指针可以解决问题。用指针可以解决问题。把把m的地址(也是值)通过指针参数的地址(也是值)通过指针参数p传给传给g,函数内,函数内对对p间接访问就能操作间接访问就能操作m,包括对,包括对m赋值(改变赋值(改变m)。)。g 的函数体参数 p变量 m在函数体里用*p 可以访问和改变实参变量 m.图 7.3在函数里通过指针可以访问外面的变量例,通过函数调用把变量值设置为例,通过函数调用把变量值设置为3:void set3(int*np)*np=3;使用实例

12、:使用实例:int main()int n,m;set3(&n);/*设置设置n和和m*/set3(&m);printf(%d,%dn,n,m);return 0;请回忆请回忆scanf的情况。的情况。通过参数改变调用环境的方案通过参数改变调用环境的方案包括三方面:包括三方面:1.函数定义中用函数定义中用指针参数指针参数;2.函数内用函数内用间接操作间接操作实际变量;实际变量;3.调用时以被操作调用时以被操作变量的地址变量的地址作为实参。作为实参。函数函数swap可定义为:可定义为:void swap(int*p,int*q)int t=*p;*p=*q;*q=t;交换变量交换变量m和和n的值

13、,调用形式是:的值,调用形式是:swap(&m,&n);swap的参数类型是的参数类型是(int*),实参,实参必须是必须是合法的整型合法的整型变量的地址。变量的地址。swap 的函数体p变量 m图 7.4函数调用 swap(&m,&n)形成的现场变量 nq设有变量定义:设有变量定义:int a10,k;调用调用swap的实例:的实例:swap(&a0,&a5);swap(&a1,&k);介绍标准库函数介绍标准库函数scanf时,强调在接受输入的变量前必时,强调在接受输入的变量前必须写须写&,就是将变量的地址传给,就是将变量的地址传给scanf。scanf采用与采用与swap一样的技术,通过间

14、接访问为指定一样的技术,通过间接访问为指定变量赋值,把输入的值赋给指定变量。变量赋值,把输入的值赋给指定变量。例:改造上章输入整数值并检查值范围的函数,引进例:改造上章输入整数值并检查值范围的函数,引进指针参数,使之能更好处理输入错误。指针参数,使之能更好处理输入错误。前面实现里用特殊整数值指明输入出错,有很大缺点前面实现里用特殊整数值指明输入出错,有很大缺点(可能不存在合适的值)。(可能不存在合适的值)。指针参数提供了另一种方法:指针参数提供了另一种方法:函数增加一个指针参数,通过它送回读入值。用函数函数增加一个指针参数,通过它送回读入值。用函数返回值传递函数执行的状态信息。返回值传递函数执

15、行的状态信息。返回返回1表示输入成功,表示输入成功,0表示输入未能正常完成。表示输入未能正常完成。新函数定义:新函数定义:int getnumber(char prompt,int imin,int imax,int repeat,int*np)int i;for(i=0;repeat=0|irepeat;+i)printf(%s,prompt);if(scanf(%d,np)!=1|*npimax)printf(Correct range%d,%d.n,imin,imax);while(getchar()!=n);else return 1;return 0;前面的调用现在可以重写为:前面的

16、调用现在可以重写为:getnumber(Choose a range 0,n.Input n:,2,32767,5,&m);getnumber(Your guess:,0,m-1,5,&guess);更合适的调用形式:更合适的调用形式:if(getnumber(Your guess:,0,m-1,5,&guess)=0)/*处理输入出错的程序片段处理输入出错的程序片段*/这类函数的形参为指针,实参必须是合法变量地址。这类函数的形参为指针,实参必须是合法变量地址。这里可以看到标准库函数这里可以看到标准库函数scanf的样子。通过返回值的样子。通过返回值表示函数的工作情况,是表示函数的工作情况,是

17、一种一种常用技术。常用技术。与指针有关的一些问题与指针有关的一些问题空指针值:空指针值:一个特殊指针值,表示指针变量闲置(未一个特殊指针值,表示指针变量闲置(未指向任何变量)。唯一对任何指针类型都合法的值指向任何变量)。唯一对任何指针类型都合法的值空指针值用空指针值用0表示,标准库专门定义了符号常量表示,标准库专门定义了符号常量 NULLp=NULL;和和p=0;相同相同前一写法易看到是指针,用时必须包含标准头文件。前一写法易看到是指针,用时必须包含标准头文件。指针初始化指针初始化指针变量定义时可用合法指针值初始化:指针变量定义时可用合法指针值初始化:int n,*p=&n,*q=NULL;若

18、没有初始化,外部指针和局部静态指针自动初始化若没有初始化,外部指针和局部静态指针自动初始化为用空;局部自动指针不自动初始化。为用空;局部自动指针不自动初始化。指针使用中的常见错误指针使用中的常见错误使用指针的最常见错误是使用指针的最常见错误是非法间接访问非法间接访问:在指针未指:在指针未指向合法变量的情况下做间接。如:向合法变量的情况下做间接。如:int f(.)int*p,n=3;*p=2;.p没有初始化,没有初始化,没有指向合法变量。没有指向合法变量。“悬空指针悬空指针”指值不是(当时)合法的变量地址的指针指值不是(当时)合法的变量地址的指针变量,也常被称为变量,也常被称为“野指针野指针”

19、。间接访问悬空指针是严重错误,后果可能很严重。间接访问悬空指针是严重错误,后果可能很严重。常见错误写法(设常见错误写法(设p是悬空是悬空int指针,指针,n是是int变量):变量):swap(p,&n);scanf(.,p);scanf(.,n);编译程序不能发现编译程序不能发现scanf的错误。有些系统可能对第的错误。有些系统可能对第一个例子(假设一个例子(假设p未初始化)给出警告未初始化)给出警告。间接访问空指针也同样无理,是非法的。间接访问空指针也同样无理,是非法的。通用指针通用指针 类型类型(void*),可以指向任何变量可以指向任何变量。声明:。声明:int n,*p;double

20、x,*q;void*gp1,*gp2;任何指针值可以赋给通用指针(不必转换)。例:任何指针值可以赋给通用指针(不必转换)。例:gp1=&n;/gp1指向指向n(值是(值是n的地址)的地址)gp2=&x;/gp2指向指向x若通用指针若通用指针gpt指向指向g,g类型是指针类型是指针pt的指向类型,将的指向类型,将gpt赋给赋给pt(要写强制转换)通过(要写强制转换)通过pt保证正确访问保证正确访问g。gp1=&n;p=(int*)gp1;/*合法,合法,p是是(int*)*/q=(double*)gp1;/*不合法,不合法,q是是(double*)*/其他使用方式没有任何保证。其他使用方式没有任

21、何保证。编译程序不能识别强制转换错误。编译程序不能识别强制转换错误。指针类型转换并不改变指针值指针类型转换并不改变指针值 将整型变量将整型变量n的地址赋给通用指针的地址赋给通用指针gpt,gpt存的就是存的就是n的地址。赋回整型指针不会有问题。的地址。赋回整型指针不会有问题。将该地址赋给将该地址赋给double指针,就造成了混乱。指针,就造成了混乱。指针类型代表一种观点。被整型指针所指的变量总看成指针类型代表一种观点。被整型指针所指的变量总看成是整型的变量;被双精度指针指向是整型的变量;被双精度指针指向。指针转换是观点转换。从整型指针转换到通用指针就是指针转换是观点转换。从整型指针转换到通用指

22、针就是丢掉类型信息。保证恢复到原有类型(转回整型指丢掉类型信息。保证恢复到原有类型(转回整型指针),被指对象还可用。针),被指对象还可用。通用指针通用指针不能做间接运算不能做间接运算 被普通指针指向的变量的类型明确,间接后可以作为被普通指针指向的变量的类型明确,间接后可以作为该类型的变量使用该类型的变量使用 通用指针可以指向任何变量,通过通用指针间接访问通用指针可以指向任何变量,通过通用指针间接访问的意义无法确定。通用指针没提供被指对象的类型信的意义无法确定。通用指针没提供被指对象的类型信息,所以不能通过它们直接使用被指对象息,所以不能通过它们直接使用被指对象 通用指针最无用,唯一用途就是提供

23、指针值通用指针最无用,唯一用途就是提供指针值 标准库的某些函数使用了通用指针(后面会看到)标准库的某些函数使用了通用指针(后面会看到)7.3 指针与数组指针与数组C指针与数组关系密切,以指针为媒介可以完成各种数指针与数组关系密切,以指针为媒介可以完成各种数组操作。常能使程序更加简洁有效。组操作。常能使程序更加简洁有效。用指针做数组操作同样要用指针做数组操作同样要特别注意特别注意越界错误。越界错误。指针和数组的关系是指针和数组的关系是C语言特有的,除了由语言特有的,除了由C派生出的派生出的语言(如语言(如C+),一般语言中没有这种关系。),一般语言中没有这种关系。指向数组元素的指针指向数组元素的

24、指针类型合适的指针可以指向数组元素。类型合适的指针可以指向数组元素。假定有定义:假定有定义:int*p1,*p2,*p3,*p4;int a10=1,2,3,4,5,6,7,8,9,10;可以写:可以写:p1=&a0;p2=p1;p3=&a5;p4=&a10;p4没没指向指向a的元素,是指向的元素,是指向a最后元素向后一个位置。最后元素向后一个位置。C语言保证这个地址存在,但写语言保证这个地址存在,但写 *p4 是错误的是错误的。数组 a p1 图 7.5 指向数组 a 的元素的 4 个指针 p2 p4 p3 写数组名得到数组首元素地址,元素类型的指针值写数组名得到数组首元素地址,元素类型的指

25、针值。“p1=&a0;”可简写为:可简写为:p1=a;指针运算指针运算当指针当指针p指向数组元素时说指向数组元素时说p指到了数组里指到了数组里。这时由。这时由p可可以访问被以访问被p指的元素,还可访问数组的其他元素。指的元素,还可访问数组的其他元素。例:例:p1指向指向a首元素,值合法(首元素,值合法(a0的地址),的地址),p1+1也合法(也合法(a1的地址)。的地址)。p1+2、p1+3、也合法,分也合法,分别为别为a其他元素的地址。由它们可间接访问其他元素的地址。由它们可间接访问a各元素。各元素。例:例:*(p1+2)=3;/*给给a2赋值赋值*/p2=p1+5;/*使使p2指向指向a5

26、*/也可由指向非首元素的指针出发访问数组其他元素:也可由指向非首元素的指针出发访问数组其他元素:*(p2+2)=5;/*给给a7赋值赋值*/可用减法访问所指位置之前的元素:可用减法访问所指位置之前的元素:*(p2-2)=4;/*给给a3赋值赋值*/通过指针访问数组元素时必须保证不越界。通过指针访问数组元素时必须保证不越界。运算取得的指针值(即使不间接访问)必须在数组范围运算取得的指针值(即使不间接访问)必须在数组范围内(可过末元素一位置),否则无定义。内(可过末元素一位置),否则无定义。这类运算称为这类运算称为“指针运算指针运算”。其他常用指针运算:。其他常用指针运算:用指针运算得到的值做指针

27、更新:用指针运算得到的值做指针更新:p2=p2-2;/*这使这使p2改指向改指向a3*/用增用增/减量操作做指针更新(指针应指在数组里):减量操作做指针更新(指针应指在数组里):p3=p2;+p3;-p2;p3+=2;如果两指针指在同一个数组里,可以求差,得到它们如果两指针指在同一个数组里,可以求差,得到它们间的数组元素个数(带符号整数)。间的数组元素个数(带符号整数)。n=p3 p2;/*也可以求也可以求 p2 p3*/指在同一个数组里的指针指在同一个数组里的指针可以比较大小:可以比较大小:if(p3 p2).当当p3所指的元素在所指的元素在p2所指的元素之后时条件成立所指的元素之后时条件成

28、立(值(值为为1),否则不成立(值为),否则不成立(值为0)。两个指针不指在同一数)。两个指针不指在同一数组里时,比较大小没有意义。组里时,比较大小没有意义。两个同类型指针可用两个同类型指针可用=和和!=比较相等或不等;任比较相等或不等;任何指针都能与通用指针比较相等或不等,任何指针可何指针都能与通用指针比较相等或不等,任何指针可与空指针值(与空指针值(0或或NULL)比较相等或不等。)比较相等或不等。两指针指向同一数据元素,或同为空值时它们相等。两指针指向同一数据元素,或同为空值时它们相等。数组写法与指针写法数组写法与指针写法如果一个如果一个指针指针指在一个数组里,通过指针访问数组元素指在一

29、个数组里,通过指针访问数组元素的操作也可用下标形式写。的操作也可用下标形式写。设设p1指向数组指向数组a0,p3指向指向a5。可写:。可写:p13=5;p32=8;p13一类写法称为一类写法称为数组写法数组写法,*(p+3)一类写法称为一类写法称为指针写法指针写法。两类写法有等价效力,可以自由选用。两类写法有等价效力,可以自由选用。对数组名求值得到指向数组首元素的指针值对数组名求值得到指向数组首元素的指针值数组名数组名可以可以“看作看作”常量指针,可参与一些指针运算常量指针,可参与一些指针运算,与其他指针比大小,比较相等与不相等。与其他指针比大小,比较相等与不相等。通过数组名的元素访问也可以采

30、用指针写法。通过数组名的元素访问也可以采用指针写法。a3可可写为写为*(a+3)。注意:注意:数组名不是指针变量数组名不是指针变量,特别是不能赋值,不能,特别是不能赋值,不能更改。更改。若若a为数组,下面操作都是错误的:为数组,下面操作都是错误的:a+;a+=3;a=p;有些运算虽不赋值但也可能没意义。如有些运算虽不赋值但也可能没意义。如 a3 不可能不可能得到合法指针值,因其得到合法指针值,因其结果超出数组界限结果超出数组界限指针运算原理指针运算原理当一个指针指向某数组里的元素时,为什么能算出下一当一个指针指向某数组里的元素时,为什么能算出下一元素位置?(这是指针运算的基础)元素位置?(这是

31、指针运算的基础)指针有指针有指向类型指向类型,p指向数组指向数组a时,由于时,由于p的指向类型与的指向类型与a的元素类型一致,数据对象的大小可以确定。的元素类型一致,数据对象的大小可以确定。p+1的值可根据的值可根据p的值和数组元素大小算出的值和数组元素大小算出。由一个数。由一个数组元素位置可以算出下一元素位置,或几个元素之后的组元素位置可以算出下一元素位置,或几个元素之后的元素位置。指针运算的基础。元素位置。指针运算的基础。通用指针即使指到数组里,因没有确定指向类型,因此通用指针即使指到数组里,因没有确定指向类型,因此不能做一般指针计算,只能做指针比较。不能做一般指针计算,只能做指针比较。基

32、于指针的数组程序设计基于指针的数组程序设计指针运算是处理数组元素的另一方式,有时很方便。设指针运算是处理数组元素的另一方式,有时很方便。设有有int数组数组a和指针和指针p1,p2,下面代码都,下面代码都打印打印a的元素:的元素:for(p1=a,p2=a+10;p1 p2;+p1)printf(%dn,*p1);for(p1=a;p1 a+10;+p1)printf(%dn,*p1);for(p1=p2=a;p1-p2 10;+p1)printf(%dn,*p1);for(p1=a;p1-a 10;+p1)printf(%dn,*p1);数组参数的意义数组参数的意义C规定,数组参数规定,数组

33、参数就是就是相应的指针参数:相应的指针参数:int f(int n,int d).和和int f(int n,int*d).意义相同。数组参数的作用就是这样实现的。意义相同。数组参数的作用就是这样实现的。对应对应d的实参是被处理数组的名字,求值得到指针值,的实参是被处理数组的名字,求值得到指针值,符合形参需要,使符合形参需要,使d指向该数组的指向该数组的“首元素首元素”。前面函数体里参数用数组写法(对指针可这样写)。通前面函数体里参数用数组写法(对指针可这样写)。通过指针形参过指针形参d访问的相应实参数组里的各元素。(访问的相应实参数组里的各元素。(数组数组参数就是利用指针实现的!参数就是利用

34、指针实现的!)这也使采用数组参数的函数能修改实参数组。这也使采用数组参数的函数能修改实参数组。函数里也可用指针方式做元素访问。函数里也可用指针方式做元素访问。int intsum(int n,int a)int i,m=0;for(i=0;i n;+i)m+=*(a+i);return m;函数里不能用函数里不能用sizeof确定数组实参大小确定数组实参大小:函数的数组:函数的数组形参实际是指针,求形参实际是指针,求sizeof算出的是指针的大小。算出的是指针的大小。所有指针大小都一样,它们保存的都是地址值,各种类所有指针大小都一样,它们保存的都是地址值,各种类型的地址值采用同样表示方式。型的

35、地址值采用同样表示方式。另一方面,另一方面,sizeof的计算是在编译中完成的。实参是的计算是在编译中完成的。实参是动态运行中确定的东西。动态运行中确定的东西。使用数组的一段元素使用数组的一段元素以数组为参数的函数可处理一段元素。求元素和:以数组为参数的函数可处理一段元素。求元素和:double sum(int n,double a);设有双精度数组设有双精度数组b,40个元素已有值:个元素已有值:用用sum可求可求b所有元素之和所有元素之和/前一段元素之和:前一段元素之和:x=sum(40,b);y=sum(20,b);sum不知道不知道b的大小,它由参数得到数组首元素地址,的大小,它由参数

36、得到数组首元素地址,从这里开始求连续从这里开始求连续40或或20个元素的和。个元素的和。也可用也可用sum求求b中中下标下标12到到24的一段元素之和。的一段元素之和。z=sum(13,b+12);指针与数组操作函数实例指针与数组操作函数实例例例1,用指针方式实现字符串长度函数。一种方式:,用指针方式实现字符串长度函数。一种方式:int strLength(const char*s)int n=0;/*通过局部指针扫描串中字符通过局部指针扫描串中字符*/while(*s!=0)s+;n+;return n;另一实现:另一实现:int strLength(const char*s)char*p=

37、s;while(*p!=0)p+;return p-s;参数类型参数类型(char*),实参应是字符串或存字符串的数组实参应是字符串或存字符串的数组例例2,用指针实现字符串复制函数。直接定义:,用指针实现字符串复制函数。直接定义:void strCopy(char*s,const char*t)while(*s=*t)!=0)s+;t+;赋值表达式有值,赋值表达式有值,0就是就是0,函数可简化:,函数可简化:void strCopy(char*s,const char*t)while(*s=*t)s+;t+;把指针更新操作也写在循环测试条件里,程序是:把指针更新操作也写在循环测试条件里,程序是

38、:void strCopy(char*s,const char*t)while(*s+=*t+);/空语句空语句注意优先级与结合性,增量运算的作用与值等。注意优先级与结合性,增量运算的作用与值等。例例3 3,利用指针,输出,利用指针,输出int数组里一段元素数组里一段元素:void prt_seq(int*begin,int*end)for(;begin!=end;+begin)printf(%dn,*begin);prt_seq(a,a+10);prt_seq(a+5,a+10);prt_seq(a,a+3);prt_seq(a+2,a+6);prt_seq(a+4,a+4);prt_seq

39、(a+10,a+10);最后两个调用对应空序列。序列为最后两个调用对应空序列。序列为“半闭半开半闭半开”。还可写出许多类似函数。还可写出许多类似函数。“设置设置”函数:函数:void set_seq(int*b,int*e,int v)for(;b!=e;+b)*b=v;把序列中每个元素都用其平方根取代:把序列中每个元素都用其平方根取代:void sqrt_seq(double*b,double*e)for(;b!=e;+b)*b=sqrt(*b);求平均值:求平均值:double avrg(double*b,double*e)double*p,x=0.0;if(b=e)return 0.0;

40、for(p=b;p!=e;+p)x+=*p;return x/(e-b);字符指针与字符数组字符指针与字符数组常用字符指针指向字符数组元素。如指向常量字符串或常用字符指针指向字符数组元素。如指向常量字符串或存着字符串的字符数组,通常指向字符串开始。存着字符串的字符数组,通常指向字符串开始。也可指到字符串中间,把指的东西当字符串用。也可指到字符串中间,把指的东西当字符串用。p r o g r a m m i n g 0 指针p p r o g r a m m i n g 0 数组a(a)(b)定义字符指针时可用字符串常量初始化,如:定义字符指针时可用字符串常量初始化,如:char*p=Progr

41、amming;1)定义了指针)定义了指针p2)建立了一个字符串常量,内容为)建立了一个字符串常量,内容为Programming3)令)令p指向该字符串常量。图指向该字符串常量。图(a)char a=Programming;1)定义了一个)定义了一个12个字符元素的数组个字符元素的数组2)用)用Programming各字符初始化各字符初始化a的元素,图的元素,图(b)1)指针指针p可重新赋值(数组不能赋值):可重新赋值(数组不能赋值):p=Programming Language C;2)p和和a类型不同,大小不同。类型不同,大小不同。a占占12个字符的空间。个字符的空间。3)a的元素可以重新赋

42、值。如:的元素可以重新赋值。如:a8=e;a9=r;a10=0;a的内容现在变成的内容现在变成“Programmer”按按规定,字符串常量不得修改规定,字符串常量不得修改 p r o g r a m m i n g 0 指针p p r o g r a m m i n g 0 数组a(a)(b)可定义字符指针变量并让它指向已有字符数组。可定义字符指针变量并让它指向已有字符数组。C程序程序常用这种方式使用和操作字符数组内容。常用这种方式使用和操作字符数组内容。例如,输入一行到数组里例如,输入一行到数组里:enum NLINE=256;char lineNLINE;int count;char*p;

43、/*-*/p=line;w h i l e(p l i n e N L I N E-1&(*p =gerchar()!=n)+p;*p=0;/*做成字符串做成字符串*/*-*/for(count=0,p=line;*p!=0;+p)if(*p=e)+count;/*统计统计e的个数的个数*/7.4 指针数组指针数组复杂复杂C程序里常用到指针的数组。程序里常用到指针的数组。例:需要一组字符串,常用字符指针数组索引它们。如例:需要一组字符串,常用字符指针数组索引它们。如软件中错误信息常用一组字符串表示。分散管理不便。软件中错误信息常用一组字符串表示。分散管理不便。可定义指针数组,指针分别指向输出信

44、息串常量。可定义指针数组,指针分别指向输出信息串常量。也可定义其他类型的指针数组,如指向整数或者其他类也可定义其他类型的指针数组,如指向整数或者其他类型的指针的数组,下面讨论以字符指针为例型的指针的数组,下面讨论以字符指针为例。定义字符指针数组:定义字符指针数组:char*pa10;优先级也适用于定义。优先级也适用于定义。优先级高,优先级高,pa是数组,其元是数组,其元素是字符指针。素是字符指针。定义字符指针数组时用字符串常量提供初始值。例:定义字符指针数组时用字符串常量提供初始值。例:char*days=Sunday,Monday,Tuesday,Wednesday,Thursday,Fri

45、day,Saturday;简单实例简单实例:printf(Work days:);for(i=1;i6;+i)printf(%s,daysi);printf(nWeekend:);printf(%s%sn,days6,days0);字符指针数组实例字符指针数组实例:改写第改写第6章的章的C语言关键字统计程序,把原来的两维字语言关键字统计程序,把原来的两维字符数组符数组keywords改为字符指针数组。改为字符指针数组。只需定义下面数组,并用(关键字)字符串对各指针做只需定义下面数组,并用(关键字)字符串对各指针做初始化:初始化:char*keywords=auto,break,.volatil

46、e,while;其他部分不需要改,程序可以正常工作。其他部分不需要改,程序可以正常工作。指针数组与两维数组指针数组与两维数组两维字符数组与字符指针数组不同两维字符数组与字符指针数组不同。定义:。定义:char color16=RED,GREEN,BLUE;char*color=RED,GREEN,BLUE;R E D 0 0 0 G R E E N 0 B L U E 0 0(a)数 组 color1指 针 数 组 colorR E D 0G R E E N 0B L U E 0(b)命令行参数的处理命令行参数的处理启动程序的基本方式是输入命令,要求启动程序的基本方式是输入命令,要求OS装入程

47、序代装入程序代码文件并执行。码文件并执行。命令行命令行:描述命令的字符行。:描述命令的字符行。在图形用户界面系统(如在图形用户界面系统(如Windows)里,命令行存在于)里,命令行存在于图标图标/菜单的定义中。菜单的定义中。源文件源文件abcd.c得到可执行文件得到可执行文件abcd.exe。键入命令:键入命令:abcd该程序就会被装入执行。该程序就会被装入执行。除命令名外,命令行常包括其他信息。除命令名外,命令行常包括其他信息。DOS命令:命令:copy a:file1.txt dir windowssystem/p附加信息也是字符序列,称为附加信息也是字符序列,称为命令行参数命令行参数。

48、前面的程序都没有包含处理命令行的功能前面的程序都没有包含处理命令行的功能要写能够处理命令行参数的程序,需要用要写能够处理命令行参数的程序,需要用C语言的命令语言的命令行参数机制。行参数机制。处理命令行参数很像处理函数参数,写程序时要考虑处理命令行参数很像处理函数参数,写程序时要考虑和处理程序启动时实际命令行提供的信息。和处理程序启动时实际命令行提供的信息。命令行被看作空格分隔的字段,各个命令行被看作空格分隔的字段,各个命令行参数命令行参数。命令名编号为命令名编号为0,其余依次编号。程序启动时把各命令,其余依次编号。程序启动时把各命令行参数做成字符串,程序里可按规定方式使用。行参数做成字符串,程

49、序里可按规定方式使用。设有程序设有程序 prog1;设启动程序的命令行是:;设启动程序的命令行是:prog1 there are five arguments这时这时prog1是编为是编为0的命令行参数,的命令行参数,there是编号是编号1的命的命令行参数,令行参数,;共;共5个命令行参数。个命令行参数。通过通过main的参数可获取命令行参数。的参数可获取命令行参数。main(void)表表示不处理命令行参数,示不处理命令行参数,main的另一形式带两个参数:的另一形式带两个参数:int main(int argc,char*argv);main开始执行时:开始执行时:argc是命令行参数的

50、个数是命令行参数的个数 argv指向含指向含argc+1个指针个指针字符指针数组,前字符指针数组,前argc个指个指针指向各命令行参数串,最针指向各命令行参数串,最后有一个空指针后有一个空指针argcargv函数 mainp r o g 1 0t h e r e 0a r e 0f i v e 0a r g u m e n t s 00空指针5图为执行下面命令时图为执行下面命令时 main 函数里的现场情况函数里的现场情况prog1 there are five argumentsmain参数参数常用常用argc、argv作作为名字(实际上可以用其他名为名字(实际上可以用其他名字)。参数类型确

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(从问题到程序课件.ppt)为本站会员(三亚风情)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|