第八章-文件与输入输出PPT课件_第1页
第八章-文件与输入输出PPT课件_第2页
第八章-文件与输入输出PPT课件_第3页
第八章-文件与输入输出PPT课件_第4页
第八章-文件与输入输出PPT课件_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

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

文档简介

第八章文件与输入输出 文件概念C程序中的文件使用结合介绍计算机及程序中一些相关问题和概念C语言标准库中的输入输出函数输入输出中的格式控制问题交互式程序的概念和相关问题 8 1文件概念输入输出和文件功能解决程序处理的数据来源和结果的保存问题 程序里的变量至多存在到程序结束 程序中积累的信息不能通过变量带到下次执行程序启动时OS为其分配存储 程序结束后该存储区可能分配给其他程序内存的特性 关机后存储其中的数据立刻消失为 持续 保存数据 必须借助外存 磁盘 磁带等语言需提供访问和使用外存的能力 文件是外存数据组织的基本单元 外存数据组织在目录 文件结构中 目录是子目录和文件的集合 文件是封装的数据体 目录 文件通过名字使用 与外存交换信息主要就是访问文件 从程序向外送信息是输出 由外部取信息是输入 OS通常把所有IO对象都统一到文件的概念 包括外存文件和各种IO设备 键盘 显示器 打印机等 键盘 显示器等设备也看作文件 给定 文件名 有关操作都通过相应的文件名实施 IO工作繁杂琐碎 依赖于运行环境 语言需处理有关问题 屏蔽细节 以利编程 是程序语言设计的难点 C语言本身无支持IO的结构或者机制 通过库提供IO具体C系统可提供自己的IO功能 ANSIC把IO纳入标准库 以提高可移植性 标准库IO基于文件概念 定义了相关数据结构和一组IO函数 文件IO采用流概念 IO的对象是文件 为与文件交换信息就需要与之建立联系 流就是这种联系 要从文件输入 需要创建与文件关联的输入流 向文件输出要创建输出流 还可能创建输入输出流建立联系 创建流 的操作称作打开文件 文件打开后就可以对它操作 一个文件不再用时可以切断联系 撤消对应的流 称为关闭文件打开 关闭是文件处理的基本操作 流分为两类 正文流 字符流 和二进制流 正文流 文件是字符行的序列 一行包含0个或多个字符 每行最后有换行符 n 正文流适合一般IO 包括与人交互的IO 二进制流 把文件看成字节的序列 二进制流操作保证信息写入文件后按同样方式读回 内容不会改变主要用于程序内部数据的直接保存和装入 在保存装入大批数据时速度快 避免转换引起的信息损失通过二进制流保存的文件不适合人阅读 流通过特殊数据结构实现 标准库定义了一个类型FILE 其具体定义由实现确定 FILE中存储与流操作 IO文件 有关的信息文件打开操作返回一个指向FILE的指针 文件指针 代表所建流对流的操作都通过这种FILE指针进行可以认为文件指针就是流的具体体现 C标准库提供一套函数 包括流创建 打开文件 撤消 关闭文件 文件读写 通过流对文件读写 等 程序启动时自动建立三个文件指针 标准输入流stdin标准输出流stdout标准错误流stderrstdin与OS标准输入连接stdout与标准输出连接stderr通常直接与显示设备连接 不能重新定向标准输入输出操作getchar scanf putchar等都是对这些流 stdin stdout 进行的 标准库采用缓冲式IO 外存 磁盘 磁带等 速度慢 用成块方式传递数据 程序用数据的方式不同 为缓和两者差异 缓冲式IO用一块存储区 缓冲区 作为文件与程序的中介 打开文件时为流建立缓冲区 一般通过动态存储分配 文件与程序间数据传递都通过缓冲区进行 文件关闭时释放流缓冲区 虽然程序与文件间有缓冲区 但操作中看不到它的影响 透明性 程序就像是直接在与外存打交道 透明性 思想在计算机领域里非常重要 是许多设计的基础 在许多领域里都能够看到 例如网络传输 数字电话等等 8 2文件的使用 通过重新定向可以将文件作为IO对象 把与标准设备 键盘 显示器 连接的标准流转连到指定文件这种做法有很大局限性 形成的定向在程序执行中不能改变无法使用多个文件 只有流stdin和stdout 为在程序中方便地使用文件 需要利用标准库的文件操作函数 通过建立输入输出流的方式使用文件 文件的打开和关闭fopen打开文件 返回FILE指针 通过这种指针可进行各种文件操作 原型 FILE fopen constchar filename constchar mode filename是文件名 mode指明文件打开方式 基本方式 r 按读方式打开文件 找不到文件则失败 w 按写方式打开 文件已有则丢弃原内容 a 按添加方式打开或创建文件 在已有部分之后写 r 读更新方式 可以对文件读或写 w 写更新方式 可写读 如文件存在则丢弃原内容 a 添加并可读方式 从文件尾接着写 用二进制方式时加b rb wb a b 以读写方式打开文件 使用时有特殊规定若文件打开出错 fopen返回空指针值 关闭文件用函数fclose 原型 intfclose FILE stream 关闭前将输出流缓冲区的数据送入文件 而后释放缓冲区 正常时返回0 否则返回EOF 能同时打开的文件数有限 文件用完后应关闭流程序退出时所有文件将自动关闭 使用文件的基本编程模式 FILE fp fp fopen myfile abc r if fp NULL 处理文件打不开的情况 可能return 对文件的操作 fclose fp 文件操作都是与外部打交道 能否正常完成 依赖于外部环境当时的情况 所以 fopen后应检查函数返回值 确保后续操作有效 若想通过交互输入文件名 可采用如下程序模式 intmain charfname 128 注意越界危险 FILE fp printf Filename scanf 127s fname 读入不超过127字符 if fp fopen fname r NULL 或者 while 1 printf Filename scanf 127s fname if fp fopen fname r NULL break printf Filenameerror n 文件输入输出函数字符IO函数字符IO函数fgetc和fputc的原型 intfgetc FILE fp 从流fp读字符intfputc intc FILE fp 向fp写字符返回该字符 遇文件结束fgetc返回EOF 出错时都返回EOF 返回值是int类型 原因与getchar相同 getc和putc与上述函数类似 用宏实现标准流的字符读写函数通常如下定义 definegetchar getc stdin defineputchar c putc c stdout 程序cat 将命令行参数作为文件名 顺序复制到标准输出 无文件名时由stdin向stdout复制 voidfilecopy FILE ifp FILE ofp 文件复制 intc while c getc ifp EOF putc c ofp intmain intargc char argv FILE ifp char name argv 0 if argc 1 无参数情况 filecopy stdin stdout return0 while argv NULL if ifp fopen argv r NULL printf s can topeninputfile s n name argv else filecopy ifp stdout fclose ifp return0 格式化IO函数文件格式化IO函数fscanf fprintf的原型 intfscanf FILE stream constchar format intfprintf FILE stream constchar format 功能 使用与scanf printf类似 增加了FILE 参数 按格式串做数据形式的转换 对指定流操作 三个圆点 是特殊参数描述形式 表示参数数目可变 定义这种函数用 第11章有介绍编译时不检查对应 的实参个数 不做类型转换 不检查错误 不产生错误信息 调用时 格式串后的参数在类型和个数上必须与格式串的转换描述一致 行式IO函数 以行为单位进行输入或输出 行IO函数需要用字符数组存放输入或者输出字符序列 char fgets char buf intn FILE s buf为字符数组 由流s读至多n 1个字符存入buf 遇换行符结束 换行符存入数组 最后放 0 正常结束时返回buf 文件结束或出错时返回空指针 buf应至少能容纳n个字符 intfputs constchar buf FILE s 将buf表示的字符串送到流s 输出的最后不向流中添换行字符 串里可以包含换行 正常完成时返回非负值 出错时返回EOF值 例 文件保存了一批单价和数量数据 写程序通过命令行参数提供文件名 最终输出货物的总货值 设文件数据以单价 数量形式成对出现 用fscanf读入 定义函数nextentry完成一对数据的读入 它在发现所有数据处理完毕后返回0值 这里没处理数据出错情况 可补充修改 doublenextentry FILE fp doublepr num intn fscanf fp lf lf intmain intargc char argv doubletotal 0 0 x FILE ifp if argc 1 缺参数 产生错误信息 printf Missingfilename Stop n return1 if ifp fopen argv 1 r NULL printf Can topen s Stop n argv 1 return2 while x nextentry ifp 0 0 total x printf Totalprice f n total flose ifp return0 二进制流和直接IO函数格式化函数fscanf fprintf工作时 要做内外部形式之间的转换 如int内部是二进制序列 实际输出的是一串数字字符 格式化输入函数也要做转换数据转换要耗费时间 如IO对象是人 就必须进行转换 若是要输出到文件 以便后来取回程序使用 转换就没必要了转换还可能丢失信息 尤其是对浮点 double等 数据 输出后再输入可能产生误差 为解决这些问题 标准库提供二进制流和直接IO函数 如果程序里需要把保存起一些内部信息 以便随后使用或下次执行程序时再用 合适方式是用二进制流 直接将内部数据保存到文件里 直接输入输出函数 size tfread void p size tsize size tnum FILE s size tfwrite constvoid p size tsize size tnum FILE s fwrite向s输出num个大小为size的数组元素 p指定数据的起始位置 各数据项顺序写入指定文件 fread由s读num个大小size的元素 p应指数组 数组元素类型应与size一致 数组大小至少为num 直接存入文件后以同样方式读回 得到的数据不变 fwrite返回输出的元素个数 小于num说明出错fread返回实际读入元素的个数对二进制流 应该用feof检查是否遇到文件结束 直接输入输出的例 设datatable是所用数组类型 enum TLEN 100 typedefdoubledatatable TLEN datatablem n 设计算出的值存在m 要存入文件 设二进制输出流为msave 保存m的全部信息 fwrite m sizeof double TLEN msave 如果需要把以前保存的数据装入数组n 数据的形式符合要求 已为此建立了流msaved 下面调用完成输入并把函数返回值存入变量num num fread n sizeof double TLEN msaved 8 3标准输入输出与格式控制 标准IO的行式输入输出对标准输入 输出流也有行式IO函数 原型 char gets char s intputs constchar s gets读一行到s 用 0 代行尾 n 并返回s s应是字符数组 出错或遇文件结束返回NULLputs将字符串s以及一个换行符输出 正常完成返回非负值 出错返回EOF用gets时应注意数组越界 无法限制写入长度 应选用足够大的数组 一般使用形式 chars 256 if gets s NULL if puts s EOF 应检查和处理操作未正常完成的情况 gets函数无长度控制 成为许多系统的安全漏洞 建议用fgets buf len stdin 或者scanf 格式串里写 ns 其中的n为长度限制 代替gets 输入格式控制以scanf为例介绍标准输入函数的格式控制scanf的原型 intscanf constchar fmt scanf将输入流看成空白字符分隔的字段 读入过程就是对这些字段的顺序处理 fmt指挥scanf进行转换 成功转换得到的值赋给对应变量 地址来自参数 scanf处理完格式串或遇转换失败时结束 返回所完成的转换项数 fmt里各种字符的意义与作用 空白字符 空格 制表符 要求scanf跳过输入中遇到的空白字符 空格 换行符 制表符 普通字符 非转换描述的非空白字符 要求scanf将它与输入流下一个非空白字符匹配 字符相同时匹配成功 否则转换失败转换描述 一个转换描述刻画对流中下一字段的转换方式 以字符 开始 到转换字符结束 转换描述 之后可有 表示只匹配不赋值 长度描述 整数 指定输入字符个数 赋值目标长度指示h l或L 最后是转换字符 转换顺利完成时结果赋给参数所指变量 无 时 若有长度描述就以指定个数的字符为字段 有星号 如 s 6d等 时所匹配的东西不赋值 直接丢掉 转换字符的意义 所要求实际输入 对应参数类型 d十进制形式的整数 int i整数 可为十 八或十六进制表示 int o八进制整数 可无先导字符0 int u无符号十进制整数 unsigned x十六进制整数 可无先导0 x或0X int c字符 指定输入宽度可输入多字符到字符数组 不跳过空白 读入多字符后不加 0 char s非空白字符序列 可有长度限制 在字符数组最后附加 0 做成字符串 char e f g符合C语言规定形式的浮点数 float p指针值 形式与printf p 输出一致 用于把由printf输出的指针值读回 void n向对应参数中写入本次函数调用执行到此已读的字符个数 不实际读入也不计转换项数 int 与所列字符的最长序列匹配 写入数组并附 0 用 表示匹配串可含 char 与不含所列字符的最长序列匹配 写入数组并附 0 表示不含 char 与输入流中的字符 匹配 不赋值 转换字符d i o u x前面可以标明目标长度 h表示赋值目标为short l表示赋值目标为long转换字符e f g前加l表示目标是double L表示是longdouble加了这些字符 scanf将按指定类型构造和赋值未做转换前出错或者遇到文件结束时返回EOF其他情况下返回执行中完成转换的项数 返回0表示第一个转换失败 例 设scanf当时要处理转换描述串 ld scanf读入并丢掉空白符号 可无 然后做匹配若遇到的非空白字符不能看作数 则匹配失败否则就逐个读入字符 直至遇到第一个非数字字符将读入的正负号及数字字符序列做成一个长整数 赋给指定的变量从这个转换描述串之后继续处理格式串 如果转换失败 引起失败的字符仍在流中 下次调用输入函数将先读到这个字符 写好输入需要考虑许多细节 较麻烦 原因 输入描述与外部打交道的方式 应根据外部提供的信息决定工作方式 外部情况不受写程序的人控制 写好处理输入的程序片段 需要考虑外部的各种可能 适当处理有关情况 难说 正确 只能说 适当 外部输入不满足程序要求时 应提供一些 信息 写输入时总要做一些假设 考虑一些问题 书上有一些例子和说明 输出格式控制以printf为例 其他格式化输出函数同 原型 intprintf constchar fmt fmt里的非转换描述直接输出根据转换描述顺序转换各实参 结果插入在fmt里相应位置 形成整个输出出错时返回负值正常完成返回实际输出的字符个数 转换描述从 开始到转换字符止 中间可有若干字符 顺序地可以有如下成分 都可缺 1 标志字符 下面字符可以以任意顺序出现 转换结果在字段范围内左对齐 数值前面总输出正负号空格转换得到的首字符不是正负号时输出一个空格0若数值输出不能填满字段 前面全填0 指定另一种形式 对转换符o的数值前加0 x和X的非0结果前加0 x或0X e E f g G输出时总写小数点 g和G 不去掉最后的0 2 一整数 最小宽度 转换结果至少占这么宽 可更宽 若得到的序列不够 在左边 或右边 有 时 填空格 数值在有0标志时在数字序列左边填0 3 圆点及另一数 对字符串参数表示最大输出字符数 对e E f表示小数点后数位 对g G表示有效数位 对整数表示最小输出数字个数 不够时左边添0 4 目标长度字符h l或L h和l用于整参数 h指short或unsignedshort l指long或unsignedlong L指longdouble 字段宽度 精度可写 表示值由参数取得 提供值的参数必须是int 转换字符 所要求参数类型和实际输出形式 d i带符号的十进制形式整数 int o无符号八进制表示的整数 无先导0 int x X无符号十六进制整数 无先导0 x或0X 用x时十以上数字用abcdef 对X用ABCDEF int u无符号十进制整数 int c字符 转为unsignedchar输出 int s字符序列 从参数所指位置直到字符 0 或者达到字段的指定宽度为止 char f一般实数形式 mmm ddd 小数点后位数由精度描述定 默认6 精度为0不输出小数点 double e E科学记数法 m dde xx或 m ddE xx 小数点后位数由精度描述确定 默认6 精度为0时不输出小数点 double g G灵活形式 指数小于 4或大于等于精度描述时用 e或 E形式输出 否则用 f形式输出 末尾的0或小数点不输出 double p指针 用具体实现确定的形式 void n把本次函数执行到此已输出的字符数写进参数 处理这个 转换描述 进行不进行任何转换 int 输出字符 无转换 通过字段宽度和精度控制 对齐等 灵活运用转换描述可形成所需输出形式 几个实例 16 8lf 10 6f 20 12e 010ld 7s 格式串里可用星号表示字段宽度和精度 实际宽度精度由参数取得 这个功能使我们可以在程序里通过程序机制控制输出格式 例 printf s d n Num width num 先输出一个字符串 然后输出num的值 假定num是整型变量 字段宽度由 int变量 width值确定 字符串作为格式化IO的对象文件是字节序列 正文流是字符序列 从文本流输入就是从中读取一段 输出的情况相反 字符串也是字符序列 可作为IO对象标准库有两个以字符串为对象的格式化IO函数 输入函数从字符串读并转换 结果赋给指定变量 输出函数实现相反过程 把输出存入字符数组并做成字符串函数原型是 intsscanf char s constchar fmt intsprintf char s constchar fmt 与对应格式化IO函数相同 只是对象是字符串 出错处理输出出错信息是希望显示到屏幕供人读 通过stdout不合适 输出定向到文件也使出错信息送到文件 送到标准错误流stderr的信息不受定向影响 改造前面程序cat 只需要改动一个语句 fprintf stderr s can topeninfile s n name argv 文件错误检查 intferror FILE stream IO出错时设置相关流的出错标志变量 ferror检查流的出错标志 当stream的状态变量设置时返回非0 错误标志复位 清除 函数voidclearerr FILE stream 标准库错误处理 为检查程序执行中出错 库提供了一些机制 每个C系统定义了一组错误编号 0表示无错 其余值表示各种错误 一些函数出错时自动给状态变量errno设错误编号 还定义了相应的信息串 见 打印当时错误信息 voidperror char s 检查当时错误编号 perror调用之前的最近错误 把对应信息串送到stderr 输出形式 字符串s冒号错误信息串换行 例 设有一组文件 每个文件存一批实数 写程序由用户取得文件名 对各文件中的数值求平均值输出 8 4程序实例 程序功能分解 从文件读数值求平均值并输出是一项独立工作 定义为函数 原型设计为 voidaverage FILE fp char fname 它要求的参数一个打开的输入文件指针和文件名 由主函数处理取得文件名并打开文件的工作 综合上面考虑 average可定义为 voidaverage FILE fp char fname doublex sum 0 0 intl 0 n 0 m c printf nFile s n fname whlie m fscanf fp lf 主函数确定循环终止方法 下面用文件结束符 给文件结束信号 组合键Ctrl Z 程序结束 intmain void charname 128 FILE fp while 1 printf Filename Ctrl Ztoend if scanf 127s name EOF break if fp fopen name r NULL printf Can topen s n name else average fp name fclose fp printf Bye n return0 主函数的另一版本 要求用户通过命令行参数提供文件名 命令行没有文件名就什么也不做 intmain intargc char argv FILE fp while argv NULL if fp fopen argv r NULL printf Can topen s n argv else average fp argv fclose fp printf Bye n return0 例 考虑一个背英语单词程序 基本循环是显示一个中文词 要求用户输入对应的英文单词并给以评判 程序运行中应保存一对对中文 英文词 最好将单词存在文件里 启动程序后将单词装入 需要用文件IO 为简化输入 应该先设计好单词文件的格式 例如每行里放一对英文词和中文词 英文在前中文在后 空格分隔 文件格式设计很重要 单词文件可能不止一个 用户通过交互提供文件名 要求程序装入文件内容 而后交互练习 中文和英文词用字符串形式存入一个两维字符数组 可以有下面定义 WDNUM 中英文词数 WDLEN 单词存储数组长度 ROUND 一轮练习的次数 enum WDNUM 1000 WDLEN 32 ROUND 20 charwds WDNUM 2 WDLEN defineENGLISH i wds 2 i defineCHINESE i wds 2 i 1 定义宏是为写程序方便 已经可以定义main intmain void charfn 256 FILE fp intterms do getnstr Wordfilename 256 fn if fp fopen fn r NULL printf Wrongfilename else terms readfile fp WDNUM wds fclose fp if terms 0 continue wordgame terms wds ROUND while next wordfile return0 getnstr从标准输入读一段字符 遇空白字符结束 voidgetnstr charprompt intlim charbf intc i 0 printf s prompt while i lim 1 本函数认为输入行里有用信息就是一个字段 由空白界定 其他信息都应抛弃 读入的字符存入数组bf 做成字符串形式 注意检查越界问题 next是前面简单函数的推广 它输出提示串参数 通过读入的y或者n确定返回真假值 本函数只在遇到y时返回1 其余情况都返回0 intnext chars intc printf Next s y n s do c getchar while isspace c 读到一个非空白字符 while getchar n 吃掉本行剩余字符 if c y c Y return1 elsereturn0 这两个函数都可能用到许多程序里 wordgame采用随机选择策略 有许多改造可能 voidwordgame intterms intrd charwds WDLEN intn i charwd WDLEN do for i 0 i wd WDLEN if strcmp wd ENGLISH n 0 printf Ok n elseprintf Wrong Itis s n ENGLISH n while next Round readfile采用按行输入方式 读入一行后分析输入并复制到指定数组 以便必要时生成错误信息 intreadfile FILE fp intlim charwds WDLEN charline 256 p intl 0 n 0 while n lim

温馨提示

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

评论

0/150

提交评论