C语言程序设计06(初识指针)_第1页
C语言程序设计06(初识指针)_第2页
C语言程序设计06(初识指针)_第3页
C语言程序设计06(初识指针)_第4页
C语言程序设计06(初识指针)_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

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

文档简介

1、C语言程序设计语言程序设计重庆邮电大学移通学院重庆邮电大学移通学院计算机系计算机系 宋文强宋文强C语言程序设计第第6章章 初识指针初识指针第第6章内容章内容指针的概念指针的概念地址与指针的概念地址与指针的概念 取地址运算符和指针运算符取地址运算符和指针运算符 指针变量的定义与引用指针变量的定义与引用 指针变量作函数参数指针变量作函数参数6.2.1 指针与地址的概念指针与地址的概念什么是指针?什么是指针?指针就是地址,地址就是指针就是地址,地址就是指针指针什么是指针变量什么是指针变量指针变量就是指针变量就是用来存储用来存储其他变量在内存中地址的变量其他变量在内存中地址的变量指针是指针是C语言的一

2、个显著特色语言的一个显著特色指针的用途指针的用途在在C语言中,指针最重要的用途如下:语言中,指针最重要的用途如下: 允许以内存地址的方式引用大的数据结构,使数允许以内存地址的方式引用大的数据结构,使数据结构更简洁,内存空间更节省。据结构更简洁,内存空间更节省。通过参数传递同一内存地址,指针使程序的不同通过参数传递同一内存地址,指针使程序的不同部分能共享数据。部分能共享数据。通过内存空间的分配与释放,指针可以在程序执通过内存空间的分配与释放,指针可以在程序执行过程中指向新的内存空间,为动态数据结构(行过程中指向新的内存空间,为动态数据结构(如链表、队列和二叉树等)提供支持。如链表、队列和二叉树等

3、)提供支持。指针可以描述数据项之间的关系(如链表)。指针可以描述数据项之间的关系(如链表)。通过指针可以使程序员尽可能多地访问由硬件本通过指针可以使程序员尽可能多地访问由硬件本身提供的功能身提供的功能。1. 变量地址变量地址程序运行所需的代码和数据程序运行所需的代码和数据都保存在内存中都保存在内存中内存以字节作为基本存取单内存以字节作为基本存取单位位计算机为每一个内存单元进计算机为每一个内存单元进行了非负整数的顺序编号,行了非负整数的顺序编号,这个编号就是该内存单元的这个编号就是该内存单元的“地址地址”内存单元内存单元012345内存单内存单元编号元编号61. 变量地址变量地址在在C程序中定义

4、了一个变量,程序编译时系统就会程序中定义了一个变量,程序编译时系统就会根据变量的数据类型,给这个变量分配相应字节根据变量的数据类型,给这个变量分配相应字节数的存储单元数的存储单元一个变量在内存中可能占用多个字节,其中第一一个变量在内存中可能占用多个字节,其中第一个字节的地址就是变量地址个字节的地址就是变量地址在在C程序中,一个变量的地址值只能通过取地址运程序中,一个变量的地址值只能通过取地址运算符算符“&”获得,而不能直接将一个正整数值当成获得,而不能直接将一个正整数值当成变量地址值来使用变量地址值来使用1. 变量地址变量地址例如,程序中有如下变量定义:例如,程序中有如下变量定义:in

5、t a=0, b/2字节字节char c/1字节字节long d/4字节字节double x, y/8字节字节假设这些变量在内存中从地址假设这些变量在内存中从地址2000开始依次开始依次存放存放abcdxy200020012002200320042005200620072008200920102011201220132014201520162017201820192. 变量的访问方式变量的访问方式定义变量:定义变量: int i; 给变量给变量 i 分配分配2个字节的存储单元,假设为个字节的存储单元,假设为4050访问变量:访问变量:i=3; 在变量在变量 i 所代表的存储单元中存入的值为所代

6、表的存储单元中存入的值为33i变量名变量名变量值变量值存储单元的地址存储单元的地址4050(1)变量的直接访问变量的直接访问已经知道变量已经知道变量 i 的地址的地址直接访问直接访问i=3; printf(%d, i);scanf(%d, &i);4050i3直接访问:直接访问:(2)变量的间接访问变量的间接访问不知道变量不知道变量 i 的地址,但的地址,但pi知道知道间接访问间接访问从从pi中取出中取出 i 的地址,然后再去访问的地址,然后再去访问 i40504050pii80003间接访问:间接访问:6.2.2 取地址和指针运算符取地址和指针运算符1.取地址运算符取地址运算符“&a

7、mp;”“&”是是单目运算符单目运算符,用于获取一个变量在内存中,用于获取一个变量在内存中的存储地址。其形式为:的存储地址。其形式为: &变量名变量名 假定整型变量假定整型变量 i 的地址值的地址值4050,则,则只能通过只能通过&i来来获得获得,而不能将,而不能将4050简单的赋值给简单的赋值给存储地址的特存储地址的特殊变量殊变量pi。6.2.2 取地址和指针运算符取地址和指针运算符2.指针运算符指针运算符“*” “*”是是单目运算符单目运算符,它根据地址提取存储单元中,它根据地址提取存储单元中的值。其形式为:的值。其形式为: *地址地址 “地址地址”实际上是用一个特

8、殊变量(指针变量)实际上是用一个特殊变量(指针变量)来存储的来存储的,因此,因此“*”后面实际上是一个特殊变量后面实际上是一个特殊变量,而不是一个具体的值。,而不是一个具体的值。 6.2.2 取地址和指针运算符取地址和指针运算符&取地址运算符取地址运算符&i 表示变量表示变量i的地址的地址*取值运算符取值运算符“*(i的地址的地址)” 表示变量表示变量i的值的值因此因此*(&i) 表示变量表示变量 i 的值,即的值,即*(&i)与与i是等价的是等价的6.2.3 指针变量的定义与引用指针变量的定义与引用1.指针变量的概念指针变量的概念每个变量在内存中都有一定数量的

9、存储单元,第一个存储每个变量在内存中都有一定数量的存储单元,第一个存储单元的地址就是变量地址;一个变量的地址就是该变量的单元的地址就是变量地址;一个变量的地址就是该变量的“指针指针”。 C规定可以定义一种特殊变量,用它来存储变量的地址。规定可以定义一种特殊变量,用它来存储变量的地址。这种特殊变量就称之为这种特殊变量就称之为“指针变量指针变量”。 指针变量就是地址变量,用来存放地址,指针变量的值是指针变量就是地址变量,用来存放地址,指针变量的值是地址(即指针),也就是说,指针变量就是存放地址的变地址(即指针),也就是说,指针变量就是存放地址的变量。量。前面提到的特殊变量前面提到的特殊变量pi实际

10、上就是存放实际上就是存放i变量的指针变量,变量的指针变量,pi表示表示&i,则,则*pi就表示就表示 i 。2. 指针变量的定义指针变量的定义指针变量定义的一般形式为:指针变量定义的一般形式为: 数据类型数据类型 *指针变量名;指针变量名; 例如:例如: int *pi,*pj; float *pa,*pb; char *pc;指针变量定义的指针变量定义的“数据类型数据类型”一定要与存放的地一定要与存放的地址值对应的变量数据类型一致。址值对应的变量数据类型一致。如:如:用来存储用来存储int类型变量的地址的指针变量就是类型变量的地址的指针变量就是int型指针型指针变量变量用来存储用来存

11、储char类型变量的地址的指针变量就是类型变量的地址的指针变量就是char型型指针变量指针变量指向整型数据的指针类型表示成指向整型数据的指针类型表示成“int *”,读作,读作“指向指向int的指针的指针”或或“int指针指针”。3. 指针变量的初始化指针变量的初始化指针变量是存放地址的变量,指针变量究竟存放哪个变量指针变量是存放地址的变量,指针变量究竟存放哪个变量的地址,与哪个变量有关系,可以使用指针变量的赋值方的地址,与哪个变量有关系,可以使用指针变量的赋值方式来实现指针变量与一般变量建立关系。其一般形式为:式来实现指针变量与一般变量建立关系。其一般形式为: 指针变量名指针变量名=&

12、;变量名;变量名; 例如:例如: int i, j; int *pi, *pj; pi=&i; pj=&j; 也可以在定义指针变量的同时直接初始化,例如:也可以在定义指针变量的同时直接初始化,例如:int a, b;int *p1=&a, *p2=&b;指针变量指针变量pi存放的是变量存放的是变量i的地址的地址指针变量指针变量pj存放的是变量存放的是变量j的地址的地址*pi表示变量表示变量i的值的值*pj表示变量表示变量j的值的值一个变量的指针包括两方面的含义:一个变量的指针包括两方面的含义:“以存储单元编号表示的地址以存储单元编号表示的地址”“它指向的存储单元

13、的数据类型它指向的存储单元的数据类型” 。int *pi; 定义了一个定义了一个指向整型数据的指针变量指向整型数据的指针变量pi指针变量的指向关系指针变量的指向关系变量变量i=3内存用户数据区内存用户数据区4050变量变量j=6变量变量k=9变量变量pi4050405240548000000010010000000000000011000000000000011000000000int i, j, k;int *pi, *pj;i=3; j=6; k=9;如果执行了以下语句如果执行了以下语句 pi=&i;则意味着则意味着pi指向了整型变量指向了整型变量i这时这时*pi和和 i 都表示同

14、一值都表示同一值34. 指针变量的引用指针变量的引用指针变量的引用方式有以下两种:指针变量的引用方式有以下两种:指针变量名指针变量名表示所指变量的地址表示所指变量的地址*指针变量名指针变量名表示所指变量的值表示所指变量的值 例如,执行了如下语句:例如,执行了如下语句:int *pi, i; pi=&i; pi表示整型变量表示整型变量 i 的的地址地址*pi表示整型变量表示整型变量 i 的的值值在指针变量定义语句在指针变量定义语句 int *pi; 中中“pi”表示表示“指向整型数据的指针变量指向整型数据的指针变量”“int *”表示指向整型数据的指针类型表示指向整型数据的指针类型不能将

15、星号不能将星号“*”和和pi看成一个整体看成一个整体“*pi”在指针变量引用中,在指针变量引用中,“*pi”是一个整体,表示指是一个整体,表示指针变量针变量pi所指向的整型变量所指向的整型变量 i 的值的值补充实例补充实例1#include main( )int a , b;int *p, *q;a = 100; b = 10;p = &a; q = &b;printf(%d,%dn, a, b );printf(%d,%dn, *p, *q );运行结果为:运行结果为:100, 10100, 10补充实例补充实例2#include main( )int a = 100, b

16、= 10;int *p= &a, *q = &b;printf(%d,%dn, a, b );printf(%d,%dn, *p, *q );运行结果为:运行结果为:100, 10100, 10若有若有p=&a;那么那么&*p的含义是:的含义是:&和和*的优先级相同,为右结的优先级相同,为右结合性,先进行合性,先进行*p运算,即运算,即得到得到变量变量a,再执行再执行&运运算算因此因此&*p与与&a相同相同*&a 与与 a 等价等价(*p)+与与 a+ 等价等价指针变量的值可以交换指针变量的值可以交换执行语句执行语句 p

17、= &a; q=&b; 后后执行语句执行语句 q = &a; p=&b; 后后paqbpaqb例例6.2(方法(方法1)输入两个数,按从大到小的顺序将其输出输入两个数,按从大到小的顺序将其输出void main ( ) int a, b, t; scanf (%d, %d, &a, &b); if ( ab ) t=a; a=b; b=t; printf (max = %d , min = %d n, a, b) ;5ab595tab例例6.2 (方法(方法2)输入两个数,按从大到小的顺序将其输出输入两个数,按从大到小的顺序将其输出main (

18、) int *p1, *p2 , *p , a , b ; scanf (%d, %d, &a, &b) ; p1 = &a; p2 = &b ; if (ab) p=p1; p1=p2; p2=p; printf (a = %d , b = %d n, a, b) ; printf (max = %d , min = %d n, *p1, *p2) ;a5bp1p2abb5ap1p2ab例例6.2 分析分析一个指针变量在程序运行过程中可以改变指向,一个指针变量在程序运行过程中可以改变指向,使其获得不同的值。使其获得不同的值。当指针变量当指针变量pa、pb分别指

19、向整型变量分别指向整型变量a、b时,按时,按照照pa、pb的顺序输出,结果就是先输出的顺序输出,结果就是先输出a的值,的值,再输出再输出b的值。的值。如果交换如果交换pa、pb指向,使其分别指向变量指向,使其分别指向变量b、a,同样按照同样按照pa、pb的顺序输出,则结果就是先输出的顺序输出,则结果就是先输出b的值,再输出的值,再输出a的值,从而达到的值,从而达到a、b数据排序的数据排序的目的。目的。例例6.2 程序分析程序分析当本例所输入的数据当本例所输入的数据a小于小于b时时,数据交换前后的内存情况数据交换前后的内存情况如下:如下: 5 9 &a &ba=5b=9ppapb

20、&a&b 5 9 &b &aa=5b=9ppapb&a&b从图中可以看出,交换前后变量从图中可以看出,交换前后变量a、b的值并未改变,而是的值并未改变,而是指针变量指针变量pa、pb的值交换了,改变了指针变量的值交换了,改变了指针变量pa、pb的的指向,重新与变量指向,重新与变量b、a建立了联系。建立了联系。 6.3 指针变量作函数参数指针变量作函数参数指针变量作函数参数的主要方式:指针变量作函数参数的主要方式:函数调用时,将数据的存储地址作为参数传递给形参函数调用时,将数据的存储地址作为参数传递给形参地址传递特点:地址传递特点:l形参与实参占用

21、形参与实参占用同样的存储单元同样的存储单元l“双向双向”传递传递l实参和形参必须实参和形参必须是地址常量或变量是地址常量或变量 当使用指针变量作函数参数时,虽然仍然遵循当使用指针变量作函数参数时,虽然仍然遵循“值传递值传递”的原则,但确实能够实现在被调函数中交换的两个数,能在主的原则,但确实能够实现在被调函数中交换的两个数,能在主调函数中访问。调函数中访问。实参实参a的内存空间的内存空间复制地址值复制地址值实参地址内存空间实参地址内存空间形参地址内存空间形参地址内存空间值传递值传递地址传递方式:地址传递方式:主调主调函数函数被调被调函数函数例例6.3【例例6.3】输入一行字符,统计各类字符的数

22、量。输入一行字符,统计各类字符的数量。分析问题:分析问题: 定义定义5个指向整型数据的指针变量个指向整型数据的指针变量c1、c2、c3、c4、c5,分别统计大写字母、小写字母、空格、数字、,分别统计大写字母、小写字母、空格、数字、其它字符的数量。在循环中采用其它字符的数量。在循环中采用getche()函数输入若函数输入若干个字符,最后输入干个字符,最后输入“#”结束循环。结束循环。 例例6.3程序程序#include void main() int *c1,*c2,*c3,*c4,*c5; char ch; *c1=0; *c2=0; *c3=0; *c4=0; *c5=0; ch=getch

23、e(); while(ch!=#) if(ch=A&ch=a&ch=0&ch=说明说明p+、p-、+p、-p和和p-=n、p+=n、p=p+n、p=p-n(这里(这里n表示整型数据,表示整型数据,p为指针变量)等为指针变量)等运算的结果仍为指针。运算的结果仍为指针。 指针变量的加或减运算,只对具有连续存储单元指针变量的加或减运算,只对具有连续存储单元的相同数据类型才有实际意义,而对几个单变量的相同数据类型才有实际意义,而对几个单变量或不同数据类型的连续存储单元的变量均无实际或不同数据类型的连续存储单元的变量均无实际意义。意义。指针运算一般用于指向数组的指针变量。指针运算

24、一般用于指向数组的指针变量。7.3.2 指向一维数组的指针指向一维数组的指针1.指向一维数组的指针变量指向一维数组的指针变量C语言规定,数组名表示数组的首地址,即数组的第一个语言规定,数组名表示数组的首地址,即数组的第一个元素的地址。元素的地址。指针变量可以存放一般变量的地址(指向变量),也可以指针变量可以存放一般变量的地址(指向变量),也可以存放数组元素的地址(指向数组元素),还可以存放数组存放数组元素的地址(指向数组元素),还可以存放数组的首地址(指向数组)。的首地址(指向数组)。 定义定义 int a20,*p,i; 执行执行 p=a; 或或 p=&a0; 后后指针变量指针变量p

25、就指向了一维数组就指向了一维数组a,也称之为,也称之为p与与a建立了联系建立了联系在内存中指针变量在内存中指针变量p与数组与数组a之间的关系如图所示之间的关系如图所示pa13 39 96 61 1&a2:4005&a3:4007&a0:4001&a1:400380014001p+1p+2p+3a2a3a0一维数组与指针的等价表示法一维数组与指针的等价表示法l 执行语句:执行语句: int a20,*p=a;l 指向数组的指针变量指向数组的指针变量也可以带下标。如也可以带下标。如pi与与*(p+i)是等价的,)是等价的,*(a+i)和)和ai是等价是等价的。的。l

26、 下标运算符实际下标运算符实际上是变址运算符,即上是变址运算符,即ai先按先按a+i计算地址,计算地址,然后找出该地址单元然后找出该地址单元中的值。中的值。l C编译时,编译时,ai被解释被解释成成*(a+i),因此指针),因此指针表示法比下标表示法表示法比下标表示法效率更高。效率更高。a数组存储区数组存储区a0a1a24000400240044000+2*iai8010pp , a,&a0p+2,a+2,&a2p+i,a+i,&ai,&a0+ia194038p+19,a+19,&a19p+1,a+1,&a1*p,*a,p0*(p+1),*(a+

27、1),p1*(p+2),*(a+2),p2*(p+i),*(a+i),pi*(p+19),*(a+19),p19地址描述地址描述数组元素描述数组元素描述-1010082582. 指向一维数组元素的指针变量指向一维数组元素的指针变量执行执行 int a20,*p; p=a; *(a+i)、*(p+i)和和ai表示同一个数表示同一个数组元素组元素执行执行int a20,*p; p=&a6; p是是a6的地址,的地址,*p表示表示a6的值的值后移一个元素后移一个元素p-1是是a5的地址,的地址,*(p-1)表示表示a5的值的值前移一个元素前移一个元素p+1是是a7的地址,的地址,*(p+1)

28、表示表示a7a10p-2pp+4a3a4a5a6a7a8a9a11 *(p-2) *p *(p+2)3. 引用数组元素的不同方法引用数组元素的不同方法地址方式:地址方式:*(地址地址)#include void main() int a10,i; for(i=0; i10; i+) scanf(%d,a+i); printf(n); for(i=0; i10; i+) printf(%6d,*(a+i); 下标法:下标法: ai格式格式#include void main() int a10,i; for(i=0; i10; i+) scanf(%d,&ai); printf(n);

29、for(i=0; i10; i+) printf(%6d,ai); 3. 引用数组元素的不同方法引用数组元素的不同方法#include void main() int a10, i, *p; for(p=a,i=0; i10; i+) scanf(%d, p+i); printf(n); for(p=a, i=0; i10; i+) printf(%6d, *(p+i);7.4 一维数组及其指针作函数参数一维数组及其指针作函数参数l 在函数参数传递中,实参和形参的参数传递只有两种:在函数参数传递中,实参和形参的参数传递只有两种: 值传递值传递和和地址地址传递传递。指针变量存放的是地址,用指针变

30、量作为参数进行传递,实际。指针变量存放的是地址,用指针变量作为参数进行传递,实际上是一种地址传递方式。上是一种地址传递方式。函数参数传递中形参与实参必须在参数个数函数参数传递中形参与实参必须在参数个数和数据类型上相匹配和数据类型上相匹配。l 数组名是常量地址,指针变量也是存储地址的,因此,数组名是常量地址,指针变量也是存储地址的,因此,指针变量和数指针变量和数组名可以组合使用组名可以组合使用。 l 用数组名和指针变量作函数参数,实参与形参的对应关系有用数组名和指针变量作函数参数,实参与形参的对应关系有4种情况:种情况:方式方式实参实参形参形参 数组名数组名 数组名数组名 数组名数组名 指针变量

31、指针变量 指针变量指针变量 指针变量指针变量 指针变量指针变量 数组名数组名 1. 实参与形参都用数组名实参与形参都用数组名int main()int main() int a10; int a10; f(a,10); f(a,10); void f(int x,int n)void f(int x,int n) 数组数组a,xa0a1x0 x1x9a9可以认为有一形参数组,与实参数组共用一段内存单元。可以认为有一形参数组,与实参数组共用一段内存单元。2. 实参用指针变量,形参用数组名实参用指针变量,形参用数组名实参实参p为指针变量,通过为指针变量,通过p=a;使它指向使它指向a0。形参为数组

32、名。形参为数组名x,而,而数组名实际上是作为指针来处理的。将数组名实际上是作为指针来处理的。将a0的地址传递给了形参的地址传递给了形参x,也就是说数组也就是说数组x的首地址是的首地址是a0的地址。这样可以理解为数组的地址。这样可以理解为数组x与与数组数组a共用同一段内存单元。在执行过程中,共用同一段内存单元。在执行过程中,xi的变化就是的变化就是ai的变化。的变化。int main()int main() int a10, int a10,* *p;p; p=a; p=a; f(p,10); f(p,10); void f(int x,int n)void f(int x,int n) 数组数

33、组a,xa0, x0a1, x1pa9, x93. 实参用数组名,形参用指针变量实参用数组名,形参用指针变量实参实参a a为数组名,形参为数组名,形参x x为指向整型变量的指针变量。函数开为指向整型变量的指针变量。函数开始执行时,始执行时,x x指向指向a0a0。通过。通过x x值的改变,可以指向数组值的改变,可以指向数组a a的任一的任一元素。元素。int main()int main() int a10; int a10; f(a,10); f(a,10); void f(int void f(int * *x,int n)x,int n) 数组数组aa0a1xa94. 实参与形参都用指针

34、变量实参与形参都用指针变量实参实参p p和形参和形参x x都是指针变量。先使实参指针变量都是指针变量。先使实参指针变量p p指向数组指向数组a a,p p的值是的值是&a0&a0。然后再将。然后再将p p的值传给形参指针变量的值传给形参指针变量x x,x x的初值也的初值也是是&a0&a0。通过。通过x x值的改变可以使值的改变可以使x x指向数组指向数组a a的任一元素。的任一元素。int main()int main() int a10, int a10,* *p;p; p=a; p=a; f(p,10); f(p,10); void f(int void

35、f(int * *x,int n)x,int n) 数组数组aa0a1p,xa92022年2月12日星期六52应用实例应用实例【例例7.2】输入一个班输入一个班30个学生的个学生的C语言语言成绩,成绩,并输出最高分。并输出最高分。分析问题:分析问题: 可以定义一个具有可以定义一个具有30个元素的整型数组变量,个元素的整型数组变量,数组的每个元素代表一个学生的数组的每个元素代表一个学生的C语言语言成绩,成绩,然后通过循环结构对一维数组的每个元素进行比较,然后通过循环结构对一维数组的每个元素进行比较,得到最大值,即最高分。得到最大值,即最高分。2022年2月12日星期六53例例7.2程序程序下标法

36、下标法#include int main() int a30,max,i; /* 定义一维数组定义一维数组a */ for(i=0;i30;i+) scanf(%d,&ai); /* 给数组元素赋值给数组元素赋值 */ max=a0; for(i=0;imax) max=ai; /* 求最高分求最高分 */ printf(max=%dn,max); /* 输出最高分输出最高分 */ return(0);2022年2月12日星期六54例例7.2程序程序指针法指针法#include int max(int *p,int n);int main() int a30,v,i; /* 定义一维数

37、组定义一维数组a */ for(i=0;i30;i+) scanf(%d,&ai); /* 给数组元素赋值给数组元素赋值 */ v=max(a,30); /* 调用函数,返回最高分值调用函数,返回最高分值v */ printf(max=%dn,v); /* 输出最高分输出最高分 */ return(0);int max(int *p,int n) int m,i; m=*p; /*这里这里*p对应对应a0的值的值*/ for(i=0;im) m=*(p+i); /*求最高分,求最高分,*(p+i)对应对应ai的值的值*/ return(m);2022年2月12日星期六55例例7.3【例

38、例7.3】用筛法求用筛法求100以内的素数。以内的素数。分析问题:分析问题: 筛法的具体做法是:先把筛法的具体做法是:先把N个自然数按次序排列起来。个自然数按次序排列起来。1不是素不是素数,也不是合数,要划去。第二个数数,也不是合数,要划去。第二个数2是素数留下来,而把是素数留下来,而把2后面所后面所有能被有能被2整除的数都划去。整除的数都划去。2后面第一个没有划去的数后面第一个没有划去的数3是素数留下来,是素数留下来,再把再把3后面所有能被后面所有能被3整除的数都划去。整除的数都划去。3后面第一个没有划去的数后面第一个没有划去的数5是素数留下来,再把是素数留下来,再把5后面所有能被后面所有能

39、被5整除的数都划去。这样一直做整除的数都划去。这样一直做下去,就会把不超过下去,就会把不超过N的全部合数都筛掉,留下来的就是不超过的全部合数都筛掉,留下来的就是不超过N的的全部素数。全部素数。 因为希腊人是把数写在涂腊的板上,每划去一个数,就在上面记因为希腊人是把数写在涂腊的板上,每划去一个数,就在上面记一小点,求完全部素数后,许多小点就像一个筛子,所以就把埃拉托一小点,求完全部素数后,许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做斯特尼的方法叫做“埃拉托斯特尼筛埃拉托斯特尼筛”,简称,简称“筛法筛法”。 定义一个数组存放定义一个数组存放100以内的数,按照上述方法未被划掉的数保以内的数

40、,按照上述方法未被划掉的数保留原数,被划掉的数置留原数,被划掉的数置0,最后留下的数组元素值不为,最后留下的数组元素值不为0的数就是素的数就是素数。数。2022年2月12日星期六56例例7.3程序程序/* LT7_3.c */#include #include #define N 100void fun(int a,int n);int main() int i,n,aN+1; for(i=1;i=N;i+) ai=i; fun(a,N); /* 调用函数求素数调用函数求素数 */ printf(n); for(i=2,n=0;i=N;i+) if(ai!=0) printf(%5d,ai);

41、 /* 输出素数输出素数 */ n+; if(n%10=0) printf(“n”); /* 每行输出每行输出10个素数个素数 */ return(0);/* 用筛法求素数用筛法求素数 */void fun(int a,int n) int i,j; for(i=2;i=sqrt(n);i+) if(ai!=0) for(j=i+1;j=n;j+) if(aj!=0)&(aj%ai=0) aj=0; /*划掉的数置划掉的数置0值值*/ 例例7.4【例例7.4】将数组将数组array中中n个整数按相反顺序存放。个整数按相反顺序存放。分析:分析:如果有数组如果有数组a,正序为,正序为a0、

42、a1、an-2、an-1,则相反顺序为则相反顺序为an-1、an-2、a1、a0,即,即a0与与an-1交换,交换,a1与与an-2交换,直到数组的中间两个元素交换,直到数组的中间两个元素交换。交换。如果数组如果数组a为奇数个元素,则中间一个元素不动;如果数为奇数个元素,则中间一个元素不动;如果数组组a为偶数个元素,则中间两个元素要交换。为偶数个元素,则中间两个元素要交换。可以用可以用i变量来表示下标从小到大,用变量来表示下标从小到大,用j变量来表示下标从变量来表示下标从大到小,即交换大到小,即交换ai和和aj,其中,其中i取值取值0、1、,j取值取值n-1、n-2、,直到,直到i=(n-1)

43、/2为止。为止。4 9 7 11 0 7 6 5 34 9 7 11 0 7 6 5 3 2 22 3 5 6 7 0 11 7 9 42 3 5 6 7 0 11 7 9 4i jm例例7.4程序程序#include #define N 10void inverter(int *p, int n); int main() int i, arrayN; printf(The original array:n); for(i=0; iN; i+) scanf(%d, &arrayi); /* 输入数组元素输入数组元素 */ printf(n); inverter(array,N); /*

44、 调用函数,将数组反向存放调用函数,将数组反向存放 */ printf(The array has been inverted:n); for(i=0; iN; i+) printf(%dt, arrayi); printf(n); return(0);void inverter(int *p,int n) int i,j,m,temp; m=(n-1)/2; /*中间下标中间下标*/ i=0; /* 第一个元素下标值第一个元素下标值 */ j=n-1; /* 最后一个元素下标值最后一个元素下标值 */ for(;i=m; i+,j-) temp=*(p+i); *(p+i)=*(p+j);

45、*(p+j)=temp; 2022年2月12日星期六60例例7.5【例例7.5】编程实现插入一个数到有序数组中。编程实现插入一个数到有序数组中。 分析问题:分析问题: 插入是数组的基本操作之一,插入排序法的关键是找到该插入的位置,插入是数组的基本操作之一,插入排序法的关键是找到该插入的位置,然后依次移动插入位置及其以后的所有元素,空出的这个位置放入待插入的然后依次移动插入位置及其以后的所有元素,空出的这个位置放入待插入的元素。插入的基本思想是:首先要查找待插入数据在数组中的位置元素。插入的基本思想是:首先要查找待插入数据在数组中的位置pos,然,然后从最后一个元素开始往前直到下标为后从最后一个

46、元素开始往前直到下标为pos的元素依次往后移动一个位置,的元素依次往后移动一个位置,最后当第最后当第pos个元素的位置空出后就将要插入的数据插入。其原理如下图所个元素的位置空出后就将要插入的数据插入。其原理如下图所示。它是在示。它是在15、23、34、42、59、75这列有序数据中插入这列有序数据中插入50这个数成这个数成为新的有序数列:为新的有序数列: 15、23、34、42、50、59、75。15 23 34 42 59 75 15 23 34 42 59 75 a0 a1 a2 a3 a4 a5 a6a0 a1 a2 a3 a4 a5 a6 插入插入50前:前: 插入位置插入位置15 2

47、3 34 42 15 23 34 42 5050 59 75 59 75a0 a1 a2 a3 a4 a5 a6a0 a1 a2 a3 a4 a5 a6插入元素插入元素 插入插入50后后2022年2月12日星期六61例例7.5程序程序下标法下标法/* LT7_5A.c */#include #define SIZE 20/* 自定义函数声明自定义函数声明 */int findposition(int array,int n,int data); int insert(int array,int n,int data,int pos); int main() int aSIZE,d,i,n; p

48、rintf(Input array length: ); scanf(%d,&n); /* 输入插入前数组长度,输入插入前数组长度,n要求小于要求小于SIZE */ printf(nInput array %d element:n,n); for(i=0; in; i+) scanf(%d,&ai); /* 输入插入前已排好序的元素输入插入前已排好序的元素 */ printf(nBefore insert:n); for(i=0; in; i+) printf(%dt,ai); /* 输出插入前的数组元素输出插入前的数组元素 */ printf(nInput insert da

49、ta: ); scanf(%d,&d); /* 输入要插入的数据输入要插入的数据 */ n=insert(a,n,d,findposition(a,n,d); /* 插入数据插入数据 */ printf(nAfter insert %d:n,d); for(i=0; in; i+) printf(%dt,ai); /* 输出插入后的数组元素输出插入后的数组元素 */ return(0);2022年2月12日星期六62例例7.5程序程序下标法(续)下标法(续)/* 查找查找data数据在数据在array数组中的插入的位置数组中的插入的位置 */int findposition(int a

50、rray,int n,int data) int i; for(i=0;(iarrayi); i+); return(i); /* 返回插入的位置返回插入的位置 */* 在在array数组的数组的pos位置插入位置插入data数据数据 */int insert(int array,int n,int data,int pos) int i; for(i=n-1; i=pos; i-) arrayi+1=arrayi; /* 将插入位置以后的元素后移将插入位置以后的元素后移1位位 */ arraypos=data; /* 将数据将数据data插入到插入到pos的位置的位置 */ return(n

51、+1); /* 返回数组的长度返回数组的长度 */2022年2月12日星期六63例例7.5程序程序指针法指针法/* LT7_5B.c */#include #define SIZE 20int findposition(int array,int n,int data); int insert(int array,int n,int data,int pos); int main() int aSIZE,d,n,*p; printf(Input array length: ); scanf(%d,&n); /* 输入插入前数组长度,输入插入前数组长度,n要求小于要求小于SIZE */

52、printf(nInput array %d element: n,n); for(p=a; pa+n; p+) scanf(%d,p); /* 输入插入前已排好序的元素输入插入前已排好序的元素 */ printf(nBefore insert: n); for(p=a; pa+n; p+) printf(%dt,*p); /* 输出插入前的数组元素输出插入前的数组元素 */ printf(nInput insert data: ); scanf(%d,&d); /* 输入要插入的数据输入要插入的数据 */ n=insert(a,n,d,findposition(a,n,d); /*

53、插入数据插入数据 */ printf(nAfter insert %d: n,d); for(p=a; pa+n; p+) printf(%dt,*p); /* 输出插入后的数组元素输出插入后的数组元素 */ return(0);2022年2月12日星期六64例例7.5程序程序指针法(续)指针法(续)/* 查找查找data数据在数据在p所指向的数组中的插入的位置所指向的数组中的插入的位置 */int findposition(int *p,int n,int data) int i; for(i=0;(i*p); i+,p+); return(i); /* 返回插入的位置返回插入的位置 */*

54、 在在p所指向的数组中的所指向的数组中的pos位置插入位置插入data数据数据 */int insert(int *p,int n,int data,int pos) int i; for(i=n-1; i=pos; i-) *(p+i+1)=*(p+i); /* 将插入位置以后的元素后移将插入位置以后的元素后移1位位 */ *(p+pos)=data; /* 将数据将数据data插入到插入到pos的位置的位置 */ return(n+1); /* 返回数组的长度返回数组的长度 */2022年2月12日星期六65例例7.6【例例7.6】编程实现在一个数组中删除一个数编程实现在一个数组中删除一个

55、数 。 分析问题:分析问题: 删除是数组的另一个基本操作,删除的基本思想是:首先删除是数组的另一个基本操作,删除的基本思想是:首先要查找待删除数据在数组中的位置要查找待删除数据在数组中的位置pos,然后从,然后从pos+1开始到开始到最后逐一向前移动。即将最后逐一向前移动。即将pos+1的元素移动到的元素移动到pos元素的位置,元素的位置,再将再将pos+2的元素移动到的元素移动到pos+1元素的位置等等。其原理如元素的位置等等。其原理如下图所示。下图所示。 15 23 34 42 75 9015 23 34 42 75 90a0 a1 a2 a3 a4 a5 a6a0 a1 a2 a3 a4

56、 a5 a6 删除删除59后后15 23 34 42 59 75 90 15 23 34 42 59 75 90 a0 a1 a2 a3 a4 a5 a6a0 a1 a2 a3 a4 a5 a6 删除删除59前:前: 删除位置删除位置2022年2月12日星期六66例例7.6程序程序/* LT7_6.c */#include #define SIZE 20int main() int aSIZE,d,i,j,n; printf(Input array length: ); scanf(%d,&n); /* 输入数组长度,输入数组长度,n要求小于要求小于SIZE */ printf(nIn

57、put array %d element:n,n); for(i=0; in; i+) scanf(%d,&ai); /* 输入数组元素输入数组元素 */ printf(nBefore delete:n); for(i=0; in; i+) printf(%dt,ai); /* 输出删除前的数组元素输出删除前的数组元素 */ printf(nInput delete data: ); scanf(%d,&d); /* 输入要删除的数据输入要删除的数据 */ for(i=0,j=0; in; i+) if(ai!=d) /* 非指定数据时,保留该数据非指定数据时,保留该数据 */

58、 aj=ai; /* 将第将第i个位置的字符移动到第个位置的字符移动到第j个位置上个位置上 */ j+; printf(nAfter delete %d:n,d); for(i=0; iamid时,则时,则x在后半部分,重新赋值在后半部分,重新赋值low=mid,再次计算再次计算mid的值并将的值并将x与与amid进行比较;当进行比较;当xamid时,则时,则x在前在前半部分,重新赋值半部分,重新赋值high=mid,再次计算,再次计算mid的值并将的值并将x与与amid进行比进行比较。如此重复上述步骤。较。如此重复上述步骤。 2022年2月12日星期六68例例7.9程序程序#include

59、#define SIZE 20int bins(int *p,int n,int x);int main() int aSIZE,n,i=0,x,pos; printf(Input array length: ); scanf(%d,&n); printf(nInput array %d element:n,n); scanf(%d,&ai+); while(i=ai-1) i+; printf(nArray: ); for(i=0; in; i+)printf(%5d,ai); printf(nInput x: ); scanf(%d,&x); pos=bins(a,

60、n,x); if(pos!=-1) printf(%d,%d,pos,x); else printf(Not found); return(0);int bins(int *p,int n,int x) int low,high,mid; low=0; high=n-1; while(low*(p+mid) low=mid+1; else if(x*(p+mid) high=mid-1; else return(mid); return(-1); 补充实例补充实例 选择排序算法选择排序算法#include void main() int i, index, k, temp; int a10=35, 24, 19, 65, 48, 72, 29, 55, 61,70; for(i=0; i10; i+) index=i;/记下当前元素的下标记下当前元素的下标 for(k=i+1; k10; k+)/在剩下的元素中在剩下的元素中 if(akaindex) in

温馨提示

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

评论

0/150

提交评论