《C/C程序设计》第06章(复合数据类型).ppt

上传人:小飞机 文档编号:5896117 上传时间:2023-08-31 格式:PPT 页数:63 大小:228KB
返回 下载 相关 举报
《C/C程序设计》第06章(复合数据类型).ppt_第1页
第1页 / 共63页
《C/C程序设计》第06章(复合数据类型).ppt_第2页
第2页 / 共63页
《C/C程序设计》第06章(复合数据类型).ppt_第3页
第3页 / 共63页
《C/C程序设计》第06章(复合数据类型).ppt_第4页
第4页 / 共63页
《C/C程序设计》第06章(复合数据类型).ppt_第5页
第5页 / 共63页
点击查看更多>>
资源描述

《《C/C程序设计》第06章(复合数据类型).ppt》由会员分享,可在线阅读,更多相关《《C/C程序设计》第06章(复合数据类型).ppt(63页珍藏版)》请在三一办公上搜索。

1、第六章 复合数据类型,6.1 指针类型概念:旅馆房间、房间编号、房间名称、派房牌(上写房间号)。1)地址 给内存单元(一般是字节)的编号。计算机根据它找到对应的字节进行访问(存取)。高级语言中定义一个变量,编译时根据其类型分配相应数目的字节(如int 型分2个字节,float 分4个字节),将变量名与对应内存字节映射。变量名 地址 内存单元 2)指针 给变量、数组、结构体、函数等分配的内存单元或块区的首地址。假如有:long m=56000 则:&m 就是 m的指针或者说是 m所占内存单元的首地址。此例中,56000就放在从这个地址开始的连续四个字节中。3)指针变量 定义一种特殊变量,这种变量

2、专门存放指针,用它也可找到(指向)变量、数组、结构体、函数,这样的变量 称作指针变量。按变量是直接寻址;按指针变量是间接寻址。由于变量、数组、结构体、函数等所分配的内存单元或块区的大小及结构不同,指针变量因而也要定义成相应的类型,不能混用。,例 交换两数。void swap();main()int a,b;scanf(%d%d”,2000H,2001H,2EA0H,2EA1H,a=10,b=8,内存,地址,变量,10,8,指针变量,p2=&b=2EA0H,:,:,:,3100H,3101H,3802H,3803H,2000H,2EA0H,p1=&a=2000H,变量的指针变量 1)指针变量的定

3、义*;例 int*p1,*p2;2)指针变量的赋值 指针变量=,其中:*号是取值运算符。*与 定义时的*与使用时的*含义不同,前者表示定义的是指针变量;后者是对变量的取值运算。定义了一个某类型的指针变量后,它可以指向任意一个同类型变量。4)指针变量作函数参数 主调函数 被调函数 实参 形参&a p p p,6.2 数组类型数组的特点:(1)数组中的每一个元素均属于同一类型,我们称这种类型为数组的基类型;(2)每个数组中的元素个数一经确定后就保持不变,我们称它为数组的长度;(3)数组中的每个元素均为变量,我们用数组下标来直接访问数组的元素;(4)数组中的元素还允许是数组类型,从而产生二维数组、多

4、维数组等结构;(5)在数组定义中,常量表达式的值虽然指出了数组元素的个数,但C编译器不做越界检查;(6)数组名表示数组所用空间的首地址,也就是数组第0个元素的地址。是一个常量地址。一、一维数组的声明 格式:类型 数组名常量表达式;二、一维数组的引用与初始化,引用形式:数组名下标初始化形式:存储类别 数据类型 数组名数组长度=初始化值;例:static int a5=10,20,30,40,50;一般要求:只有定义为静态或外部存储的才能初始化。三、数组作为函数的参数(传递地址)例:对一字符串反序输出。(exinver.c)四、二维数组的声明形式:类型 数组名常量表达式常量表达式;如:int sc

5、ores503;说明:编译程序为二维数组分配存储空间时是按行进行的,即先按顺序存放第一行的所有数据,然后接着按顺序存放第二行的所有数据,如此类推。二维数组scores的存储空间分配如下图所示:,.25000 scores00 25002 scores01 25004 scores02 25006 scores10 25008 scores11 25010 scores12.25298 scores492.,五、二维数组元素的引用与初始化引用形式:数组名行下标列下标/下标为整数类型的表达式如:scores201=100;初始化形式:存储类别 数据类型 数组名常量1常量2=初值;如:static

6、int s34=50,60,80,20,40,90,70,100,10;例 矩阵行列互换。Exmatrix.c 1 2 3 4 1 5 9 5 6 7 8 2 6 10 9 10 11 12 3 7 11 4 8 12 六、指针与数组在语言中,指针与数组之间的关系是十分密切的。指针类型变量可以当作数组使用,数组类型变量也可以当作指针使用,即在语,言中,我们可以象访问指针一样访问数组,也可以象访问数组一样访问指针。其区别为:数组名不能自加、自减,但指针变量可以。例如:int a10,*p;p=a;p+或p-都是成立的,而a+或a-是不成立的。而*(a+I)、aI、*(p+I)、pI是等价的。七、

7、指针数组与数组指针指针数组:指基类型为指针类型的数组,即该数组的每个元素均为一个指针。如果我们需要保留许多指针的值,也就是要保存多个变量的地址,就可以使用指针数组。定义形式:数据类型*数组名数组长度;如:int*p10;/在此声明了一个包含10个整数类型指针变量的数组p。这里*并不是数组名字的组成部分,它只是告诉编译程序p是一个整数类型的指针数组,而不是简单的整数类型数组。,例:建立如下距阵并输出 1 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1程序为:main()int a55=0,*p5,i,j;for(i=0;i5;i+)pi=,数组指针

8、:,定义形式:数据类型(*指针变量名)长度;如:int(*array_ptr)10;/申明了一个指针类型的变量array_ptr,它指向一个长度为10 的整数数组。数组指针可以看成是二维的,此时与二维数组在存储上相同,但变量名是指针变量,可以进行指针运算。引用方式:若有:int(*p)4,a34;p=a;引用:*(*(p+I)+j)aIj例:exarrp.c,6.3字符串,一、字符串常量与变量:字符串变量是一个基类型为字符类型的数组变量,同样遵循“先声明、后使用”的原则,我们在声明字符串变量时,可用字符串常量作初始化。如:char name10=“limeixue”;初始化方式有三种。也可以定

9、义指针变量指向字符串。如:char*name=“limeixue”;二、字符串数组定义:char*name12;例:按姓名查询。Exsearch.c,三、字符串库函数(string.h)1.char*strcat(char*str1,const char*str2);作用:将字符串str2连接到字符串str1后,形成一个新字符串,原先str1的结束标记0被取消。函数返回值为str1。注意为字符串变量str1分配的存储空间一定要足够大,能够容纳两个字符串连接后的新字符串。如:char s1=“good”,s2=“evening!”;strcat(s1,s2);2.char*strchr(cons

10、t char*str,int ch);作用:寻找字符串str中第一次出现字符ch的位置。如果找到ch,则返回指向该位置的指针;否则返回空指针。3.int strcmp(const char*str1,const char*str2);作用:比较字符串str1和str2的内容是否相同。如果str1小于str2则返回负数;如果str1等于str2则返回零;如果str1大于str2则返回正数。4.char*strcpy(char*str1,const char*str2);作用:将str2指向的字符串复制到str1指向的位置中并返回str1。注意为str1分配的存储空间必须能放得下str2指向的字符

11、串。注:char*str;strcpy(str,“Be careful”);引起的问题。,5.unsigned int strlen(const char*str);作用:返回字符串str中的字符个数,包括其中的空格与转义字符,但不包括字符串结束标记0。6.char*strstr(const*str1,const char*str2);作用:寻找字符串str2在字符串str1中第一次出现的位置,不包括str2的结束标记0。如果找到str2,则返回指向该位置的指针;否则返回空指针。四、字符串应用例1:按姓名排序。(exnsort.c)冒泡法排序(从小到大):n个数参与排序,每趟找出最大数存与最后

12、,共n-1趟。每一趟中对相邻的两个元素进行比较,不符合次序的立即交换。例2:打印出全班每个学生姓名的长度。Exlen.c,6.4 结构体类型一、概述,记录型数据与结构体 一组相关的不同数据类型的数据项,可作一个整体来处理。PASCAL中称“记录型”数据,C中称结构体类型数据。与数组有明显不同,数组要求其所有成员的类型、长短一样结构体类型和结构体变量。,struct student int num;char name20;char sex;struct date birthday;float score;stu1,stu2;,struct date int month;int day;int y

13、ear;,什么情形时适用结构体或数组?,二、定义结构体的类型和变量,定义结构体类型 一般形式:例 参见上页,struct 结构体类型名 分量1;分量2;分量3;:分量:分量又称域或成员。当分量是结构体时,形成定义时的嵌套。,定义结构体类型的变量,定义结构体变量三种形式:,1.定义结构体的同时定义 例如前页例。2.先定义结构体,后定义结构体变量 例:struct stu.;.struct stu st1,st2;3.直接定义 例:struct.变量名表;在struct 后不出现结构体类型名,三、结构体变量的引用,结构体类型不是存储数据的实体,即系统并不是给它分配内存,它仅是一种数据类型,与int

14、,char 类似,用来定义一种数据类型的变量;结构体类型变量才是存储数据的实体,结构体变量的分量具体分配存储单元,等价于一组变量。因此我们引用的是结构体变量。引用结构体变量只能通过引用结构体变量的分量(成员)实现(在I/O时,赋值时等)。用“.”或“-”引用。例如:sum=st1.score+st2.score;成员运算符(多级)例如:age=1999-st1.birthday.year;_QC允许将一结构体变量的所有分量赋予同类的另一变量。例如:st2=st1;例 ex2stu1.c,四、结构体数组,以某结构体类型也可以定义数组例 按姓名查询。ex2stuarr.c,struct stude

15、nt int num;char name30;char sex;float score;stu30;每个下标变量stui 都有结构体类型student 的各个分量;下标变量的引用同变量。,五、结构体类型的指针,指向结构体类型变量的指针,指向结构体类变量的指针就是该变量所占用的内存区段的首址。例 struct student int num;char name3;char sex;float score;st1,st2,st3;struct student*p=,num,name,sex,score,:,:,2A00H,st1,p,指向结构体类型数组的指针,指向结构体类数组的指针就是该数组所占用

16、的内存区段的首址。例 struct student int num;char name3;char sex;float score;st30=;struct student*p=st;for(p=st;pnum,p-name,p-sex,p-score);,:,:,2A00H,st0,st1,st2,st3,:,2A0AH,2A14H,2AE0H,p,例:若干个学生的信息包括:学号、姓名、三门可课的成绩(c语言、电子技术、控制理论)、总分,要求打印一份名次表。分析:总分是需要计算的。按总分从小到大排序(bubble)。按行输出。Ex2table.c,指向结构体类型数据的指针一、指向结构体类型变

17、量的指针例 打印通讯录。(excommu.c)二、指向结构体数组的指针例用结构指针建立一个图书检索系统。按书名检索。(exsearch.c)三、结构指针的使用例链表。链表的建立、遍历、查找、插入、删除操作。,链表,什么是链表?,线性表:有限个元素的有序集合。可用数组或链表表示。数组和链表两 者都逻辑连续,但后者可以在空间不连续。动态数据结构:其大小可变;动态分配存储空间。链表是最简单的一种,属于线性动态数据结构,树是非线性动态数据结构。链表:链表中的一个元素称为一个结点或节点。每个结点由两部分组成:数据部分、指向上下结点的指针。靠这样的指针把各个结点串联起来构成链表。分单向、双向链表,后者可以

18、两方向连接。,0,0,单向链表,双向链表,0,数据部分,链表,为什么使用链表?,1)不需要连续存储空间,可利用内存碎片;2)插入删除元素不需移动其它元素,处理速度快;3)动态分配存储空间,不必以最大可能长度预定存储空间,且可以随意扩充表的容量。动态分配存储空间(使用函数)void*malloc(unsigned size)函数(memory allocation):在内存的动态存储区中分配一个长度为size的连续空间,size为结点元素各成员项的总字节数,可以用sizeof(数据类型名)运算符获得。该函数的返回值是一个指针,它的值是所分配存储区的起始地址,当该函数未成功执行时,返回值为0。如:

19、struct student int num;float score;struct student*next;*p1;p1=(struct student*)malloc(sizeof(struct student);,void free(ptr)函数:该函数释放由ptr指向的内存区。Ptr是最近一次调用calloc或malloc函数时返回的值。用结构体及结构体指针构造链表和链表操作(1)建立链表。链表的建立过程可以描述如下:假设结构体定义如下:struct node int num;float s;struct node*next;1.为了建立链表,在程序中需要使用两个指向结构的指针。例如:

20、struct node*p1,*p2;建立链表时,首先使用malloc函数为第一个元素分配存储 空间,并把该空间的地址赋予p1,使p1指向该存储空间:p1=(struct node*)malloc(sizeof(struct node);,2.把p1的值赋予p2,从而使p2也指向该存储空间,便于连接 后面的结点元素。3.通过p1访问成员num和s,并对其赋值:p1-num=1;scanf(“%f”,使指针p2指向第二个(始终指向最 后一个)元素。反复执行上面的四个语句,就可以不断地把 元素加入到链表中去。这种建立链表的方法是从表头插入的 过程,指针p2总是指向最后出现的那个元素。,链表建立函数

21、:#define NULL 0/*定义空指针,作为表尾结点的next域*/struct node/*结点元素的数据结构类型*/int num;struct node*next;int n=0;/*定义外部变量n,用来记录结点的个数*/struct node*creat()/*函数的返回值为指向头结点的指针*/struct node*p1,*p2,*head;p2=NULL;/*最先加入的为表尾结点,将其next域置为NULL*/printf(nplease input num:n);do p1=(struct node*)malloc(sizeof(struct node);/*申请一个结点空

22、间*/,scanf(%d,/*返回链表头指针*/,(2)链表的遍历(输出)函数如下:void print(head)struct node*head;struct node*p;printf(n The table is:n);p=head;/*以表尾结点中指针为NULL做为遍历结束的标志*/while(p!=NULL)printf(%4d-%7.2f,p-num,p-s);p=p-next;/*移向下一个结点*/(link_t.c),链表,插入结点删除结点,0,单向链表,2100h,2100h,2180h,2010h,2050h,2050h,2a02h,2a02h,2100h,2180h,0

23、,单向链表,2100h,2050h,2a02h,2010h,2050h,2100h,2a02h,2a02h,指针在函数中的应用一、指针作为函数的参数用指针作为函数的参数,应该在主调函数和被调用函数分别定义指针变量;在函数调用中实参指针和形参指针类型应一致。例分析结果。(expoint.c)#include stdio.h”sub(int*s,int y)static int t=3;y=st;st=st+4;t-;main()int a=1,2,3,4,i,x=0;printf(x ain);for(i=3;i=0;i-)sub(a,x);printf(%d%dn,x,ai);,X ai0 8

24、0 70 60 5,二、函数的指针及函数的指针变量 概念 函数的指针就是函数代码在内存中所占存储区的首地址。函数的指针变量(指向函数的指针变量)存放函数的指针,用来指向某函数。p+,p+n 无意义。可以在不同时间用同一个指针变量调用不同函数。指向函数的指针变量的定义 类型标示符(*变量名)();例如:float(*p)();表示 p是一个指向返回值为float 型的函数的指针变量。运用 例求n!。赋值形式:=;调用形式:(*指向函数的指针变量)(实参表);(expfun.c),#include stdio.hint add(n)int n;int sum=1,i;for(i=1;i=n;i+)

25、sum=sum*i;return(sum);main()int n,m,(*p)();printf(input n:n);scanf(%d,赋值,调用,用指向函数的指针变量作函数的参数 在C语言中可以把指向函数的指针变量作为参数传递到其他函数。例如在有些程序中,用户可以从各种可供选择的选择项中选用他所需的操作,而各选项又是由一个独立的函数来实现的,在程序实现中就可以采用函数指针作参数的方式完成。,例 编写一个简单的帐单系统,包括:录入、删除、显示 帐目、退出功能,各功能项所对应的实现函数分别为 enter()、delete()、review()、quit()。,#include stdio.h

26、”int enter(),delete(),review(),quit();main()int i;int(*p)();i=menu();switch(i)case 1:p=enter;break;case 2:p=delete;break;case 3:p=review;break;case 4:p=quit;break;process(p);,menu()char ch;do printf(1.entern);printf(2.Deleten);printf(3.Reviewn);printf(4.Quitn);printf(Select a number:);ch=getche();pr

27、intf(n);while(!strchr(1234,ch);return(ch-48);,process(int(*f)()(*f)();enter()printf(In enter!n);delete()printf(In deleten);review()printf(In review!n);quit()printf(In quit!n);,返回指针值的函数定义 类型标示符*函数名(参数表);例如:char*person(char name,char sex);函数 person()返回的指针指向 char 型量。例 编写一个strchr()函数,它的作用是在一个字符串中找一个 指定的

28、字符,返回该字符的地址。#include stdio.hchar*strch(char*str,char ch)while(*str!=ch)str+;/*查找指定字符的位置*/return(str);/*返回找到字符的地址*/,main()char*strchr();char*pt,ch,line=I love china.;printf(please input char:n);scanf(%c,/*输出找到字符的相对于首地址的偏移位置*/,指针数组和二级指针概念:数组的元素是指针变量。定义:类型标示符*数组名 数组长度;例如:char*p20;定义了p0-p19 计20个带下标的指针变量

29、,都指向char 型量。适合于处理字串。,指针数组 name,name0,name1,name2,name3,“Turbo C”,“MS C”,“Quick C”,:,“ANSI C”,字符串,二级指针 二次间接。定义:*;例如:int*p;引用方式为:*例1 main()static char*name=“Turbo C”,“ANSI C”,“MS C”,“Visual C”,.);char*p=name;int i;for(i=0;i10;i+)printf(“%sn”,*p+);/*?*p*/,例2#include stdio.h”main()int*k,*j,i=100;j=结果:10

30、0,main函数中的参数main函数也可以有参数,它可以带两个参数。其一般形式为:main(argc,argv)int argc;char*argv;其中第一个形参argc是一个整型变量,第二个形参argv是一个指针数组,其元素指向字符型数据。这两个参数的值从那里传递而来呢?main()函数是主函数,它不能被程序中其它函数调用,因此显然不可能从其它函数向它传递所需的参数值,只能从程序以外传递而来。main函数的参数传递是在命令行中,除了给出应执行的文件名外,再给出一个或多个字符串,作为传递该main函数的参数值。例如,从键盘输入以下命令行:file computer enginish,main

31、函数的参数传递规律与其它函数有所不同,并不是将file(文件名)传递给argc,将后面的computer和enginish传递给argv。而是将命令行中总的字符串的个数(包括文件名)传递给参数argc,上面的命令行中有三个字符串,即传递给argc的值为3;将命令行中第一个字符串(如file)的地址传递给指针数组argv中第0个元素argv0,第二个字符串的地址传给argv1,依次类推。例1有如下main函数(其所在文件的源文件名为file1.c):#include stdio.h”main(int argc,char*argv)int i=1;while(argc1)printf(%sn,ar

32、gvi);-argc;i+;(file1.c),如果从键盘输入的命令行为:file1 This is a example.则输出为:(argc=5 argv0)This file1isaexample.,例2编写一个ren(换名)程序。#include dir.h”#include string.h”int main(int argc,char*argv)char oldnameMAXPATH,newnameMAXPATH;if(argc2)strcpy(oldname,argv1);strcpy(newname,argv2);else printf(use:jc12 oldname newn

33、amen);exit(1);if(rename(oldname,newname)=0)puts(successfuln);exit(0);else printf(nerrorn);exit(2);return(0);exren.c,定义在dir.h中,系统函数,指向结构体类型数据的指针一、指向结构体类型变量的指针例 打印通讯录。(excommu.c)二、指向结构体数组的指针例用结构指针建立一个图书检索系统。按书名检索。(exsearch.c)三、结构指针的使用例链表。链表的建立、遍历、查找、插入、删除操作。,枚举类型,Made by lut,共用体类型,位域,类型别名,共用体(联合)类型,什么

34、是共用体,结构型数据类型;存储形态:共用体类型变量的若干分量分时共占同一存储空间。例如:union data int i;char c;long l;com;com.i=10;com.c=A;com.l=65535;,0000 0000 0000 0000 1111 1111 1111 1111,0100 0001,共用体类型,共用体类型及其变量的定义和引用,共用体类型及其变量的定义和引用与结构体类似,本质的不同在于使用内存的方式。类型定义:union 类型名 数据类型 变量名;数据类型 变量名;联合变量名表;(或;结束)变量的定义:三种方式(同结构提变量的定义方式)共用体变量的引用方式:(.

35、或-)如前所示:com.I、com.c、com.l,例1 main()union unsigned char c;unsigned int I4;z;z.I0=65;z.I1=66;printf(“%cn”,z.c);结果:A,例2 main()union int I2;long k;char c4;r,*s=结果:9,57 0 56 0,0 1 2 3,9,8,S-I0,S-I1,S-c0,枚举类型什么是枚举类型,枚举是一组命名的整数常量,用以说明可能类型变量的所有合法值。定义类型形式:enum 名字枚举列表 变量表;定义变量形式(三种方式)枚举类型的变量仅有几个确定的值。例如:enum w

36、eekday sun,mon,tue,wed,thu,fri,satworkday;枚举元素是常量,具有数值。按顺序默认为0,1,2,.;也可以在定义时按需求指定。如:enum colorred,green,blue=8,blank,white;,应用举例例1main()enum language basic=3,assembly,ada=100,cobel,fortran97;enum language speak;speak=fortran97;printf(“%dn”,speak);结果:102,例2main()enum teammy,your=4,his,her=his+10;prin

37、tf(“%d%d%d%dn”,my,your,his,her);结果:0 4 5 15,类型别名,为提高程序的可读性,我们可用保留字typedef为类型起一个新名字,这个新名字应该用一个有意义的标识符来命名。typedef 不建立新的类型,它只是为原有类型起一个新的名字而已。如:typedef char*STRING;就可以用STRING代替char*,即 STRING P;定义了一个指向字符的指针变量p。例1:typedef union long I;int k5;char c;DATE;/10 struct date/2+10+8=20 int cat;DATE cow;double do

38、g;too;,main()DATE max;printf(%dn”,sizeof(struct date)+sizeof(max);结果:30例2typedef union long x2;int y4;char z8;MYTYPE;MYTYPE them;main()printf(%dn”,sizeof(them);结果:8,位域,所谓的位域是以位为单位定义长度的结构体类型中的成员。位域类型及变量的定义形式:struct 位域类型名 类型 位域名1:长(二进制位数);类型 位域名2:长(二进制位数);变量表;注:一个位域可以定义成int,unsigned或signed。长度为1的位域必须定义

39、为unsigned,因为单个位不可能有符号。,位域的引用:struct packed_data unsigned a:2;unsigned b:6;unsigned c:4;unsigned d:4;int i;data;,a b c d i,2 6 4 4 16,例1:下列定义中的错误。Struct twobyte unsigned I:3;unsigned j:4;unsigned:0;float k:4;unsigned:2 unsigned m:18;bit;,例2:main()struct pp unsigned i:3;unsigned j:4;unsigned k:4;unsigned:0;/下面将从下一字节开始分配 unsigned:3;unsigned m:6;union uu/长度为4个字节 struct pp bb;long int l;u;u.l=0 x12345678;,printf(%u,%u,%u,%u,%dn,u.bb.i,u.bb.j,u.bb.k,u.bb.m,sizeof(struct pp);结果:0,15,12,6,4,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号