欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > PPT文档下载
     

    程序设计实习第十八讲输入输出流和文件操作.ppt

    • 资源ID:2250249       资源大小:299.01KB        全文页数:64页
    • 资源格式: PPT        下载积分:8
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要8
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    程序设计实习第十八讲输入输出流和文件操作.ppt

    程序设计实习 第十八讲 输入输出流和文件操作,主讲教师:田永鸿 yhtianpku.edu.cn http:/ai.pku.edu.cn/cpp2008/tyh/tyh.htm http:/idm.pku.edu.cn/jiaoxue-CPP/cpp08.htm 2008年5月12日,2,上节内容回顾,虚函数和多态 纯虚函数和抽象类 多态的实现:虚函数表 虚函数的访问权限 构造函数和析构函数中调用虚函数 虚析构函数,3,课堂问题(1),判断对错并说明理由 抽象基类中的所有virtual函数都必须声明为纯virtual函数; 声明某个类为virtual,该类就成为抽象类。 如果基类声明了一个纯virtual函数,派生类只有实现该函数才能成为具体类。 下面的定义是否正确,该如何改正? class base string name() return basename; virtual void print(ostream ,class derived: public base void print() base:print(os); os“ ”mem; private: int meme; 同时,基类及派生类也应该定义构造函数和析构函数。 base:base(string name):basename(name) ; base:base() ; derived: derived(string name, int val): base(name), mem(val) ; derived: derived() ;,4,课堂问题(2),下列关于重载函数和虚函数的辨析描述中,理解不正确的是: 重载函数处理的是同一类层次上的同名函数问题,而虚函数处理的是不同派生层次上的同名函数问题。 重载函数要求函数有相同的函数名称,不管返回值类型是否相同,但参数序列必须不同,而虚函数则要求函数名、参数序列和返回值类型完全相同。 重载函数和虚函数都必须是类成员函数,但重载函数一般功能类似,而虚函数一般功能有所不同,甚至基类虚函数的函数体可以为空,具体功能在派生类中添加。 重载函数在编译时,根据传递参数序列的不同,确定具体调用表现多态性,而虚函数在运行时,根据基类指针或引用所指向对象的不同,确定具体调用表现出多态性。,5,课堂问题(3),请写出运行时输出的结果 class A public: A( ) virtual void func() cout “A:func“ endl; A( ) virtual void fund( ) cout “A:fund“ endl; ; class B: public A public: B ( ) func( ) ; void fun( ) func( ) ; B ( ) fund( ); ;,class C : public B public : C( ) void func( ) cout “C:func“ endl; C() fund( ); void fund() cout “C:fund“ endl; ; main() C c; ,A:func C:fund A:fund,6,内容提要,输入输出流 文件操作 作业,7,输入输出流,流的概念模型 C+中与流操作相关的类及其继承关系 输入输出流对象: cin, cout, cerr, clog 输出流 输入流 无格式输入输出 流操纵算子 流格式状态,8,流的概念模型,流 - 可以看作一个无限长的二进制数字序列 通过读写指针进行流的读和写(以字节为单位),将流上的数据读进变量x,将y的值写入流,y,x,9,流的概念模型,输出流 可以看作一端无限,另一端通过写指针不停地向后写入新内容的单向流,,写指针,10,流的概念模型,输入流 可以看作一端无限,另一端通过读指针不停地从流中读取新内容的单向流,读出的内容从流中删去。,读指针,11,有格式读写和无格式读写,有格式读写,以某种数据类型为单位读写 例如:读一个整数,写一个浮点数等; 无格式读写,以字节为单位读写,不区分其中的内容 例如:读20个字节,写50个字节等;,12,缓冲区刷新,向输出流中写数据时,通常是先向缓冲区中写,当缓冲区写满时,才真正向输出流写 也可以通过函数在程序中主动将缓冲区内容写入输出流。,13,C+中与流操作相关的类及其继承关系,ios,istream,ostream,ifstream,iostream,ofstream,fstream,14,标准流对象,输入流对象 cin 与标准输入设备相连 输出流对象: cout 与标准输出设备相连 cerr 与标准错误输出设备相连,非缓冲输出 clog 与标准错误输出设备相连,缓冲输出,15,输出流,流插入运算符 cout “Good morning!n”; 不刷新缓冲区 cout “Good”; 不刷新缓冲区 cout “morning!”; 不刷新缓冲区 cout endl; 刷新缓冲区 cout flush; 刷新缓冲区 cout显示内容的时候会先将欲显示内容存放在缓存区,待刷新的时候才将内容付显,而具有刷新功能的语句为endl或者flush。,16,输出流,输出表达式 cout (47+53); / 将表达式括起来, / 避免优先级冲突。 连续使用流插入运算符 cout “ha ha” (100+100)endl; 相当于 (cout “ha ha”)(100+100)endl;,17,输出流,输出 char * 类型的变量 char *string = “test”; cout (string); / 输出 string的地址 / 0x0042501c - 会变的!,用法:static_cast (a ) 将地址a转换成类型T,T和a必须是指针、引用、算术类型或枚举类型。 表达式static_cast(a), a的值转换为模板中指定的类型T。在运行时转换过程中,不进行类型检查来确保转换的安全性。,18,输出流,用成员函数put输出字符 cout .put(A); put的连续使用 cout .put(A).put(a);,19,输入流,读取运算符 int x,y; cin x; cin y; 或者 cin x y;,20,输入流,读取运算的返回值 重载运算符的定义: istream while(cinx) ,21,输入流,成员函数 cin.get() 读入一个字符(包括空白字符), 返回该字符; char* cin.get(char *buffer, int size, char delim=n ) 或者读size 1 个字符入buffer,或者遇到n; 在buffer最后加0,分隔符留在输入流. char* cin.getline(char *buffer, int size, char delim=n) 或者读size 1 个字符入buffer,或者遇到n; 在buffer最后加0, 分隔符从流去掉. bool cin.eof() 返回输入是否结束标志.,22,输入流,cin.peek(): 返回下一个字符,但不从流中去掉. cin.putback(char ch): 将字符ch放回输入流 cin.gcount():返回上次读入的字节数 cin.ignore( int nCount = 1, int delim = EOF ): 从流中删掉最多nCount个字符,遇到EOF时结束。,23,无格式输入输出,用read, write 进行指定字节数的输入输出 const int SIZE = 80; char bufferSIZE; cin.read(buffer, 20); /cin.get(buffer, 20); cout.write(buffer, cin.gcount(); /gcount返回上次读入的字节数 cout endl; 输入:Using the read,write and gcount member functions 输出:Using the read,write,24,流操纵算子,整数流的基数:流操纵算子dec, oct, hex, setbase 浮点数的精度(precision, setprecision) 设置域宽(setw, width) 用户自定义的流操纵算子,25,流操纵算子,整数流的基数:流操纵算子dec,oct,hex int n = 10; cout n endl; cout hex n “n” dec n “n” oct n endl; 输出结果: 10 a 10 12,26,流操纵算子,浮点数的精度(precision, setprecision) precision是成员函数,其调用方式为: cin.precision(5); setprecision 是流操作算子,其调用方式为: cin setprecision(5); / 可以连续输出 它们的功能相同。,27,流操纵算子,流格式操纵算子setioflags setiosflags(ios:fixed) 用定点方式表示实数 seiosflags(ios:scientific) 用指数方式表示实数 setiosflags(ios:fixed)与seiosflags(ios:scientific)都可以和setprecision(n)合用,其效果分别为:控制小数点右边的数字个数,控制指数表示法的小数位数。 在用浮点表示的输出中,setprecision(n)表示有效位数。 在用定点表示的输出中,setprecision(n)表示小数位数。 在用指数形式输出时,setprecision(n)表示小数位数。 小数位数截短显示时,进行4舍5入处理。 左右对齐输出可用setiosflags(ios:left)和setiosflags(ios:right)实现。 强制显示小数点和符号可用setiosflags(ios:showpoint) 和setiosflags(ios:showpos) 实现。,28,流操纵算子,浮点数的精度(precision,setprecision) double x = 12.3456789, y=12.34; cout setiosflags(ios:fixed) setprecision(6) x endl y endl; 输出为: 12.345679 /小数点后有6位 12.340000,29,流操纵算子,浮点数的精度(precision,setprecision) double x = 12.3456789, y=12.34; long z=1234567 cout setprecision(6) x endl y endl z endl; 输出为: 12.3457 /一共有6位 12.34 / 不到6位 1.23457e+006 /科学计数法,30,流操纵算子,设置域宽(setw,width) 两者功能相同,一个是成员函数,另一个是流操作算子,调用方式不同: cin setw(5); 或者 cin.width(5); cout setw(5); 或者 cout.width(5); 不含参数的width函数将输出当前域宽,31,流操纵算子,设置域宽(setw,width) 例:int w = 4; 输入:1234567890 char string10; 输出:1234 cin.width(5); 5678 while(cin string) 90 cout.width(w+); cout string endl; cin.width(5); 输入操作提取字符串的最大宽度比定义的域宽小1,这是因为在输入的字符串后面必须加上一个空字符。,32,流操纵算子,设置域宽(setw,width) 例:int w = 4; 输入:happy new year char string10; 输出? cin.width(5); while(cin string) cout.width(w+); cout string endl; cin.width(5); 。,happ y new year,33,流操纵算子,设置域宽(setw,width) 需要注意的是在每次读入和输出之前都要设置宽度。例如: char str10; 输入:1234567890 cin.width(5); 输出:1234 cin string; 567890 cout string; cout string endl;,34,流操纵算子,设置域宽(setw,width) 需要注意的是在每次读入和输出之前都要设置宽度。例如: char str10; 输入:1234567890 cin.width(5); 输出:1234 cin string; 5678 cout string; cout string endl; (输出具有同样的性质),35,流操纵算子,用户自定义的流操纵算子 ostream 输出:aa bb,36,流的错误状态,当流中发生格式错误时,设置failbit 当发生导致数据丢失错误时,设置badbit 如果eofbit、failbit、badbit都没有设置,则设置goodbit 成员函数rdstate返回流的错误状态。 成员函数clear把一个流的状态恢复为“好”,如:cin.clear(), 清除cin,并为流设置goodbit。 eof():判断流是否到文件尾,37,流格式状态,自己阅读 V2版的11.7( V5版的15.7 ), 学会设置流格式状态,38,内容提要,输入输出流 文件操作 作业,39,文件操作,数据的层次 文件和流 建立顺序文件 文件的读写指针 有格式读写 无格式读写,40,数据的层次,位 bit 字节 byte 域/记录 Field/Record 例如:学生记录 int ID; char name10; int age; int rank10; 我们将所有记录顺序地写入一个文件,称为顺序文件。,41,文件和流,可以将顺序文件看作一个有限字符构成的顺序字符流,然后象对cin, cout 一样的读写。回顾一下输入输出流类的结构层次:,ios,istream,ostream,ifstream,iostream,ofstream,fstream,42,建立顺序文件,#include / 包含头文件 ofstream outFile(“clients.dat”, ios:out|ios:binary); /打开文件 ofstream 是 fstream中定义的类 outFile 是我们定义的ofstream类的对象 “clients.dat”是将要建立的文件的文件名 ios:out 是打开并建立文件的选项 ios:out 输出到文件, 删除原有内容 ios:app 输出到文件, 保留原有内容,总是在尾部添加 ios:ate 输出到文件, 保留原有内容,可以在文件任意位置添加 ios:binary 以二进制文件格式打开文件,43,建立顺序文件,也可以先创建ofstream对象,再用 open函数打开 ofstream fout; fout.open(“test.out“,ios:out|ios:binary); 判断打开是否成功: if(!fout)cerr “File open error!”endl;,44,文件的读写指针,对于输入文件,有一个读指针; 对于输出文件,有一个写指针; 对于输入输出文件,有一个读写指针; 标识文件操作的当前位置, 该指针在哪里,读写操作就在哪里进行。,45,文件的读写指针,ofstream fout(“a1.out”,ios:ate); long location = fout.tellp(); /取得写指针的位置 location = 10L; fout.seekp(location); / 将写指针移动到第10个字节处 fout.seekp(location,ios:beg); /从头数location fout.seekp(location,ios:cur); /从当前位置数location fout.seekp(location,ios:end); /从尾部数location location 可以为负值,46,文件的读写指针,ifstream fin(“a1.in”,ios:ate); long location = fin.tellg(); /取得读指针的位置 location = 10L; fin.seekg(location); / 将读指针移动到第10个字节处 fin.seekg(location,ios:beg); /从头数location fin.seekg(location,ios:cur); /从当前位置数location fin.seekg(location,ios:end); /从尾部数location location 可以为负值,47,字符文件读写,int x, y; / 有类型的读写 fin x y; fout x “ “ y endl; 说明: 字符文件的读写本质是将所有类型转为字符串,再将字符串转成各种类型的数据。 所以写出来的是文本格式的文件,可以在记事本中阅读。 因为文件流也是流,所以前面讲过的流的成员函数和流操作算子也同样适用于文件流。,48,二进制文件读写,int x=10; fout.seekp(20, ios:beg); fout.write(reinterpret_cast( 二进制文件读写,直接写二进制数据,记事本看未必正确。,reinterpret_cast(a) 任何指针都可以转换成其它类型的指针,T必须是一个指针、引用、算术类型、指向函数的指针或指向一个类成员的指针。 表达式reinterpret_cast(a)能够用于诸如char* 到 int*。,49,显式关闭文件,ifstream fin(“test.dat”,ios:in); fin.close(); ofstream fout(“test.dat”,ios:out); fout.close();,50,获得文件长度,ofstream fout(“1.txt“,ios:out); char a100000; fout.write(reinterpret_cast(a),100000); fout.close(); ifstream fin(“1.txt“,ios:in); fin.read(reinterpret_cast(a),100000); fin.seekg(0,ios:end); long b = fin.tellg(); cout b endl; fin.close();,51,命令行参数,启动程序运行时可以指定命令行参数 方式一 开始 -运行 -输入cmd,按确定 -dos窗口 可以用 cd 切换当前目录: . cd 子目录 等等 来到程序所在目录,启动程序:myprogram arg1 arg2 或者在任意目录下,启动程序:e:/me/aa arg1 arg2 绝对路径和相对路经的概念 方式二 在vc编程环境中: project - settings-debug -program arguments,52,命令行参数,int main(int argc, char* argv) cout argc endl; for(int i=0; iargc; i+) cout argvi endl; 第一个参数为命令本身, 第二个以后为参数,53,文件目录操作,dir - 列文件及子目录 cd - 当前目录转换 mkdir - 创建目录 . 目录 - 当前目录 目录 - 父目录,54,在程序中得到某个路径下的文件,#include HANDLE f1; / 句炳 WIN32_FIND_DATA fData; /存储文件信息 f1 = FindFirstFile(“e:/teaching/*“,55,在程序中得到某个路径下的文件,while(FindNextFile(f1, ,56,关闭文件查找句炳,HANDLE f1; / 句柄 WIN32_FIND_DATA fData; /存储文件信息 f1 = FindFirstFile(“e:/teaching/*“,57,课堂练习 写成代码,打开图像文件 / 假设是raw格式的正方形图像 8bit/pixel 如果打开失败,处理失败,退出 申请动态数组 如果申请失败,关闭图像文件,处理内存申请失败,退出 将图像数据读入动态数组 关闭图像文件 处理数组,进行二值化 / if pixel 100 pixel=0 else pixel=255 创建新文件 如果创建失败,释放内存,处理创建失败,退出 将新数组写进新文件 释放动态数组 关闭新文件 程序结束,58,内容提要,输入输出流 文件操作 作业,59,作业,书上: 阅读V2版的11.7(或V5版的15.7) 完成练习 V2版的11.12 (或V5版的15.12) 几何形体练习3 以几何形体练习2为基础 在基类中加两个虚函数setfromfile(),printtofile()分别用于文件读写,文件统一后缀“.geo“,在输入文件名时不必输入。向文件输出时注意在每个输出后要输出' '或'n',否则从文件输入时会出错。从文件输入时,只能屏幕输出,输出结果是按周长大小排序的。而从键盘输入时可以选择是屏幕输出还是文件输出,但都是按面积大小排序的。这点区别请注意。 文件压缩,题目描述放在作业网页上。可以迟些(1-2周)交这个作业。,60,强制类型转换运算符,static_cast(a) 将地址a转换成类型T,T和a必须是指针、引用、算术类型或枚举类型。 表达式static_cast(a), a的值转换为模板中指定的类型T。在运行时转换过程中,不进行类型检查来确保转换的安全性。 class B . ; class D : public B . ; void f(B* pb, D* pd) D* pd2 = static_cast(pb); / 不安全, pb可能只是B的指针 B* pb2 = static_cast(pd); / 安全的 . ,61,强制类型转换运算符,dynamic_cast(a) 完成类层次结构中的提升。T必须是一个指针、引用或无类型的指针。a必须是决定一个指针或引用的表达式。 表达式dynamic_cast(a) 将a值转换为类型为T的对象指针。如果类型T不是a的某个基类型,该操作将返回一个空指针。,class A . ; class B . ; void f() A* pa = new A; B* pb = new B; void* pv = dynamic_cast(pa); / pv 现在指向了一个类型为A的对象 . pv = dynamic_cast(pb); / pv 现在指向了一个类型为B的对象 ,62,强制类型转换运算符,const_cast(a) 去掉类型中的常量,除了const或不稳定的变址数,T和a必须是相同的类型。 表达式const_cast(a)被用于从一个类中去除以下这些属性:const, volatile, 和 _unaligned。,class A . ; void f() const A *pa = new A; /const对象 A *pb; /非const对象 /pb = pa; / 这里将出错,不能将const对象指针赋值给非const对象 pb = const_cast(pa); / 现在OK了 . ,63,强制类型转换运算符,reinterpret_cast(a) 任何指针都可以转换成其它类型的指针,T必须是一个指针、引用、算术类型、指向函数的指针或指向一个类成员的指针。 表达式reinterpret_cast(a)能够用于诸如char* 到 int*,或者One_class* 到 Unrelated_class*等类似这样的转换,因此可能是不安全的。 。,class A . ; class B . ; void f() A* pa = new A; void* pv = reinterpret_cast(pa); / pv 现在指向了一个类型为B的对象,这可能是不安全的 . ,64,static_cast和reinterpret_cast区别,假设你想把一个int转换成double,以便让包含int类型变量的表达式产生出浮点数值的结果。如用C风格的类型转换,你能这样写: int firstNumber, secondNumber; double result = (double)firstNumber)/secondNumber; 如果用上述新的类型转换方法,你应该这样写: double result = static_cast(firstNumber)/secondNumber; 这样的类型转换不论是对人工还是对程序都很容易识别。 reinterpret_casts的最普通的用途就是在函数指针类型之间进行转换。其的转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_casts的代码很难移植。 typedef void (*FuncPtr)(); FuncPtr funcPtrArray10; funcPtrArray0 = ,

    注意事项

    本文(程序设计实习第十八讲输入输出流和文件操作.ppt)为本站会员(本田雅阁)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开