C语言课件第11章结构体与共用体.ppt

上传人:max****ui 文档编号:6335118 上传时间:2020-02-23 格式:PPT 页数:54 大小:206KB
返回 下载 相关 举报
C语言课件第11章结构体与共用体.ppt_第1页
第1页 / 共54页
C语言课件第11章结构体与共用体.ppt_第2页
第2页 / 共54页
C语言课件第11章结构体与共用体.ppt_第3页
第3页 / 共54页
点击查看更多>>
资源描述
第11章结构体与共用体 1 结构体类型的定义2 结构体变量的定义及引用3 结构体数组4 结构体类型的指针5 链表的基本操作6 共用体和枚举类型 了解 结构体类型的引入 问题 为了描述一个事物的不同属性 需要用到各种不同类型的数据 这些数据彼此相关 形成一个有机的整体 例如 一个教师的基本信息由姓名 性别 年龄 职称 工资等几项组合而成 如何描述一个教师的情况呢 前面我们已学习过各种基本类型的变量和数组 而且我们知道 各个变量之间是相互独立的 无任何联系 而数组只能用来表示一批相同类型的数据 因此 若用单个变量分别表示教师的姓名 性别 年龄等属性 则难以反映他们之间的内在联系 若用数组 则根本无法表示 因为姓名 性别 年龄等不属同一种数据类型 C语言中用 结构体 来描述由多个不同类型的数据组成的数据集合 相当于其他高级语言中的 记录 11 1结构体类型的定义 与基本数据类型不同的是 结构体是又一种构造类型 是由多个类型的数据成员组合而来的 因此该类型的具体内容应根据需要先定义 后使用 可以定义如下结构体类型来描述教师的基本情况 structteacher struct是关键字 charname 30 内是该类型的各成员 charsex intage charposition 10 floatsalary 语句末尾是 该结构体类型名为structteacher teacher是该结构体的标识符 该类型包含有6个成员的数据项 name sex age position和salary 其中每个成员项都有自己的类型 可见 定义一种新的结构体类型的一般形式是 struct结构体类型名 成员类型成员名 成员类型成员名 其中 struct是关键字 结构体类型名 结构体成员名的命名规则同变量的命名规则一样 特别提示 structteacher只是一种具体的结构体类型 根据需要 程序员可以定义多个不同内容的结构体类型 其中的成员项是该类型的组成部分 而不是变量 结构体类型的成员可以是基本类型的变量或数组 也可以是结构体类型的数据 即结构体类型的嵌套定义 例如 若将教师的年龄改为出生日期 则可以将出生日期定义为一个结构体类型 然后嵌入structteacher中 将出生日期单独定义为一个结构体类型后再嵌入 Structdate type intyear intmonth intday Structteacher 2 charname 30 charsex structdate typebirthday charposition 10 floatsalary 常用 直接嵌入 Structteacher 3 charname 30 charsex structdate type intyear intmonth intday birthday charposition 10 floatsalary 成员birthday又是一个结构体类型的数据 11 2结构体变量的定义及引用 经以上定义后 结构体类型structteacher与系统定义的类型int long float等一样 可以用它来定义该类型的变量 数组 函数等 不同的是 结构体类型的作用范围是有限制的 在函数体内定义的结构体类型的作用域为本函数内 在函数体外定义的结构体类型的作用域为本程序文件内 若要引用不在本文件内的结构体类型 通常用 include命令将定义该类型的文件包含进来 例11 1定义一个结构体变量 用于存放一个教师的信息 然后将其输出 include stdio h main structteacher 该类型的作用范围在本函数内 charname 30 charsex intage charposition 10 floatsalary structteacherperson 定义结构体变量person strcpy person name wangli person sex f 给各成员赋值 person age 30 strcpy person position middle person salary 1600 printf nnamesexagepositionsalary printf n 10s 3c 5d 10s 8 2f person name person sex person age person position person salary 分析 本例中结构体类型在函数体内定义 其作用范围在本函数体内 先定义结构体类型 后定义结构体变量 对结构体变量输入输出操作 或将基本类型的数据赋给结构体变量时 需分别访问各个基本类型的成员 不能整体赋值或输入输出 如 printf s c d s f person 错 person lili f 24 primary 1000 错 例11 2定义一个结构体类型 包含通讯录中的如下信息 姓名 年龄 电话 通讯地址 并定义该类型的变量 输入数据并输出 程序l11 2 c include stdio h structaddress list 在函数体外定义结构体类型 charname 10 该类型的作用域为本程序内 intage chartel 10 charaddress 40 main structaddress lists 定义变量s 占空间62个字节 printf ninputname gets s name printf inputage scanf d 分析 结构体类型address list放在函数体外定义 其作用范围为本程序文件内 结构体变量的输入输出需逐个访问基本类型的成员 引用方法与同类型的变量 数组相同 例11 3定义一结构体类型 包含工人的工资信息 编号 姓名 工资 并定义变量存放两人的数据 然后交换 输出交换前后的信息 程序l11 3 c include stdio h main structsalary list charno 10 charname 30 floatsalary structsalary listz x 10 liming 2000 y 12 wangyan 2500 结构体变量的初始化 给出各成员的数据并用 括起来 各成员之间用逗号分开 printf nnonamesalary printf nx 5s 6s 10 2f x no x name x salary printf ny 5s 6s 10 2f y no y name y salary z x x y y z 交换两个结构体变量 printf nafterexchange printf nx 5s 6s 10 2f x no x name x salary printf ny 5s 6s 10 2f y no y name y salary 特别提示 同类型的结构体变量可以整体赋值 即可以将一个结构体变量整体赋给相同类型的另一个结构体变量 说明一 定义结构体变量 定义结构体变量的方法有三种 经常用第一种 方法一 先定义结构体类型 再定义结构体变量 如 structteachert1 t2 例11 1 方法二 定义结构体类型的同时定义结构体变量 例11 2 又如 structcoursemath longno 4Bcharname 30 math english 30B若以后还需用到此结构体类型 定义方法同1 structcoursechemic 方法三 格式同方法 二 其中类型名course省略 缺点是该类型无法再次引用 结构体变量的存储 系统按结构体类型中各成员的类型给变量分配存储空间 如上图 noname 说明二 结构体变量的引用 结构体变量定义后 可以分两个层次引用 访问结构体变量的成员 引用整个结构体变量 1 使用成员运算符 引用结构体变量的成员 的优先级仅次于括号 如例11 1 11 2 11 3中的person name person agex no s salary等成员的赋值 输入 输出 person age 等价于 person age 对结构体变量中的成员的操作与基本类型的变量完全相同 注意 当结构体类型嵌套定义时 应逐级访问 如structteacher 2pp pp birthday year 1999 2 相同类型的结构体变量之间可以整体赋值 如例11 3中交换两个结构体变量的值 11 2结构体数组 结构体数组用于保存一批同类型的结构体数据 每个数组元素相当于一个结构体变量 例 11 4输入三门课的信息 课程编号 课程名 并输出 分析 每门课的信息包含2项 用结构体类型表示 其成员有两项 即课程编号和课程名 三门课的信息 用一维数组保存 输入 可以赋初值 也可由用户输入 本例中采用赋初值的方式 程序l11 2 1 c说明 结构体数组的初始化同基本类型的一维数组 只不过每个数组元素是用 括起的一个结构体常量 数组元素中每个成员的访问 同变量的成员的访问 例11 5输入N个学生的学号 姓名 三门课的成绩 计算每人的平均成绩 并按平均成绩由高到低排序 输出排序后的成绩表 分析 每个学生的信息包括多项 用结构体类型表示 其成员有学号 姓名 三门课的成绩 平均成绩 N个学生的信息用一维数组保存 算法 输入并计算平均成绩 排序 输出三步 可将后面两项功能分别用函数实现 在主函数中调用 设排序函数为sort 输出函数为output 分析每个函数的具体组成 函数类型参数函数体程序l11 2 2 c 例11 5程序 structstu charno 8 charname 10 floatscore 3 floataver include stdio h include stdlib h defineN3 defineSTU SCstructstu main voidsort STU SCsc1 output STU SCsc2 STU SCsc list N inti j chartemp 10 floatsum printf ninputno name score 1 3 for i 0 i N i printf nstudent d n i 1 sum 0 printf no gets sc list i no printf name gets sc list i name for j 0 j 3 j printf score d j 1 gets temp sc list i score j atof temp sum sc list i score j sc list i aver sum 3 sort sc list output sc list voidsort STU SCsc1 inti j k STU SCt for i 0 isc1 k aver k j if k i t sc1 k sc1 k sc1 i sc1 i t voidoutput STU SCsc2 inti printf nnonamescore1score2score3aver for i 0 i N i printf n 8s 10s sc2 i no sc2 i name printf 8 2f 8 2f 8 2f 8 2f sc2 i score 0 sc2 i score 1 sc2 i score 2 sc2 i aver 通过本例说明 1 结构体数组中的每一个数组元素相当于一个同类型的结构体变量 2 对数组元素的输入输出及运算均需对元素的基本类型的成员进行 只有同类型的数组元素才可以作为整体相互赋值 3 结构体数据的成员通常类型各不相同 输入各成员数据时应注意 4 关于成员数据的输入技巧 为了正确读入任意字符串 通常用gets 输入字符串 而不用scanf 为了避免多余的回车符影响数据的正常输入 整型 实型的数据也用gets 但作字符串读入 然后再用相应的函数转换成所需类型 如 chart 20 gets t sc list i score j atof t 同理 atoi t 则转换成整型 但输入单个字符时 通常用 ch getchar getchar 5 本例中 用结构体数组名作函数参数 传递的是数组的首地址 实现主 被调函数共用同一个结构体数组 11 3指向结构体类型的指针 结构体变量在内存中占据一内存段 该内存段的首地址就是该结构体变量的指针 通过指向结构体类型数据的指针变量可以间接的访问结构体变量 也可以使用指向结构体数据的指针变量访问结构体数组中的元素 例11 3 1定义一结构体类型 表示复数 定义该类型的变量和指针变量 用指针变量访问结构体变量 分析 复数由实部和虚部组成 因此该结构体类型有两个成员 real image L11 3 1程序 main structcomplex 表示复数的结构体类型 floatreal floatimage structcomplexx 2 3 p p 通过p访问x 运行结果 2 3i2 3i 两个输出结果相同 23 使用指向结构体数据的指针变量引用结构体成员的一般格式 指针变量名 成员名 为指向运算符 即取指针变量指向的结构体数据的成员 如 p real等价于 p real其含义为 取指针变量p指向的结构体数据的成员real 例11 3 2使用指向结构体数组元素的指针引用数组元素 输入输出N个复数 分析 复数用结构体类型表示 输入时用下标法引用数组元素 输出实用指针引用各元素 注意 p 的含义是p指向下一个数组元素 为了引用已定义的结构体类型 通常将结构体类型名定义为更简单的宏名 structcomplex intreal intimage defineCOMPLEXstructcomplex defineN5main COMPLEXss N p inti printf ninput dcomplex n N for i 0 i 引用成员 printf n d di p real p image 11 4动态内存分配与链表 动态内存分配的引入问题 如果要在内存中保存一个班学生的数据 按照现有的手段 首先要知道该班的人数 然后据此定义数组 可是 每一个班的人数并不完全相同 并且是浮动的 用确定长度的数组无法保存任意班级学生的数据 如果定义的数组太大 造成内存浪费 太小将导致程序无法实现原功能要求 这显然不够理想和灵活 解决以上问题的方法是使用动态内存分配 在程序运行中实时申请内存分配 申请到的内存在不用时还可以随时释放 这样就可以根据每次运行程序时要处理的数据的多少随时申请内存 因此可以处理任意人数的数据 用于动态内存分配的和释放的函数 1 malloc 函数原型 void malloc unsignedintsize 功能 申请分配size字节的连续内存空间 若分配成功 函数返回所分配内存的首地址 否则返回空指针 NULL 2 calloc 函数原型 void calloc unsignedintn unsignedintsize 功能 申请分配n各连续的内存空间 每个空间为size字节 若成功 返回所分配内存的首地址 否则返回空指针 NULL 3 free 函数原型 voidfree void p 功能 释放以前分配到的 指针p指向的内存空间 无返回值 例11 4 1编程实现 输入一批实验数据 整型 计算其平均值 个数由用户输入 include includemain intn i p floatsum 0 printf ninputdata snum scanf d printf ninput dinteger n for i 0 i n i p scanf d p sum p printf naver f sum n free p 程序分析 特别提示 1 使用分配失败是返回的空指针会造成程序的流产或系统的破坏 因此 程序中应先判断分配是否成功 然后再分别做出处理 2 所分配的首地址应先强制转换为所需的类型 然后使用 3 动态内存使用后应及时释放 否则 会导致内存资源的枯竭 链表 是一种重要的数据结构 用来保存一批相同类型的结构体数据 与数组不同的是 链表中的各元素不要求连续存放 而且链表的长度事先不必确定 当要输入数据时 先向系统申请分配一个结构体数据的空间 因此实现链表时要用到动态内存分配技术 由于链表的组成元素 结点 在C语言中是用结构体来实现的 所以链表和链表操作是结构体应用的重要实例 本节讨论最简单的链表 单向链表 单向链表 头指针头结点尾结点链表结点 结点是一结构体数据 其成员包括两部分 结点有效数据和结点指针 如图 结点指针指向下一个结点 由此将所有结点 链 在一起 形成一根数据的 链条 尾结点的指针为0 即空指针NULL 表示链表的结束 单向链表的基本操作 建立链表 插入 删除结点 释放结点或整个链表 例11 4使用链表建立工人的工资单档案 编号 姓名 工资 并能及时添加记录 删除记录 插入记录 输出工资表 分析 首先定义每个记录的结构体类型 structwork longno charname 10 有效数据 3项 floatsalary structwork next 指向下一个结点的指针 一 建立单向链表 功能 输入一个或多个结点数据 工人编号输入0时结束 按输入的先后顺序生成链表 返回链表的头指针 函数 structwork create 结点指针head为头指针 指向第一个结点 指针p1指向新输入的结点 p2指向链表的尾节点 n表示结点的个数 算法 首先输入一个结点数据 若该数据有效 即编号不等于0 n加1 然后将该结点加入链表 若n等于1 则该结点应是头结点 即head p1 否则 连接在尾结点后面 p2 next p1 然后p2后移 p2 p1 使得p2始终指向结点 重复以上过程 申请一个结点空间并输入数据 structwork input structwork q floatx q structwork malloc LEN if q printf nfailure exit 0 printf ninputaworker sinformation no 0forend n printf no scanf ld 返回该结点的首地址 建立链表 返回头指针 structwork create void structwork head p1 p2 intn 0 p1 p2 input head NULL while p1 no 0 n if n 1 head p1 elsep2 next p1 p2 p1 p1 input 输入下一个人的信息 p2 next NULL return head 二 添加结点 功能 在链表的末尾追加多个结点 直至输入的结点编号等于0为止 函数 structwork append structwork head 算法 指针p指向链表的尾结点 q指向新输入的结点 重复执行 若链表为空 则q指向的结点尾头结点 否则 将q链在p之后 添加结点之链表尾 structwork append structwork head2 structwork q p head2 q input q next NULL while q no 0 if head2 NULL while p next NULL p p next p next q elsehead2 p q q input q next NULL return head2 三 输出链表各结点 算法 指针p指向链表的头结点 然后重复 若p指向的结点不为空 即链表未结束 则输出链表的结点成员 p指向下一个结点 输出链表各结点 voidout list structwork head structwork p printf nnonamesalary n p head if head NULL printf nnodata elsewhile p NULL printf n 4ld 10s 7 2f p no p name p salary p p next 四 按编号删除结点 函数 structwork delete structwork head3 longno 算法 先判断链表是否为空 若是 则结束 否则 从头结点开始查找要删除的结点 若找到 则删除 即将其从链表中去掉 并释放该结点 否则 若到了链表的为结点仍未找到 则输出 notfound 按编号删除结点 structwork delete structwork head3 intno structwork p q head3 if head3 NULL printf nlistnull return head3 while no q no 在第n个结点前插入一个结点 分析 变量p指向第n个结点 q指向第n 1个结点 即新结点插在p和q指向的结点之间 分三种情况 1 插在头结点之前 2 插在中间 t next p q next t 3 链表中无第n个结点 在第n个结点前插入一个结点 structwork insert structwork head intn inti structwork p head q t t input if n 1 t next head head t return head 插在表头 for i 1 inext NULL q p p p next elsebreak if ino 0 q next t t next p return head 主函数 include include defineLENsizeof structwork main structwork head longnum intn1 head create printf nappend head append head printf ninsert scanf d 11 5共用体 所谓共用体数据类型是指将不同的数据项组织为一个整体 它们在内存中占用首地址相同的一段存储单元 共用体也称为联合 例如 unionexam inta floatb charc x 共用体类型说明的一般形式为 union共用体标识名 类型名1共用体成员名表1 类型名2共用体成员名表2 类型名n共用体成员名表n 其中union是关键字 是共用体类型的标志 共用体中的成员可以是简单变量 也可以是数组 指针 结构体和共用体 11 5 2共用体变量的定义及引用 定义共用体变量的方式与结构体变量相似 1 定义类型的同时定义变量 uniondata inti charch floatf a b c 2 将类型定义与变量定义分开 uniondata inti charch floatf uniondataa b c 3 直接定义共用体变量 union inti charch floatf a b c 可以引用一个共用体变量中的某个成员 引用方式与引用结构体变量中的成员相似 例如 a i 5 a ch b a f 8 6 特别提示 一个共用体变量不是同时存放多个成员的值 某一时刻只能存放其中的一个成员的值 这就是最后赋予它的值 比如 执行上面三个赋值语句后 变量a中存的是实型数8 6 如果此时执行语句printf d c f a i a ch a f 输出的分别是 a f中最低两个字节 a i的值 最低字节的值 a ch a f的值 例11 9 利用共用体的特点分别取出int变量中高字节和低字节中的两个数 includeunionword charch 2 intn typedefunionwordWORD main WORDw printf 输入 scanf d 运行结果 输入 24930 低位 98高位 97 11 6枚举类型 所谓 枚举 是指将变量的值一一列举出来 变量的值只限于列举出来的值的范围内 例如 enumweekday Sunday Monday Tuesday Wednesday Thursday Friday Saturday 说明 enum是关键字 标识枚举类型 定义枚举类型必须用enum开头 在C编译中 枚举类型中的元素按常量处理 称为枚举常量 不能对它们赋值 枚举常量是有值的 C语言按定义时的顺序定义它们的值为0 1 2 也可以在定义时指定枚举常量的值 例如 enumweekday Sunday 7 Monday 1 Tuesday Wednesday Thursday Friday Saturday 指定枚举常量的值后 其后的元素的之依次递增 如定义Sunday 7 Monday 1 则Tuesday的值顺序加1 即Tuesday 2 Saturday 6 枚举值可以用来作判断比较 按其值大小进行比较 如 if today Monday printf Monday 一个整数不能直接赋给一个枚举变量 应先进行强制类型转换才能赋值 例如 若定义 enumweekdayday 则day enumweekday 3 等价于 day Wednesday 11 7用typedef定义类型
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!