




已阅读5页,还剩98页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计 CProgramming 辽宁科技大学 下 C语言程序设计 CProgramming 第7章构造数据类型第8章编译预处理第9章文件 第7章构造数据类型 C语言程序设计 CProgramming 辽宁科技大学 4 1 掌握结构体类型 结构体变量 结构体数组的定义和使用2 掌握结构体类型指针的概念和使用3 掌握结构体作为函数的参数和返回值的使用4 掌握共用体类型 共用体变量的定义和使用5 理解链表的概念和建立6 了解枚举类型的定义和使用 本章学习目标 5 7 1结构体数据类型 7 2结构体与数组 7 3结构体与指针 7 4结构体与函数 7 5结构体与链表 7 6共用体数据类型 7 7枚举类型 7 8类型定义符Typedef 6 7 1结构体数据类型 1 结构体类型的定义 2 结构体变量的定义 3 结构体变量的初始化 4 结构体变量成员的引用 结构体 是一种构造数据类型 结构体中包含的数据元素称为成员 那么如何定义一个结构体数据类型呢 定义一个结构体类型的一般形式为 struct结构体名 类型说明符1成员名1 类型说明符2成员名2 类型说明符n成员名n 每个成员都是该结构体类型的一个组成部分 每个成员可以是一个基本数据类型 也可以是一个构造类型 成员名的命名应符合标识符的书写规范 7 7 1结构体数据类型 1 结构体类型的定义 2 结构体变量的定义 3 结构体变量的初始化 4 结构体变量成员的引用 structstudent longno charname 15 charsex intage floatscore 在这个结构体定义中 student为结构体名 no name sex age和score为该结构的5个成员 其中no为长整型变量 name为字符数组 sex为字符变量 age为整型变量 score为实型变量 一般情况下 结构体名称用有一定意义的单词或单词的缩写组合作为结构体的名称 结构体是一个整体 因此结构体中的每个成员不能脱离结构体单独使用 8 7 1结构体数据类型 2 结构体变量的定义 1 结构体类型的定义 3 结构体变量的初始化 4 结构体变量成员的引用 结构体类型一旦定义 即可进行变量定义 以结构体student为例 凡定义为结构student的变量都由上述5个成员组成 成员名可以与程序中变量名相同 两者互不干扰 结构体变量定义有以下三种方法 1 先定义结构体类型 再定义结构体变量 例如 structstudent longno charname 15 charsex intage floatscore structstudentstu1 stu2 本例中定义了两个变量stu1和stu2 它们都是student结构体类型 structstudent代表的是类型名 就如同定义实型变量时 如 floata b 其中float是类型名是一样的 结构体类型所占有的内存字节数是所有成员的字节数的和 9 7 1结构体数据类型 2 结构体变量的定义 1 结构体类型的定义 3 结构体变量的初始化 4 结构体变量成员的引用 2 在定义结构体类型的同时定义结构体变量 例如 structstudent longno charname 15 charsex intage floatscore stu1 stu2 10 7 1结构体数据类型 2 结构体变量的定义 1 结构体类型的定义 3 结构体变量的初始化 4 结构体变量成员的引用 3 直接定义结构体类型的变量 例如 struct longno charname 15 charsex intage floatscore stu1 stu2 11 7 1结构体数据类型 3 结构体变量的初始化 1 结构体类型的定义 2 结构体变量的定义 4 结构体变量成员的引用 例7 1 外部结构体变量初始化 includestructstudent 结构体定义 longno charname 15 charsex intage floatscore stu1 structstudentstu1 20080001 ZhangJun M 21 87 5 voidmain printf No ld nName s n stu1 no stu1 name printf Sex c nAge d nScore f n stu1 sex stu1 age stu1 score 12 7 1结构体数据类型 3 结构体变量的初始化 1 结构体类型的定义 2 结构体变量的定义 4 结构体变量成员的引用 例7 2 静态结构体变量初始化 includevoidmain staticstructstudent 定义静态结构体变量 longno charname 15 charsex intage floatscore stu2 20080001 ZhangJun M 21 87 5 printf No ld nName s n stu2 no stu2 name printf Sex c nAge d nScore f n stu2 sex stu2 age stu2 score 13 7 1结构体数据类型 4 结构体变量成员的引用 1 结构体类型的定义 2 结构体变量的定义 3 结构体变量的初始化 定义了结构体变量以后 就可以引用这个变量 在程序中使用结构变量时 往往不把它作为一个整体来使用 对结构变量的使用 包括赋值 输入 输出 运算等都是通过结构变量的成员来实现的 表示结构变量成员的一般形式是 例如 stu1 no 学生的学号 stu1 name 学生的姓名 其中 是成员运算符 它在所有的运算符中优先级最高 如果成员本身又是一个结构体类型 则应该用若干个 一级一级地找到最低级的成员 例如 stu1 birthday yearstu1 birthday monthstu1 birthday day不能将一个结构体变量作为一个整体加以引用 例如已定义了结构体变量stu1 并且进行了初始化 14 7 1结构体数据类型 4 结构体变量成员的引用 1 结构体类型的定义 2 结构体变量的定义 3 结构体变量的初始化 例7 3 结构体变量的引用 includevoidmain structdate intyear intmonth intday structstudent longno charname 15 charsex intage structdatebirthday floatscore stu2 stu1 20080001 ZhangJun M 21 1987 3 19 87 5 stu2 stu1 stu2 age printf No ld nName s n stu2 no stu2 name printf Birthday d d d n stu2 birthday year stu2 birthday month stu2 birthday day printf Sex c nAge d nScore 2f n stu2 sex stu2 age stu2 score 15 7 2结构体与数组 1 结构体数组的定义 2 结构体数组的初始化 3 结构体数组的引用 结构体数组的定义方法和结构体变量的定义方法相同 可以采用三种方法定义结构体数组 本节以第二种方法为例 例如 structstudent longno charname 15 charsex intage floatscore char address stu 5 定义了一个结构数组stu 数组中包含5个元素 stu 0 stu 4 每个数组元素都是一个结构体变量 16 7 2结构体与数组 2 结构体数组的初始化 1 结构体数组的定义 3 结构体数组的引用 结构体数组可以在定义时初始化 但只能对全局的或静态存储的数组进行初始化 例如 structstudent longno charname 15 charsex intage floatscore char address stu 5 20080001 Liuping F 20 85 0 Beijing 20080002 Zhangbin M 21 72 0 Anshan 20080003 Hanfeng M 21 96 5 Hefei 20080004 zengli F 21 67 0 Dalian 20080005 Wangmin F 20 57 5 Tianjin 当对全部元素作初始化赋值时 也可不给出数组长度 17 7 2结构体与数组 2 结构体数组的引用 1 结构体数组的定义 3 结构体数组的初始化 结构体数组的引用类似于结构体变量的引用 只是用结构体数组元素来代替结构体变量 如第一个学生的个人信息 stu 0 nostu 0 namestu 0 sexstu 0 agestu 0 scorestu 0 address同结构体变量一样 结构体数组元素不能整体的输入输出 只能以单个成员为对象进行输入输出 18 7 2结构体与数组 2 结构体数组的引用 1 结构体数组的定义 3 结构体数组的初始化 例7 4 计算学生的平均成绩 includestructstudent longno charname 15 charsex intage floatscore char address stu 5 20080001 Liuping F 20 85 0 Beijing 20080002 Zhangbin M 21 72 0 Anshan 20080003 Hanfeng M 21 96 5 Hefei 20080004 zengli F 21 67 0 Dalian 20080005 Wangmin F 20 57 5 Tianjin 19 7 2结构体与数组 2 结构体数组的引用 1 结构体数组的定义 3 结构体数组的初始化 例7 4 计算学生的平均成绩voidmain inti floatave sum 0 for i 0 i 5 i sum sum stu i score ave sum 5 printf Average 2f n ave 20 7 3结构体与指针 1 指向结构体变量的指针 2 指向结构体数组的指针 指向一个结构体变量的指针变量称之为结构体指针变量 一个结构体变量的指针是该变量所占内存空间的首地址 通过结构体指针即可访问该结构体变量 结构体指针变量定义的一般形式为 struct结构体名 结构体指针变量名例如 structstudent longno charname 15 charsex intage floatscore char address stu1 stu2 structstudent pstu 结构体指针变量先赋值后才能使用 赋值是把结构体变量的首地址赋予该指针变量 21 7 3结构体与指针 例7 5 通过结构体指针输出程序代码 includestructstudent longno charname 15 charsex intage floatscore char address stu1 20080001 Liuping F 20 85 0 Beijing pstu voidmain pstu 1 指向结构体变量的指针 2 指向结构体数组的指针 22 7 3结构体与指针 例7 5 通过结构体指针输出程序代码 includestructstudent longno charname 15 charsex intage floatscore char address stu1 20080001 Liuping F 20 85 0 Beijing pstu voidmain pstu 1 指向结构体变量的指针 2 指向结构体数组的指针 23 7 3结构体与指针 指针变量可以指向一个结构体变量 同样指针变量也可以指向一个结构体数组 此时结构体指针变量的值是整个结构数组的首地址 通过结构体指针变量的移动可以指向结构体数组的任意一个元素 例7 6 用指针变量输出结构体数组 includestructstudent longno charname 15 charsex intage floatscore char address stu 5 20080001 Liuping F 20 85 0 Beijing 20080002 Zhangbin M 21 72 0 Anshan 20080003 Hanfeng M 21 96 5 Hefei 20080004 zengli F 21 67 0 Dalian 20080005 Wangmin F 20 57 5 Tianjin 2 指向结构体数组的指针 1 指向结构体变量的指针 24 7 3结构体与指针 voidmain structstudent pstu clrscr printf No t tName t tSex tAge tScore t tAddress n for pstu stu pstuno pstu name pstu sex pstu age pstu score pstu address 2 指向结构体数组的指针 1 指向结构体变量的指针 25 7 4结构体与函数 例7 7 输出一组学生中的最高成绩 includestructstudent longno charname 15 charsex intage floatscore char address stu 5 20080001 Liuping F 20 85 0 Beijing 20080002 Zhangbin M 21 72 0 Anshan 20080003 Hanfeng M 21 96 5 Hefei 20080004 zengli F 21 67 0 Dalian 20080005 Wangmin F 20 57 5 Tianjin 1 结构体指针变量作嫦娥数参数针 2 结构体指针变量作函数返回值 26 7 4结构体与函数 voidmain structstudent pstu floatmax structstudent pstu pstu stu printf Max 2f max pstu floatmax structstudent p inti floatmax max p score for i 1 iscore max max p score returnmax 1 结构体指针变量作嫦娥数参数针 2 结构体指针变量作函数返回值 27 7 4结构体与函数 例7 8 输出一组学生中的成绩最高学生的学号 姓名和成绩 includestructstudent longno charname 15 charsex intage floatscore char address stu 5 20080001 Liuping F 20 85 0 Beijing 20080002 Zhangbin M 21 72 0 Anshan 20080003 Hanfeng M 21 96 5 Hefei 20080004 zenglili F 21 67 0 Dalian 20080005 Wangmin F 20 57 5 Tianjin 2 结构体指针变量作函数返回值 1 结构体指针变量作嫦娥数参数针 28 7 4结构体与函数 voidmain structstudent pstu q structstudent max structstudent pstu pstu stu q max pstu printf No t tName t tScore n printf ld t s t 2f n q no q name q score structstudent max structstudent p inti k 0 floatmax max p score for i 1 iscore max k i returnp k 2 结构体指针变量作函数返回值 1 结构体指针变量作嫦娥数参数针 29 7 4结构体与函数 程序说明 程序中定义了函数structstudent max structstudent p 其形参为结构体指针变量p 函数的返回值也为结构体指针变量 stu被定义为结构体数组 并作了初始化 语句pstu stu 把stu的首地址赋予pstu 使pstu指向stu数组 以pstu作实参进行函数调用q max pstu 并将结果返回给结构体指针变量q 2 结构体指针变量作函数返回值 1 结构体指针变量作嫦娥数参数针 30 7 5结构体与链表 1 动态存储分配 2 链表的操作 在 语言中不允许动态定义数组类型 也就是说数组的长度一旦定义是不可以改变的 但是在实际的应用中 有些问题的数据量的大小是无法预先确定 并且在程序的运行过程中数据的个数是动态改变的 为了解决此类问题 语言提供了一些内存管理函数 这些内存管理函数可以按需要动态地增加或减少内存空间 C语言中提供了4个有关动态存储分配的函数 即malloc calloc free 和realloc 常用的两个函数是malloc 和free 分配内存空间函数malloc 函数原形 void malloc unsignedsize 功能 在内存的动态存储区中分配一块长度为 size 字节的连续存储区 函数的返回值为该区域的首地址 malloc 函数经常和sizeof 一起使用 31 7 5结构体与链表 1 动态存储分配 2 链表的操作 例如 p int malloc 50 表示分配50个字节的内存空间 并强制转换为整型数据类型数组 函数的返回值为指向该整型数组的指针 把该指针赋予指针变量p 释放内存空间函数free 函数原形 voidfree void p 功能 释放p所指向的一块连续内存存储空间 p指向被释放区域的首地址 被释放区必须是由malloc或calloc函数所分配的区域 32 7 5结构体与链表 2 链表的操作 1 动态存储分配 C语言中动态内存管理函数的引入提高了系统内存的使用效率 链表是实现动态内存分配的解决方案 它是在程序的执行过程中根据需要向系统要求申请存储空间 使用结束就释放内存空间 决不构成对存储区的浪费 链表是一种复杂的数据结构 其数据之间的相互关系使链表分成三种 单链表 循环链表 双向链表 本节主要介绍单链表的建立 插入 删除等操作 链表采用动态分配的办法为一个结构体分配内存空间 称之为一个结点 每个结点存放一个对象 学生或职工等 的数据信息 有多少个对象就应该申请分配多少个结构体内存空间 也就是说要建立多少个结点 当对象增加或减少时动态的添加或释放存储空间 结点 33 7 5结构体与链表 2 链表的操作 1 动态存储分配 如建立一个学生学籍管理系统 有一个学生就分配一个结点 结点之间的联系用指针来实现 如果某学生退学 可删去该结点 并释放该结点占用的存储空间 使用动态分配时 每个结点之间可以是不连续的 结点内是连续的 在结点结构中定义一个成员项用来存放下一结点的起始地址 这个用于存放地址的成员 常把它称为指针域 在第一个结点的指针域内存入第二个结点的起始地址 在第二个结点的指针域内又存放第三个结点的起始地址 如此串连下去直到最后一个结点 最后一个结点因无后续结点连接 可以赋值为NULL 这样一种存储管理方式 在数据结构中称为 链表 34 7 5结构体与链表 2 链表的操作 1 动态存储分配 图7 1为一学生学籍管理单链表的示意图 图中每个结点是一个结构体 结构体的定义如下 structstudent longno charname 15 charsex intage floatscore 35 7 5结构体与链表 2 链表的操作 1 动态存储分配 例7 9 建立一个10个结点的链表 存放学生数据 程序分析 定义链表结点的数据结构 建立表头 利用malloc函数向系统申请结点空间 对新结点赋值 将新结点的指针域赋为NULL 若是空表就将新结点连接到表头 否则将新结点连接到表尾 若有后续结点则转到 3 否则结束 程序代码 include includestructstudent longno charname 15 charsex intage floatscore structstudent next 36 7 5结构体与链表 2 链表的操作 1 动态存储分配 structstudent create structstudent head intn structstudent p1 p2 inti p1 head p2 structstudent malloc sizeof structstudent printf Inputstudentdata scanf ld s c d f 37 7 5结构体与链表 2 链表的操作 1 动态存储分配 voidprint structstudent h structstudent t h while t NULL printf n ld s c d 2f n t no t name t sex t age t score t t next voidmain structstudent head head NULL head create head 10 print head 38 7 5结构体与链表 2 链表的操作 1 动态存储分配 例7 10 创建包含学号 姓名结点的单链表 其结点数任意个 表以学号为序 低学号的在前 高学号的在后 以输入姓名为空作结束 在此链表中 要求删除一个给定姓名的结点 并插入一个给定学号和姓名的结点 include stdio h include string h include malloc h structnode 结点的数据结构 intnum charname 20 suctnode next 39 7 5结构体与链表 2 链表的操作 1 动态存储分配 voidmain structnode create 函数声明 structnode insert structnode delete voidprint structnode head charstr 20 intn head NULL 做空表 head create head 调用函数创建以head为头的链表 print head 调用函数输出结点 printf nPleaseinputinsertednum name n scanf d 40 7 5结构体与链表 2 链表的操作 1 动态存储分配 创建链表 structnode create structnode head structnode p1 p2 p1 p2 structnode malloc sizeof structnode printf Pleaseinputnum name n scanf d 41 7 5结构体与链表 2 链表的操作 1 动态存储分配 插入结点 structnode insert head pstr n structnode head char pstr intn structnode p1 p2 p3 p1 structnode malloc sizeof structnode strcpy p1 name pstr p1 num n p2 head if head NULL head p1 p1 next NULL else while n p2 num 42 7 5结构体与链表 2 链表的操作 1 动态存储分配 删除结点 structnode delete head pstr structnode head char pstr structnode temp p temp head if head NULL printf nThelistisnull n else temp head while strcmp temp name pstr 0 43 7 5结构体与链表 2 链表的操作 1 动态存储分配 链表各结点的输出 voidprint structnode head structnode temp temp head printf nOutputstudents n while temp NULL printf n d s n temp num temp name temp temp next return 44 7 6共用体数据类型 共用体又叫联合体 共用体也是将不同数据类型的数据项组成一个整体 但是它与结构体不同 这些不同类型的数据项在内存中所占用的起始地址是相同的 共用体类型的定义形式和结构体的定义形式是相似的 向区别的就是结构体定义的关键字是struct而共用体定义的关键字是union 1 共用体数据类型的定义定义一个共用体类型的一般形式为 union共用体名 类型说明符1成员名1 类型说明符2成员名2 类型说明符n成员名n 例如 unionmem chara floatb 45 7 6共用体数据类型 2 共用体变量的定义共用体变量的定义和结构体变量的定义方式相同 也有三种形式 定义一个共用体变量的一般形式为 union共用体名 类型说明符1成员名1 类型说明符2成员名2 类型说明符n成员名n 变量名表列 例如 unionmem chara floatb x y 46 7 6共用体数据类型 3 共用体变量的引用 共用体变量的应用方式和结构体变量的引用方式相同 由于共用体变量不同时具有每个成员的值 因此 最后一个赋予它的值就是共用体的值 例如 unionmem chara floatb x y x a A x b 100 共用体变量x的a成员先被赋予了 A 然后b成员又被赋予了100 最后共用体变量x中只存储了成员b的值 即100 47 7 6共用体数据类型 4 共用体的特点 1 同一内存段可放几种不同类型的成员 但每次只能存放一种数据类型的数据 例如 a c a a f 2 1 在完成以上两个赋值运算后 只有a f是有效的 a c都不再有效 例如 printf f a f 正确的 printf c a c 错误的 所以引用共同体变量时应该特别注意当前放的是什么数据 2 共用体变量地址及其各成员地址都是同一地址 即 a a i a c a f值相同 3 不能对共用体变量名赋值 也不能定义时进行初始化 4 不能把共用体变量作为函数参数 也不能使函数返回共同体变量 但可以使用指向共用体的指针 5 允许定义共用体数组 48 7 7枚举类型 1 枚举类型定义的一般形式为 enum枚举名 枚举值表 在枚举值表中应列出所有可用值 这些值也被称为枚举元素 例如 enumweekday Sunday Monday Tuesday Wednesday Thursday Friday Saturday 枚举名为weekday 枚举值共有7个 枚举类型中个每个元素对应一个数值 系统默认从0开始 如在weekday中 Sunday值为0 Monday值为1 Tuesday值为 Wednesday值为 Thursday值为 Friday值为 Saturday值为6 一旦定义它们的值是不能改变的 49 7 7枚举类型 2 枚举变量的说明同结构和共用体变量定义一样 枚举变量也可用不同的方式说明 即先定义后说明 同时定义说明或直接说明 例如 enumweekday Sunday Monday Tuesday Wednesday Thursday Friday Saturday enumweekdaya b 或者为 enumweekday Sunday Monday Tuesday Wednesday Thursday Friday Saturday a b 或者为 enum Sunday Monday Tuesday Wednesday Thursday Friday Saturday a b 50 7 8类型定义符Typedef 整型 字符型 实型等数据类型是系统定义的类型说明符 C语言还允许用户自定义类型说明符 也就是说为已有的数据类型取个 别名 类型定义符typedef即可用来完成此功能 typedef定义的一般形式为 typedef原类型名新类型名1 简单的类型名称定义例如 typedeffloatREAL 一旦定义 则float和REAL两者是等价的 就可用INTEGER来代替int作整型变量的说明了 例如 REALa b 它等价于 floata b 51 7 8类型定义符Typedef 2 结构体类型名称定义例如 typedefstructstudent longno charname 15 intage STU 定义的STU等同于student的结构体类型 然后结构体变量的定义就可以是 STUstu1 stu2 它等价于 structstudentstu1 stu2 52 7 8类型定义符Typedef 3 数组类型定义例如 typedefcharADDRESS 20 表示ADDRESS是字符数组类型 数组长度为20 然后可用ADDRESS进行数组说明 如 ADDRESSstr1 str2 它等价于 charstr1 20 str2 20 习惯上常把用typedef定义的类型名称用大写字母来表示 以区别于系统定义的标识符 需要注意的是typedef可以重新定义各种类型名 但不能定义变量 typedef与 define有相似之处 但 define是由编译预处理完成的 typedef是在编译时完成的 因此更为灵活方便 使用typedef有利于提高程序的通用性 移植性和可读性 53 第8章编译预处理 C语言程序设计 CProgramming 辽宁科技大学 54 8 1宏定义 define 8 2文件包含 include 55 8 1宏定义 define 1 不带参有宏定义 2 带参的宏定义 定义的一般形式为 define标示符字符串其中的 表示这是一条预处理命令 define 为定义宏命令 标示符 为所定义的宏名 字符串 可以是常数 表达式 格式串等 如 definePI3 1415926 definePRprintf 无参宏的使用可以减少程序输入量 方便程序的调试与修改 56 8 1宏定义 define 1 不带参有宏定义 2 带参的宏定义 例8 1 求N个数的平均值 并输出其最大值与最小值 程序代码 defineN100 includevoidmain floata N s ver max min intk for k 0 kmax max a k if a k min min a k s a k ver s N printf n f f f ver max min 57 8 1宏定义 define 1 不带参有宏定义 2 带参的宏定义 例8 2 宏替换的应用 程序代码 defineQ x x x 2 x x 1 includevoidmain longx y scanf d 58 8 1宏定义 define 1 不带参有宏定义 2 带参的宏定义 不带参数的宏定义应该注意的一些问题 1 宏定义是用宏名来表示一个字符串 在宏展开时又以该字符串取代宏名 这只是一种简单的代换 字符串中可以含任何字符 常数或表达式 例8 3 中的字符串就是一个表达式 预处理程序对字符串不作任何检查 因此 这个字符串的正确与否程序员要注意把握 2 宏定义不是说明或语句 在行末不必加分号 如果不小心加上一个 那么这个 将一同参加替换 读者可以将 例8 2 的宏定义语句加上 编译时将报错 编译无法通过 3 习惯上宏名都用大写字母来表示 一般来说 宏名用大写字母表示 以便于与变量区别 但这并不意味着宏名不能用小写字母 只是为了与变量区别而已 4 宏定义必须写在函数之外 其作用域为宏定义命令起到源程序结束 若不希望宏定义命令到源程序结束时终止 可以在需要终止其作用域的地方用 undef命令 5 如果宏名在程序中被引号括起来 则不进行宏替换 下面就是这样一个例子 59 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 带参宏定义的一般形式为 define宏名 形参表 字符串在宏定义中的参数称为形式参数 在宏调用中的参数称为实际参数 对带参数的宏 在调用中 不仅宏要展开 而且要用实参去替换形参 带参宏调用的一般形式为 宏名 实参表 例如 defineQ x y x x y 2 x y y 宏定义 a Q 3 5 宏调用 在宏调用时 用实参去代替形参x 经预处理宏展开后语句为 a 3 3 5 2 3 5 5 带形参的宏 具有较强的功能 但也有很多地方需要读者注意 稍不小心 可能就会出错 下面结合读者容易忽略的地方通过应用实例介绍带形参的宏定义的正确应用 60 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 例8 3 利用带参数的宏实现简单函数的功能 程序代码 defineMAX x y x y x y 带参宏定义 实现求两个数中较大的 includevoidmain inta b max scanf d d 61 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 在这个例子中 要注意如下问题 1 带参宏定义中 宏名和形参表之间不能随便加入空格 否则将空格以后的字符都作为替代字符串的一部分 例如把上例中的宏定义 defineMAX x y x y x y写成 defineMAX x y x y x y将被认为是无参宏定义 宏名定义MAX代表字符串 x y x y x y 宏展开时 宏调用语句 max MAX a b 将变为 max x y x y x y a b 这显然是错误的 实际上 在上例中的宏定义语句中插入空格后 编译将失败 62 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 2 在带参宏定义中 形式参数不分配内存单元 因此不必作类型定义 而宏调用中的实参有具体的值 要用它们去代换行参 因此必须作类型说明 读者要注意这与函数的区别 在函数原型的定义中 要定义形参的数据类型 而且函数调用过程中形参和实参是两个不同的量 各有自己的作用域 调用时要把实参值赋予形参 进行 值传递 而在带参宏中 只是符号代换 不存在值传递的问题 3 在宏定义中 括号的使用要注意 不同位置的括号 往往效果不一样 下面举例说明宏定义中括号的作用 63 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 例8 4 宏定义中括号的使用问题举例 程序代码 defineQA x y x y defineQB x y x y includevoidmain inta 3 b 4 m n m QA a 1 b 2 n QB a 1 b 2 printf m d nn d m n 64 8 1宏定义 define 2 带参有宏定义 1 不带参的宏定义 4 宏展开与函数的调用是不同的 函数调用时要把实参表达式的值求出来再传递给形参 而宏代换中对实参表达式不作计算 当作字符串 直接地照原样代换 函数调用是在程序运行时处理的 分配临时的内存单元 而宏展开则是在编译时进行的 在展开时并不分配内存单元 不进行值的传递处理 也没有 返回值 的概念 函数中的实参和形参都要定义类型 二者的类型要求一致 而宏不存在类型问题 宏名无类型 它的参数也无类型 65 8 2文件包含 include 所谓 文件包含 处理是指一个源文件可以将另外一个源文件的全部内容包含进来 即将另外的文件包含到本文件之中 C语言提供了 include命令用来实现 文件包含 的操作 一般形式为 include 文件名 或 include在程序设计中 文件包含是很有用的 有些公用的符号常量或宏定义等可单独组成一个文件 在其他文件的开头用包含命令包含该文件即可使用 这样 可避免在每个文件开头都去书写那些公用量 这样可以节省时间 减少出错 对于C系统提供的标准库函数 也可以通过文件包含使之包含到当前的程序里 从而实现库函数的调用 例如在前面章节中已经用到的文件包含处理 66 8 2文件包含 include 对文件包含命令还要说明以下几点 1 包含命令中的文件名可以用双引号括起来 也可以用尖括号括起来 例如以下写法都是允许的 include stdio h include但是这两种写法在文件的路径搜索的顺序上有区别的 使用尖括号 表示在包含文件路径中去查找 包含路径是由用户在设置环境时设置的 而不在源文件路径去查找 如果没有找到指定的文件 就到包含路径中去查找 用户编程时可以根据自己文件所在的路径来选择某一种命令形式 2 文件包含命令每行写一条 只能写一个文件名 结尾不加 被包含的文件必须是源文件而不能是目标文件 文件名可以任意 但通常以 h 作为后缀 被包含文件通常放在包含文件的头部 因此被包含文件常被称为 头文件 3 一个 include命令只能指定一个被包含文件 若有多个文件要包含 则需用多个 include命令 67 8 2文件包含 include 4 如果文件file1包含文件file2 而在文件file2中又要包含文件file3的内容 则可在文件file1用两个 include命令分别包含文件file2和文件file3 而且文件file3要出现在文件file2之前 即在文件file1 c中定义 include include这样file1和file2都可以用file3的内容 5 在一个被包含文件中又可以包含另一个被包含文件 即文件包含是可以嵌套的 6 被包含文件 如file2 h 与其所在文件 如file1 c 经编译预处理后已成为同一文件 因此 如果file2 h中有全局静态变量 它在文件file1 c中有效 不必用extern声明 68 第9章文件 C语言程序设计 CProgramming 辽宁科技大学 69 1 文件的概念 文件的打开 关闭 2 文件的读写函数及使用方法 本章学习目标 70 9 1C文件概述 9 2文件的打开与关闭 9 3文件的读写 9 4文件定位函数 9 5文件出错检测函数 71 9 1C文件概述 计算机术语中的 文件 的含义比较广 泛指存储在外部介质上数据的集合 从不同的角度可对文件作不同的分类 普通文件和设备文件按用户的角度可将文件分为普通文件和设备文件两种 普通文件又可分为程序文件和数据文件 前面各章我们多次使用的源文件 目标文件 可执行程序等被称作程序文件 程序中所需输入的数据和程序运行输出的数据构成的文件被称作数据文件 本章所介绍的文件是指数据文件 设备文件是指与主机相联的一切能进行输入和输出的终端设备 如显示器 打印机 键盘等 在操作系统中 把外部设备也看作是一个文件来进行管理 把它们的输入 输出等同于对磁盘文件的读和写 通常键盘被定义为标准输入文件 显示器被定义为标准输出文件 前面经常使用的scanf getchar函数 printf putchar函数就属于这类输入输出 1 C文件的分类 2 文件脂针 72 9 1C文件概述 ASCII码文件和二进制码文件在C语言中 文件可以看作字节的序列 按文件内数据的组织形式可将文件分为ASCII码文件和二进制码文件两种 ASCII码文件也称为文本文件 这种文件在磁盘中存放时每个字符对应一个字节 用于存放字符对应的ASCII码 二进制文件是按二进制的编码方式来存放文件的 它把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放 例如1234为普通的整型数据 若将其存入ASCII码文件中 则是分别以 1 2 3 4 这四个字符的ASCII码值存入文件的 因此它占4个字节 1 C文件的分类 2 文件脂针 73 9 1C文件概述 ASCII码文件的存储形式 1 C文件的分类 2 文件脂针 二进制文件的存储形式 74 9 1C文件概述 缓冲文件系统和非缓冲文件C的文件系统可分为缓冲文件系统和非缓冲文件系统两类 缓冲文件系统 系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区 用缓冲文件系统进行的输入输出又称为高级磁盘输入输出 非缓冲文件系统 系统不自动开辟确定大小的缓冲区 而由程序为每个文件设定缓冲区 用非缓冲文件系统进行的输入输出又称为低级输入输出系统 前者功能十分强大 为用户提供了很多方便 后者则直接依赖于操作系统 缓冲文件系统输入输出称为标准输入输出 标准I O 非缓冲文件系统输入输出称为系统输入输出 系统I O 非缓冲文件系统只以二进制方式处理文件 使程序的可移植性降低 因此ANSIC标准采用缓冲文件系统 1 C文件的分类 2 文件脂针 75 9 1C文件概述 在缓冲文件系统中 每个被使用的文件都在内存开辟一个区域 用来存放文件的相关信息 如文件名 文件状态和文件当前位置等 这些信息保存在一个结构体变量中 该结构体类型是系统定义的 系统为其取名为FILE TurboC在stdio h文件中有以下的文件类型声明 typedefstruct shortlevel 缓冲区 满 或 空 的程度 unsignedflags 文件状态标志 charfd 文件描述符 unsignedcharhold 如无缓冲区不读取字符 shortbsize 级冲区的大小 unsignedchar baffer 数据缓冲区的位置 unsignedar curp 指针 当前的指向 unsignedistemp 临时文件 指示器 shorttoken 用于有效性检查 FILE 2 文件指针 1 C文件的分类 76 9 1C文件概述 语言中用一个指针变量指向一个文件 这个指针称为文件指针 通过文件指针就可对它所指的文件进行各种操作 定义说明文件指针的一般形式为 FILE 指针变量标识符 例如 FILE fp fp是一个指向FILE类型结构体的指针变量 表示fp是指向FILE类型结构体的指针变量 通过fp即可找存放某个文件信息的结构体变量 然后按结构体变量提供的信息找到该文件 实施对文件的操作 有几个文件就可以设几个FILE类型的指针变量 习惯上把fp称为指向一个文件的指针 2 文件指针 1 C文件的分类 77 9 2文件的打开与关闭 文件在进行读写操作之前要先打开 使用完毕要关闭 打开文件 就是建立文件的各种相关信息 并使文件指针指向该文件 可以对文件进行操作 关闭文件则是断开指针与文件之间的联系 禁止再对该文件进行操作 C语言用fopen函数实现打开一个文件 其调用的一般形式为 文件指针名 fopen 文件名 使用文件方式 其中 文件指针名 必须是被说明为FILE类型的指针变量 文件名 是被打开文件的文件名 是字符串常量或字符串数组 使用文件方式 是指文件的类型和使用方式 1 文件的打开 2 文件的关闭 78 9 2文件的打开与关闭 例如 FILE fp 定义fp为文件指针变量 fp fopen file1 r 以只读方式打开file1 表示在当前目录下打开文件file1 只允许进行 读 操作 fopen函数返回指向file1文件的指针并赋给fp 这样fp就和文件file1相联系了 或者说 fp指向file1文件 可以看出 在打开一个文件时 通知给编译系统以下3个信息 需要打开的文件名 也就是准备访问的文件的名字 使用文件的方式 读 还是 写 等 让哪一个指针变量指向被打开的文件 1 文件的打开 2 文件的关闭 7
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 深度学习和影像组学模型在预测胃癌术前浆膜侵袭中的价值
- 有机肥-灌溉协同对民勤绿洲土壤性质与南瓜提质增效的调控效应
- 混凝土外加剂使用管理方案
- 防腐保温施工方案的技术论证与优化方案
- 大班游戏活动中幼儿同伴冲突的教师介入行为研究
- 六妹羊肚菌野生种质驯化栽培评价及原生质体融合研究
- 考点攻克人教版八年级《力》综合训练试题(含详解)
- 社区环境美化整治方案
- 考点攻克苏科版八年级物理下册《力》重点解析练习题(含答案详解)
- 园林施工环境保护方案
- 可靠的出租吊篮施工方案
- (2025年标准)分包意向协议书
- 2025食品经营考试题及答案
- 炼钢厂工艺技术规程
- (2025年标准)订婚双方协议书
- 标本运送基础知识培训课件
- 针灸技术操作规范
- 外来施工人员安全教育培训考试试卷
- 脐静脉置管新技术申报
- 【MOOC答案】《3D工程图学》(华中科技大学)章节作业慕课答案
- 2025年司炉工考试题库及答案
评论
0/150
提交评论