结构体C语言基础PPT.ppt_第1页
结构体C语言基础PPT.ppt_第2页
结构体C语言基础PPT.ppt_第3页
结构体C语言基础PPT.ppt_第4页
结构体C语言基础PPT.ppt_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

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

文档简介

第7章结构体 7 1 1结构体类型的声明 就像int float char一样 结构体也是一种数据类型 但它又跟这些基础类型不一样 因为它不是系统规定好的 而是可以根据用户需要来定义的 然后系统根据用户的定义来确定它占据的字节数 结构体类型的声明格式为 struct结构体类型名称 基础类型或结构体类型变量名 基础类型或结构体类型变量名 例如 structbook longbookid charname 20 floatprice 这样就声明了一个结构体类型structbook 然后可以用structbook来定义变量了 注意 1 结构体类型名的命名应遵循命名规则 2 结构体类型名不可以和它包含的基础类型名相同 例7 1 includevoidmain structbook longbook charname 20 floatprice x scanf ld 编译时出现 redefinitionofclassname book 错误 结构体类型名与结构体变量名相同虽编译正确 但一般不建议如此书写 例7 2 includevoidmain structbook longbookid charname 20 floatprice book scanf ld 3 结构体类型不占据内存空间 它仅是一个声明 结构体类型变量才占据内存空间 4 声明结构体类型时 花括号后的分号不能缺少 5 在声明结构体类型时 成员也可以是一个结构体类型变量 structp date intyear intmonth intday structlab book longbookid charname 20 structp datepubdate floatprice x y xp 7 1 2结构体类型变量的定义 每个结构体变量必须对应一个确定的结构体类型 因此要定义结构体类型变量必须声明结构体类型 定义结构体类型变量的格式为 struct结构体类型名结构体类型变量名 也可以定义指向结构体类型的指针变量 格式为 struct结构体类型名 结构体类型指针变量名 结构体变量的定义有三种形式 1 先声明结构体类型 再定义结构体类型变量 structbook longbookid charname 20 floatprice structbookx y xp 2 可以在声明结构体类型的同时定义结构体类型变量 structbook longbookid charname 20 floatprice x y 声明结构体类型的同时定义结构体变量x和y structbook xp 3 如果在声明结构体类型的同时定义结构体变量 那么可以省略结构体类型名 struct longbookid charname 20 floatprice x y 注意 a 结构体变量在内存中占据的字节数是该变量所属的结构体类型的各子类型所占据字节数之和 例如x和y变量所占据的内存数 4 1 20 4 28字节 b 不能对结构体类型进行存取 运算 因为结构体类型并不占据内存空间 只能对结构体变量进行赋值 存取 运算 c 在第三种定义结构体类型变量的方法中因为省略了结构体类型的名称 那么变量要跟在类型的声明后定义 struct longbookid charname 20 floatprice x y 声明结构体类型的同时定义结构体变量x和y struct xp 这种写法是错误的 只能把变量紧跟在类型声明后 structbook longbookid charname 20 floatprice x y xp 7 1 3结构体变量成员的引用 结构体变量是一个组合 进行输入和输出时不能整体输入和输出 必须对结构体变量成员逐一输入和输出 要引用结构体变量的成员就要用到成员运算符 成员运算符优先级为最高级 结合方向自左向右 用法如下 结构体变量 成员x bookid若结构体类型中又包含结构体类型 那么在进行输入和输出时应该用成员运算符找到最底层的成员 例7 3 includevoidmain structp date intyear intmonth intday 声明结构体类型p date structlab book longbookid charname 20 structp datepubdate floatprice x 声明结构体类型lab book 其成员pubdate是p date结构体类型变量 scanf d 输入 2011输出 Theyearis2011 7 1 4结构体变量的赋值 结构体变量在定义的同时可以赋初值 写法如下 structbook longbookid charname 20 floatprice x 6003563 EXPERTSYSTEMS 59 0 y 6003564 Meditations 32 0 除了在定义变量时赋初值 也可以在程序中对结构体变量赋值 在赋值时不能对结构体变量整体赋值 必须逐一对成员赋值 例7 4 includevoidmain structbook longbookid charname 20 floatprice x x bookid 6003563 strcpy x name EXPERTSYSTEMS x price 59 0 printf ld s f x bookid x name x price 7 1 5指向结构体类型变量的指针 可将一结构体变量的的地址赋值给结构体指针变量 然后可通过指针变量引用结构体变量 利用结构体指针变量引用结构体变量成员的方法为 结构体指针变量 例7 5 includevoidmain structbook longbookid charname 20 floatprice y xp 定义了结构体变量y和结构体指针变量xp xp 利用结构体类型指针变量引用结构体类型变量成员时要使用圆括号 和 号 写起来费时费力 因此c语言中提出一种新的符号 指向运算符 指向运算符 的优先级为最高优先级 结合方向自左向右 xp bookid等价于xp bookid 因此上题中的scanf 和printf 可改为 scanf d 7 2结构体数组 结构体数组的定义方式为 结构体类型数组名 数组大小 structbook longbookid charname 20 floatprice structbookn 5 与普通数组一样 可以在定义时对数组进行初始化 structbook longbookid charname 20 floatprice structbookn 5 6003563 EXPERTSYSTEMS 59 0 6003564 Meditations 32 0 6003565 TheSecret 32 0 6003566 WUTHERINGHEIGHTS 35 0 6003567 EMMA 15 8 也可以写为 structbook longbookid charname 20 floatprice n 5 6003563 EXPERTSYSTEMS 59 0 6003564 Meditations 32 0 6003565 TheSecret 32 0 6003566 WUTHERINGHEIGHTS 35 0 6003567 EMMA 15 8 在使用时 结构体数组元素和普通的结构体类型变量的用法一致 在遍历结构体数组元素时 可以使用循环 也可以使用 自增运算符和 自减运算符 例7 6输入5本书的信息 并求出图书的平均价格 includevoidmain structbook longbookid charname 20 floatprice structbookb 5 inti floatsum 0 ave 0 for i 0 i 5 i scanf ld 也可以使用指向结构体变量的指针结合自增运算符 遍历结构体数组 上述c程序可改写为 includevoidmain structbook longbookid charname 20 floatprice structbookb 5 xp floatsum 0 0 ave 0 0 for xp b xpbookid 为了避免输入问题 ld后有一空格 gets xp name scanf f xp price sum sum xp price ave sum 5 0 printf Theaverageis f ave 7 3结构体和函数 1 结构体变量成员作为函数参数结构体变量成员作为函数的参数与普通变量作为函数的参数用法相似 实参和形参之间是单向值传递 实参和形参占据不同的内存单元 对形参的修改不会影响实参的值 例7 8 某单位有10名职工参加考试 每位职工的信息包括 工号 姓名 年龄 成绩 年龄50岁及以上的 60分及格 年龄50岁以下的 75分及格 要求输出及格人数以及及格人员的平均成绩 includefloattotal 0 0 intcount 0 structemployee intnumber charname 10 intage floatgrade voidsum intx floaty voidmain structemployeea 10 inti for i 0 i 50 2 结构体变量作为函数参数结构体变量作为函数的参数 实参和形参之间是单向值传递 实参和形参占据不同的内存单元 对形参的修改不会影响实参的值 这种方法使用的比较少 因为在函数调用时要为形参分配与实参等同的内存单元 内存空间消耗太大 例如上题可改为 例7 9 includefloattotal 0 0 intcount 0 structemployee intnumber charname 10 intage floatgrade voidsum structemployeex voidmain structemployeea 10 inti for i 0 i 10 i scanf d printf Thenumberofpassingtheexaminationis d andtheaverageis f n count total count voidsum structemployeex if x age 50 3 指向结构体变量的指针作为函数参数结构体指针变量作为函数的参数 实参指针和形参之间是单向值传递 实参指针和形参指针占据不同的内存单元 传递的是指针所指向的结构体变量的地址 在传递完毕后 实参指针和形参指针指向同一个结构体变量 函数中对指针所指向的结构体变量的修改在函数调用结束后会被保留下来 某单位有10名职工参加考试 每位职工的信息包括 工号 姓名 年龄 成绩 年龄50岁及以上的 所有人成绩加2分 年龄50岁以下的所有人成绩加1分 要求输出所有人修改后的成绩 例7 10 includestructemployee intnumber charname 10 intage floatgrade voidrevise structemployee xp voidmain structemployeea 10 x for x a xnumber gets x name scanf d revise x printf TheemployeeNO is d andthegradechangedis f x number x grade voidrevise structemployee xp if xp age 50 xp grade 2 elseif xp agegrade 1 7 4链表 1 动态存储分配无论是变量还是数组在程序运行前的编译阶段已经被分配好了内存空间 但是有些时候我们希望在程序运行过程中动态地分配一内存空间来使用 这就要用到内存分配函数malloc 和calloc 使用完毕的内存空间还可以用free 函数回收 这三个函数通常被包含在 stdlib h 头文件中 但在有的编译系统中被包含在 malloc h 头文件中 建议使用时查阅相关手册 1 malloc 函数其函数原型为 void malloc unsignedintsize 其作用是在内存空间中分配一大小为size个字节的连续空间 函数返回一个void类型 无类型 的指针 须将该指针强制类型转换为某种特定的指针类型方可使用 如果函数执行失败 空间不够 则返回空指针 NULL 例 structemployee intnumber charname 10 intage floatgrade structemployee xp xp structemployee malloc sizeof structemployee 实现了分配一个存储类型为structemployee的内存单元 并用structemployee类型的指针变量xp指向该单元 程序中可以使用指针xp找到该单元并对单元内各成员进行输入输出和修改 2 calloc 函数其函数原型为 void calloc unsignedintn unsignedintsize 其作用是在内存空间中分配n个每个大小为size个字节的连续空间 函数也返回一个void类型 无类型 的指针 也须将该指针强制类型转换为某种特定的指针类型方可使用 如果函数执行失败 空间不够 则返回空指针 NULL calloc 函数在分配空间的同时实现清0的工作 而malloc 函数不具备这个功能 3 free 函数如果只有分配内存单元的函数没有回收函数 那么极有可能出现内存单元不足的情况 free 函数能把malloc 函数和calloc 函数分配的单元释放掉 以供下次分配 其函数原型为 void free void xp 其作用是释放xp指针所指向的内存单元 xp是最近一次由malloc 或calloc 调用的返回值 free 函数本身没有返回值 2 链表概述 链表的元素个数可以根据需要任意增减 是一种能够动态的进行存储分配的重要数据结构 1354 1542 1684是链表结点的地址 链表是有一个头指针和若干个数据节点组成的 每个数据节点都是一个结构体类型的变量 从上图的地址可以看出链表节点并不是紧挨着的 因此适应于内存空间比较零碎 很难找到一块很大的连续空间的情况 3 建立链表 例7 11 输入图书信息 建立一个图书信息链表 当输入的图书价格为0时结束链表 include includestructbook longbookid charname 20 floatprice structbook next structbook set structbook head NULL p1 NULL p2 NULL intn 0 while 1 p1 structbook malloc sizeof structbook 开辟一个新单元 scanf ld if p1 price 0 break if n 0 第一个节点 需要特别处理 head p1 p2 p1 else p2 next p1 p2 p1 n if n 0 p2 next NULL 最后一个节点的next值为NULL return head voidmain structbook head p1 p2 head set if head NULL printf Havenonodes else p1 head while p1 NULL printf ld s f n p1 bookid p1 name p1 price p1 p1 next 4 查找链表元素现有一个图书信息链表 编写一个查找编号的函数 例7 12structbook search structbook head intnum structbook p p head while p NULL if p bookid num printf Findnodesuccessfully ThebookIDis d booknameis s priceis f p bookid p name p price return p else p p next return NULL 5 插入链表元素 1 插入位置位于链表中间 前后都有结点 那么操作步骤为 指针p1插入位置的前一结点 指针p2指向插入位置的后一结点 指针insert指向待插入的结点 p2 next insert insert next p1 next next next next next next 2 插入位置位于链表第一个结点前 那么操作步骤为 指针p1指向链表第一个结点 指针insert指向待插入的结点 head insert insert next p1 next next next next 3 插入位置位于链表最后一个结点后 那么操作步骤为 指针p2指向链表最后一个结点 指针insert指向待插入的结点 p2 next insert insert next NULL next next next next next NULL 现有一个图书信息链表是按图书编号由小到大的顺序排列的 编写程序实现插入一个链表结点 例7 13 include includestructbook longbookid charname 20 floatprice structbook next structbook set structbook head NULL p1 NULL p2 NULL intn 0 while 1 p1 structbook malloc sizeof structbook 开辟一个新单元 scanf ld if n 0 第一个节点 需要特别处理 head p1 p2 p1 else p2 next p1 p2 p1 n if n 0 p2 next NULL 最后一个节点的next值为NULL return head structbook insert structbook head structbook ins structbook p1 p2 p1 head if head NULL head ins ins next NULL return head if head bookid ins bookid head ins ins next p1 return head p2 p1 p1 p1 next while p1 NULL if p1 bookidbookid p2 p1 p1 p1 next else p2 next ins ins next p1 return head p2 next ins ins next NULL return head voidmain structbook head p1 xp longnum head set xp structbook malloc sizeof structbook printf Inputinsertnodeinformation n scanf ld 6删除链表结点删除链表结点是去掉指向该结点的指针 那么该结点就不会被找到 就相当于删除了 删除已有的链表中的结点首先要确认删除位置 删除位置不同所需的操作也不同 1 删除位置位于链表中间 前后都有结点 那么操作步骤为 指针p1指向要删除的结点 指针p2指向删除位置的后一结点 则p2 next p1 next next next next next next next 2 删除链表第一个结点 那么操作步骤为 让指针p1指向链表首结点 则head p1 next next next next next 3 删除链表最后一个结点 那么操作步骤为 指针p2指向链表倒数第二个结点 则p2 next NULL next NULL NULL NULL 例7 14 现有一个图书信息链表 编写程序实现删除一个链表结点 include includestructbook longbookid charname 20 floatprice structbook next structbook set structbook head NULL p1 NULL p2 NULL intn 0 while 1 p1 structbook malloc sizeof structbook 开辟一个新单元 scanf ld if n 0 第一个节点 需要特别处理 head p1 p2 p1 else p2 next p1 p2 p1 n if n 0 p2 next NULL 最后一个节点的next值为NULL return head structbook del structbook head longnum structbook p1 p2 p1 head if head NULL printf Chainhasnonodes n return NULL if head bookid num 删除的是链表头结点 head p1 next return head p2 p1 p1 p1 next while p1 NULL if p1 bookid num voidmain structbook head p1 xp longnum head set printf Inputinsertnodeinformation n scanf ld 7 5联合 多个变量可以共享一段内存空间 前提是这些变量不会被同时使用 这种不同变量共用一段内存空间的结构叫做联合体也叫共用体 联合体的定义形式为 union联合体名 类型变量名 类型变量名 unionran intx chary floatz p 注意 1 联合体定义时最后的分号不能丢 2 占据内存单元最大的成员所占据的字节数就是整个联合体变量所占的字节数 3 联合体变量任一时刻只能存放其中一个成员的信息 如果再放入新成员信息那么前一成员信息就被覆盖了unionran intx chary floatz p p x 10 p z 3 14 联合体变量p里保存的是成员z的数据 成员x的数据被覆盖掉了 例7 15 输入五位员工信息 求出员工的平均工资 类别代码为1的老员工输入工号 年龄 工资 类别代码为2的新员工没有工号则输入姓名 年龄 工资 includevoidmain unioninfo 声明联合体类型info intnumber charname 10 structemployee 声明结构体类型employee intrank unioninfox 成员x是联合体类型变量 intage floatsalary s 5 inti floatsum 0 ave 0 for i 0 i 5 i printf Pleaseinputrank n scanf d 7 6位域 一 位域的声明位域的声明类似于结构体 struct位域类型名 类型说明符位域成员名 位域长度 类型说明符位域成员名 位域长度 例如 structstate 声明位域类型state unsignedinterror 2 error占2位 unsignedintready 2 ready占2位 unsignedintread 2 read占2位 unsignedintwrite 2 write占2位 structstatex 定义state位域类型变量x 说明 1 在VC 编译环境中 一个位域必须存储在同一个整数字 4字节 32位 中 不能跨两个整数字 如一个整数字所剩空间不够存放另一位域时 应占据下一整数字存放该位域 例如 structexample unsignedinta 28 unsignedintb 3 unsignedintc 2 unsignedintd 2 x x变量占据8个字节 2个整数字 a和b放在第一个整数字中 c和d放在第二个整数字中 也可以有意使某位域从下一整数字开始 structexample unsignedinta 28 unsigned 0 空域 unsignedintb 3 从下一整数字开始存放 unsignedintc 2 unsignedintd 2 y 在这个位域定义中 a占据第一整数字 空域的作用是使下一位域从下一整数字开始存放 所以4位填0表示不使用 b从第二整数字开始存放占3位 c占用2位 d占用2位 2 由于位域不允许跨两个整数字 因此位域的长度不能大于一个整数字的长度 也就是说不能超过32位二进位 structexample unsignedinta 33 出错 unsignedintb 2 z 编译出错 显示 errorC2034 a typeofbitfieldtoosmallfornumberofbits3 不同的及其分配字段的方向不同 有的从左向右 有的从右向左 4 位域值没有符号 也不能对位域取地址 二 位域的使用位域的使用和结构成员的使用相同 其一般形式为 位域变量名 位域名例7 16 includevoidmain structexample unsignedinta 4 unsigned 4 无名的空域不能使用 只用于填充 unsignedintb 4 x x a 3 x b 2 printf d d n x a x b 注意 位域可以无位域名 这时它只用来作填充或调整位置 无名的位域是不能使用的 C中的位域在嵌入式软件中很常见 位域的最大好处是可以根据自己需要定制位数 从而节省空间 特别适合嵌入式编程稀缺的内存资源 还有在网络通讯中 对头信息部分的结构定义也常用到位域 因为传输的信息越少所需要的传输时间越少 7 7枚举 若变量可取的值只有有限的几种 那么这种变量可被定义为枚举类型的变量 枚举类型的变量就是把变量可取的值一一列出 变量只能取其中的一种 枚举类型的声明enum枚举类型名 枚举常量 枚举常量 枚举常量 例 enumnumber one two three four five 注意 1 枚举类型常量是必须是合法的标志符 2 编译系统在处理枚举常量时是为每个枚举类型常量自动与一个整数相联系 且整数默认是从0开始按每次加1的顺序 在enumnumber one two three four five 声明中one为

温馨提示

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

评论

0/150

提交评论