实验8 指针
一、实验目的
1、通过实验进一步掌握指针的概念,会定义和使用指针变量;
2、能正确使用数组的指针和指向数组的指针变量;
3、能正确使用字符串的指针和指向字符串的指针变量;
4、了解指向指针的指针的概念及其使用方法。
二、实验内容
1、编程解决日期转换问题,要求如下:
(1)任意给定某年某月某日,计算它是这一年的第几天。
(2)已知某一年的第几天,计算它是这一年的第几月第几日。
分别用函数实现,并在主函数中调用验证。
2、编写一个函数,从一组实形数中求出最大值、最小值、平均值,并通过参数返回主函数,在主函数中输入10个实形数(用指针变量作为参数传送的方式实现函数调用)。
3、编写一个函数:给定一个以秒为单位的时间量,计算所包含的小时数、分钟数和剩余的秒数。在主函数中调用验证。
4、编写一函数,统计字符串中字母、数字、空格和其他字符的个数,在主函数中输入字符串并输出统计结果(用指针变量作为参数传送的方式实现函数调用)。
5、编写一函数,要求矩阵中值最大的元素的值,以及它的行号和列号。在主函数中输入一个3×4的矩阵,并将结果输出(用指针变量作为参数传送的方式实现函数调用)。。
6、用一个函数实现两个字符串的比较,即自己写一个strcmp函数,函数原型为:int strcmp (char * p1, char * p2);
设p1指向字符串s1,p2指向字符串s2,要求当s1=s2时,函数返回值为0,如果sl≠s2,则返回它们二者第一个不相同字符的ASCII码差值(如“BOY”与“BAD”的第二个字母不相同,“O”与“A”之差为79—65=14);如果sl>s2,则输出正值;如果sl 两个字符串s1、s2由main函数输入,并输出字符串比较结果。 7、编程求字符串的长度。 要求:求长度用自定义函数实现,字符串的输入、长度的输出由主函数实现。用指针变量作函数参数。提示:用指针从字符串首部逐个往后检查每一个字符,如果不是’\0’字符,则计数器加1,如果是’\0’字符,则结束。 参考N-S图: main( )函数的N-S图: 9、程序填空: (1)一维数组和指针。分别采用下标法、数组名法和指针法访问数组元素,求出10 个数中的最大值。 下标法: # include void main() { int a[10],i,max; for ( ) scanf (“%d”, ); for ( ) if ( ) max=a[i]; printf (“MAX=%d\n”,max); } 数组名法: #include void main() { int a[10],i,max; for ( ) scanf (“%d”, a+i); for ( ) if ( ) max=*(a+i); printf (“MAX=%d\n”,max); } 指针法: #include void main() { int a[10]; int *p, max; for ( ) scanf (“%d”, p); for ( ) if ( ) max=*p; printf (“MAX=%d\n”,max); } 10、编程:有n个整数,使其前面各数顺序后移m个位置,最后m个数变成最前面m 个数字。 C++程序设计 第8章指针和引用 在程序运行时变量和函数都存放在内存中,通过变量名来访问数据、通过函数名来调用函数都是直接访问方式。还有另一种间接访问方式就是用指针。指针的本质是内存地址。指针往往用于说明函数的形参,使实参能通过指针传递,以提高函数调用的效率。利用指针能动态地使用内存,以提高内存使用效率。指针也能用来表示数据关联,以构成复杂的数据结构。指针是C程序中最常见的类型。引用是C++扩展的新概念,主要用于函数形参和返回类型。本章将详细介绍指针和引用的概念及应用。 8.1 指针及指针变量 指针(pointer)的本质是内存地址。指针变量就是专门存储地址的一种变量。通过指针变量所存储的地址来访问数据是一种间接寻址方式。由于处理器的机器语言能支持间接寻址,所以使用指针可以达到较高的计算性能。 8.1.1 地址的概念 C++编译器对不同对象或变量按其数据类型分配合适大小的存储空间。例如为char或bool型变量分配1个字节(bytes)的存储空间,short分配2字节,int和float分配4个字节,为double型变量分配8个字节的存储空间。当程序执行时,代码和变量都加载到内存中。计算机内存被分成若干个存储单元,存储单元以字节为单位。每个存储单元都有一个固定的编号,这个编号就是内存地址。尽管一个变量可能占用多个字节空间,但都通过第一个字节的地址来访问。存放某个变量的第一个字节的地址就是该数据的首地址。 指针即内存单元的地址,而数据是内存单元中的内容(或值)。 假设在程序中说明了1个int型的变量a,其值为68。系统为变量a分配4字节的存储空间,设首地址为0X0065FDF4。通过地址0X0065FDF4就能找到变量a在内存中的存储单元,从而对变量a进行访问。0X0065FDF4就是变量a的指针。知道一个变量的地址和变量的类型就能对变量进行访问,就如同知道房间号就能找到房间,从而找到房间里的主人。 指针是一种特殊的数据类型。所有类型的变量,无论是基本类型、用户定义类型、还是这些类型的数组,在一次运行时都有确定的地址,因此它们都有指针。对于32位计算机,地址长度就是32位,因此一个指针需要4个字节,与整型int、浮点型float具有相同大小的长度。一个指针不仅有值,而且还要确定其类型,表示它能指向什么类型的数据,决定了通过它要取用多少字节作为该变量的值。 //lnkList.h 无头结点的单链表的类(lnkLIST类) #ifndef _lnkLIST_H_ #define _lnkLIST_H_ template 指针1 选择题 1.如下程序段: int *p ,a=10 ,b=1 ; p=&a ;a=*p+b ; 执行该程序段后,a 的值为。 A. 12 B. 11 C. 10 D. 编译出错 2.若有以下定义和语句: double r=99 ,*p=&r ; *p=r ; 则以下正确的叙述是。 A. 以下两处的*p 含义相同,都说明给指针变量p 赋值 B. 在"double r=99,*p=&r;"中,把r 的地址赋值给了p 所指的存储单元 C. 语句"*p=r;"把变量r 的值赋给指针变量p D. 语句"*p=r;"取变量r 的值放回r 中 3.若有说明int *p,a;则能通过scanf语句正确给a存入数据的程序段是()。 A.p=&a; scanf(“%d”,p); B.scanf(“%d”,a); C.p=&a; scanf(“%d”,*p); D.*p=&a; scanf(“%d”,p); 4.若int x ,*pb;,则正确的赋值表达式是。 A. pb=&x B. pb=x; C. *pb=&x; D. *pb=*x 5.若有说明:int i, j=2,*p=&i;,则能完成i=j 赋值功能的语句是。 A. i=*p; B. *p=*&j; C. i=&j; D. *p=i; 6.若已定义:int a[9] ,*p=a;并在以后的语句中未改变p 的值,不能表示a[1]地 址的表达式是()。 A. p+1 B. a+1 C. a++ D. ++p 7.若有以下说明:int a[10]={1,2,3,4,5,6,7,8,9,10} ,*p=a ; 则数值为6 的表达式是( )。 A. *p+6 B. *(p+6) C. *p+=5 D. p+5 8.以下程序段的运行结果是()。 int a[10]={1,2,3,4,5,6,7,8,9,10}; int *p=&a[3],*q; q=p+2; printf(“%d”,*p+*q); A.16 B.10 C.8 D.6 1文档来源为:从网络收集整理.word 版本可编辑. 第八章 地址和指针 第一节 变量的地址和指针 1、计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就成为内存地址。 2、程序中定义了一个变量,c 编译系统就会根据定义中变量的类型,为其分配一定字节数的内存空间: Short int 2 Int float 4 Double 8 char 1 指针 4 图8.1 变量在内存中所占字节的地址示意图 每个变量的地址就是指该变量所占存储单元的第一个字节的地址。 3、直接存取:程序中我们对变量进行存取操作,实际上也就是对某个地址的存储单元进行操作。这种直接按变量的地址存取变量值的方式。 4、在c 语言中,还可以定义一种特殊的变量,这种变量只 a 2001 p 3001 a b x 1012 1013 1015 1016 1201 1202 1203 1204 a 1文档来源为:从网络收集整理.word 版本可编辑. 是用来存放内存地址的。 图8.2 存放地址的指针变量示意图 通过变量p 间接得到变量a 的地址,然后再存取变量a 的值的方式称为“间接存取”方式,通常变量p 指向了变量a ,变量a 是变量p 所指向的对象。 5、用来存放指针地址的变量就称作“指针变量”。 6、“变量p 指向变量a ”的含义就是指针变量p 中存放了变量a 的地址。 7、在某些场合,指针是使运算得以进行的唯一途径。 第二节 指针的定义赋值 一、 指针变量的定义和指针变量的基本类型 1、 定义指针变量的一般形式如下: 类型名 *指针变量名1,*指针变量名2…… 说明:1)类型名是基本类型。 2)*是说明符。(而在调用的时候,代表的是存储单元中的值) 3)指针变量名是用户标识符。 例:1)int *pi,*pj; pi pj 只能存放整型变量的地址 int I,*pi;double *pj; 2)p 为一个指向指针的指针变量 2002 2002 1012 1013 p p 第八章变量的地址和指针 变量:整 int 4B 单精度 float 4B 双精度 double 8B 存储空间:随机存放 short int a,b; float c,d; a 2B b 2B c 4B d 4B 1012 1013 1018 1019 2010 2011 2012 2013 3033 3034 3035 3036 变量的地址:该变量所占存储单元的第一个字节的 地址 &a=1012 p a *定义一个指针变量用于存放地址 4039 1012 地址就是指针 1.指针变量:存放(指向)不同地址的指针 定义:类型说明 *变量名; int *p; (指向一个整型变量) float *f; 2.给指针变量赋值 (1)int a,*p; p=&a; /*将a变量的地址赋给指针p*/ (2)初始化赋值 int a,*p=&a; 3.赋值形式: (1)赋值运算 int a,*p; p=&a; 注意:p=1000; (错误) (2)初始化赋值 int a,*p=&a; (3)把一个指针变量的值送给相同类型的另一个指针变量 int a,*pa,*pb; pa=&a; pb=pa; /*两个指针同时指向a*/ (4)把数组的首地址,送给指针变量 (数组名就表示数组的首地址) int b[5],*p; p=b; 或者 p=&b[0] (也可以指在数组中间 p=&b[2]) (5)把字符串的首地址送给字符型的指针变量 char *p; p="abcdef"; (把字符串的首地址送给p) 4.指针变量的运算 &:取地址符号 *:取内容运算符(把指针所指变量内容取出来) 优先级相同 main() {int a,*p=&a; a=5; printf("%d\n",*p); printf("%d\n",p); printf("%d\n",&p);} 如何透彻理解C语言中指针的概念 强大的指针功能是C语言区别于众多高级语言的一个重要特征。C语言指针的功能强大,使用灵活多变,可以有效地表示复杂的数据结构、动态分配内存、高效地使用数组和字符串、使得调用函数时得到多个返回值。而它的应用远不限于此。初学者对于指针的概念总是感到无所适从,有时觉得“自己懂了,为什么编译器就是不懂呢”,常有茫然和无助的感觉。 学好指针的关键在于深入了解内存地址的空间可以理解为一个一维线性空间,内存的编址和寻址方法,以及指针在使用上的一些规定。事实上,指针就是方便我们对内存地址直接进行操作的,是为程序员服务的,我们只要抓住指针想要帮助我们解决什么问题这个核心,就可以轻松地理解它的工作原理。 什么是指针,指针有什么作用 指针就是指向一个特定内存地址的一个变量。简化了的内存空间模型是按照从0到某一个数(比如1048575=1M-1)的一维线性空间,其中的每一个数对应一个存储单元,即1个字节。指针有两个属性:指向性和偏移性。指向性指的是指针一定要有一个确定的指向,偏移性则是体现指针重要应用的方面,即指针可以按程序员的要求向前或向后偏移。 指针的应用往往与数组联系在一起,为了方便说明问题,不妨从数组开始解释指针的偏移。数组就是许多的变量,它的一个重要特征就是在内存空间中连续地存放,而且是按下标顺序存放。比如我们定义一个有100个变量的一维整型数组,它一定从内存的某一个存储单元开始按数组下标顺序存放,连续占用100*4=400字节。当我们定义一个数组时,系统就会自动为它分配一个指针,这个指针指向数组的首地址。(在本文剩余部分的论述中,不加区分地使用“指向数组的首地址”与“指向数组的第一个元素”这两种说法,事实上这两种说法也是一致的。) 为了让系统了解每一次指针偏移的单位,也为了方便程序员进行指针偏移(让程序员记住一个整形变量占用4字节,一个字符型变量占用1字节……等等是很麻烦的),不用每次去计算要偏移多少个字节,C语言引入了指针的基类型的概念。基类型的作用就是让系统了解某个指针每次偏移的字节数。比如,对于一个字符型指针,它每次偏移(比如ptr=ptr+1)所起到的作用就是让指针偏移1字节;而对于一个整型指针,它每次偏移就应该是4字节。这样操作数组时就带来了方便。比如对于一个指向某个整型数组起始存储单元(称为首地址)的指针ptr,ptr=ptr+1就表示将该指针指向这个数组的下一个元素的存储单元,即向后移动4字节,而不仅仅是移动一个存储单元(即移动1字节)。 &()、*()、和[ ]运算符的意义 在本文中,将&()、*()和[ ]都看成是运算符。这样可以方便理解这三个概念。简单地说,&()将某个标识符(比如变量)转化为其在内存空间中的地址,而*()是产生一个对应于某个地址的标识符,[ ]就更复杂一点,ptr[i]表示 第八章指针 一、选择题 1、设有定义:int n1=0,n2,*p=&n2,*q=&n1;,以下赋值语句中与n2=n1;语句等价的是 A)*p=*q; B)p=q; C)*p=&n1; D)p=*q; 2、若有定义:int x=0, *p=&x;,则语句printf("%d\n",*p);的输出结果是 A)随机值 B)0 C)x的地址 D)p的地址 3、以下定义语句中正确的是 A)char a='A'b='B'; B)float a=b=10.0; C)int a=10,*b=&a; D)float *a,b=&a; 4、有以下程序 main() { int a=7,b=8,*p,*q,*r; p=&a;q=&b; r=p; p=q;q=r; printf("%d,%d,%d,%d\n",*p,*q,a,b); } 程序运行后的输出结果是 A)8,7,8,7 B)7,8,7,8 C)8,7,7,8 D)7,8,8,7 5、设有定义:int a,*pa=&a;以下scanf语句中能正确为变量a读入数据的是 A)scanf("%d",pa) ; B)scanf("%d",a) ; C)scanf("%d",&pa) ; D)scanf("%d",*pa) ; 6、设有定义:int n=0,*p=&n,**q=&p;则以下选项中,正确的赋值语句是 A)p=1; B)*q=2; C)q=p; D)*p=5; 7、有以下程序 void fun(char *a,char *b) { a=b; (*a)++; } main () { char c1='A', c2='a', *p1, *p2; p1=&c1; p2=&c2; fun(p1,p2); printf("%c%c\n",c1,c2); }程序运行后的输出结果是 A)Ab B)aa C)Aa D)Bb 8、有以下程序 #include main() { printf("%d\n", NULL); } 程序运行后的输出结果是 A)0 B)1 C)-1 D)NULL没定义,出错 9、已定义以下函数 fun(int *p) { return *p; } 该函数的返回值是 A)不确定的值 B)形参p中存放的值 第八章地址和指针 8.1变量的地址和指针 在程序中变量实际上代表了内存中的某个存储单元。那么C是怎样存取这些单元的数据内容的呢? 我们知道计算机的内存是以字节为单位的一片连续的存储空间,每个内存单元都有一个唯一的编号,我们将其称为“内存地址”。计算机对数据的存取操作都是依赖于内存地址进行的。因为计算机的内存空间是连续的,所以内存中的地址空间也是连续的,并且用二进制数据来表示,为了方便和直观,我们将用十进制数据进行描述。 若在程序中定义了一个变量,C编译系统就会自动根据变量的类型,为其分配一定字节数量的存储空间。如int型2个字节,float型4个字节,double型8个字节,char型1个字节等。此后,这个变量的内存地址也就唯一的确定了。 一般情况下,我们在程序中只要给出变量名,不需要知道每个变量在内存中的具体地址,变量与地址之间的联系由C编译系统来完成。程序中我们对变量进行存取操作,实际上就是对变量地址的存储单元进行操作。这种直接按照变量地址进行存取的操作方式称为“直接存取”方式。 在C语言中我们还可以定义一种特殊的变量,这种变量只是用于存放内存变量地址的。如:p93 图8.2 这种通过变量p间接得到变量a的地址,然后再存取变量a的值的方式称为“间接存取”的方式。这种用来存放地址的变量称为“指针变 量”或“指针”。 由此我们可以知道,在C语言中,地址是指变量在内存中的存放的位置,即存放该变量的内存单元的名字。而指针是指一个变量,在该变量中存放的是其指向的那个变量在内存存储单元的地址。也就是说,变量的地址就可以理解为指针。 在C语言中,指针被广泛使用,他可以使程序简洁并高效运行,但使用不当就会产生意料不到的严重后果。因此,正确使用和掌握指针是十分必要的。 8.2 指针变量的定义和基本类型 定义指针变量的形式: 类型名*指针变量名1,*指针变量名2,……; 例如: int *pi,*pj; float *i,*j,*k; double *l,*m,*n; char *c,*s; 在每个变量前面的星号*是一个指针说明符,用来说明该变量是指针类型。变量前面的星号*不可以省略。指针变量名前面的类型定义是说明指针指向的数据类型。 另外,我们还可以定义一个指向指针的指针变量。定义形式为: 类型名**指针变量名1,**指针变量名2,……; 实现单链表的各种基本运算 一、实验目的 了解单链表表的结构特点及有关概念,掌握单链表的各种基本操作算法思想及其实现。 二、实验内容 编写一个程序,实现顺序表的各种基本运算: 1、初始化单链表; 2、单链表的插入; 3、单链表的输出; 4、求单链表的长度 5、判断单链表是否为空; 6、输出单链表的第i位置的元素; 7、在单链表中查找一个给定元素在表中的位置; 8、单链表的删除; 9、释放单链表 三、算法思想与算法描述简图 主函数main void InitList(LinkList*&L) 初始化单链表L void DestroyList(LinkList*&L)//释放单链表L int ListEmpty(LinkList*L)//判断单链表L是否为空集 int Listlength(LinkList*L)//返回单链表L的元素个数 void DispList(LinkListt*L)//输出单链表L int GetElem(LinkList*L,int i,char e)/*ElemType e)获 取单链表L中的第i个元素*/ int LocateEmpty(LinkList*L,char e)/*ElemType e)在单 链表L中查找元素e*/ int ListInsert(LinkList*&L,int i,char e)/*ElemType e) 在单链表中第i个位置上插入元素e*/ int ListDelete(LinkList*&L,int i,char &e)/*ElemType e)在单链表L中删除第i个元素*/ 四、实验步骤与算法实现 #include 内存管理指针的基本概念指针应用实例指针作函数参数第8章指针(1) 复习回顾 上次课的内容: ◆局部变量和全局变量 ◆变量的作用域 ◆变量的生存期 ◆声明与定义 ◆内部函数 ◆外部函数◆你开始习惯写函数了吗? 2012是如何实现的?假定造成世界末日的上帝是一个程序员,作为一名合格的程序员,他绝不应该写出类似于“摧毁地球”这样的程序,而应该写一个“摧毁(行星)”的函数,然后把地球作为参数传进去! C语言新手的晋级之路 第一步:萧规曹随 ◆在这一步要求按照教材或讲义上的程序实例进行原样 输入,运行一下程序看是否正确。 ◆在这一步,掌握C语言编程软件的使用方法(包括新 建、打开、熟练输入、编辑、保存、关闭C程序); 初步记忆新学章节的知识点;养成良好的编程风格( 是讲义提倡的而不是教材上的) ◆难点:小心数字1和字母l,字母o和数字0,中英文标 点符号的区别 C语言新手的晋级之路 第二步:移花接木 ◆在第一步输入的C程序的基础上进行试验性的修改, 运行一下程序看一看结果发生了什么变化,分析结果变化的原因,加深新学知识点的理解。 ◆可与第一步同步进行,“输入”可加深记忆,“修改 ”可加深理解,二者相辅相成,互相促进。 ◆友提,一次进行一处修改即可,免得把自己改晕了。 C语言新手的晋级之路 第三步:无中生有 ◆面对教材的例子题目,不参考教材,自己从头开始编 写程序。看能否写出正确运行的代码。 ◆初学者易犯的错误:scanf格式控制和输入不匹配或把变量 名当地址作参数,使用未定义的变量、漏掉或多写“;”、“{” 与“}”、“(”与“)”不匹配,控制语句(选择、分支、循环)的格式不正确,调用库函数没有包含相应头文件,调用未声明 的函数、调用函数时实参和形参不匹配、数组边界越界等等 ◆要学会看编程工具的错误信息提示:双击错误提示光标可 跳转到发生错误的行,如果该行没有错误就往前查找。错误要一 个一个修改,每改完一次编译一下程序。 指针思考题 一、填空题 【1】下面函数要求用来求出两个整数之和,并通过形参传回两数相加之和值,请填空。 int add( int x, int y, ) { =x+y;} 【2】若有定义: char ch; (1) 使指针p 可以指向变量ch的定义语句是。 (2) 使指针p指向变量ch的赋值语句是。 (3) 通过指针p给变量ch读入字符的scanf函数调用语句是。 (4) 通过指针p 给变量ch赋字符A的语句是。 (5) 通过指针p输出ch中字符的语句是。 (6) 在16位微机上,指针变量p在内存中所占字节数是,变量ch在内在所占字 节数是。 二、选择题 【3】若有说明:int i,j=7,*p=&i;则与i=j;等价的语句是()。 A.i=*p; B.*p=*&j; C.i=&j; D.i=**p; 【4】若有定义:int x,*pb;则正确的赋值表达式是()。 A.pb=&x B.pb=x C. *pb=&x D.*pb=*x 【5】对于类型相同的指针变量,不能进行的运算是()。 A.< B. = C. + D. – 【6】以下程序的输出结果是()。 A.23 B. 24 C. 25 D. 26 Void fun ( int *x) { printf(%d\n”,++*x); } main( ) { int a=25; fun (&a); } 【7】以下程序的输出结果是()。 A.6 B. 7 C. 8 D. 9 main() { int k=2,m=4,n=6; int *pk=&k,*pm=&m,*p; *(p=&n)=*pk*(*pm); printf("%d\n",n); } 【8】以下程序的输出结果是()。 A.100 B. 50 C. 101 D.200 main() { int *v,b; v=&b; b=100; 指针 一、指针概述 1. 地址 C++程序中每一个实体,如变量、数组和函数等,都要在内存中占有一个可标识的存储区域。每一个存储区域由若干个字节组成,在内存中,每一个字节都有一个“地址”,一个存储区的“地址”指的是该存储区中第一个字节的地址。 2.指针 指针就是存储区域的地址。一个地址指向一个程序实体的存储空间。 直接访问:通过变量名或地址访问程序中一个实体的存储空间的方式(其实通过变量名访问也就是通过地址访问)。 间接访问:把一个变量的地址放在另一个变量中。 3.指针变量 专门用来存放地址的变量就叫指针变量,需要专门加以定义。 二、指针的类型与指针的定义 指针也是具有类型的。指针的类型就是它所指向的变量的类型。例如,一个指向int型的指针,一个指向一维数组的指针。 在使用一个指针变量之前,先要用声明语句对其进行定义。例如:int *p; 定义了一个指向整型数据的指针变量p。即p是一个存放整型变量地址的变量。 应当特别注意的是,定义一个指针变量必须用符号“*”,它表示其后的变量为指针变量,指针变量为p,而不是*p。 要想使一个指针变量指向一个变量,必须将变量的地址赋给指针变量。例如:C++程序设计 第八章 指针和引用
单链表代码
第8章指针1练习答案
C语言第八章地址与指针
第八章 二级c语言
如何透彻理解C语言中指针的概念
计算机二级c语言第八章 指针习题
第八章地址和指针
实现单链表的各种基本运算
第8章 善于利用指针(1)
第8章-指针练习题
指针1