C++语言程序设计:第9、10、11、12、13章.ppt_第1页
C++语言程序设计:第9、10、11、12、13章.ppt_第2页
C++语言程序设计:第9、10、11、12、13章.ppt_第3页
C++语言程序设计:第9、10、11、12、13章.ppt_第4页
C++语言程序设计:第9、10、11、12、13章.ppt_第5页
已阅读5页,还剩148页未读 继续免费阅读

下载本文档

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

文档简介

第九章 群体类 和群体数据的组织,清华大学 郑 莉,c+语言程序设计,2,本章主要内容,模板 群体类 群体数据的组织,3,第一部分模板,函数模板 类模板,4,函数模板,函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。 声明方法: template 函数声明,函 数 模 板,5,求绝对值函数的模板,#include using namespace std; template t abs(t x) return x0?-x:x; int main() int n=-5; double d=-5.5; coutabs(n)endl; coutabs(d)endl; ,函 数 模 板,运行结果: 5 5.5,6,求绝对值函数的模板分析,编译器从调用abs()时实参的类型,推导出函数模板的类型参数。例如,对于调用表达式abs(n),由于实参n为int型,所以推导出模板中类型参数t为int。 当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数: int abs(int x) return x0?-x:x; ,函 数 模 板,7,类模板的作用,使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本类型的和用户自定义类型)。,类 模 板,8,类模板的声明,类模板: template class 类名 类成员声明 如果需要在类模板以外定义其成员函数,则要采用以下的形式: template 类型名 类名:函数名(参数表),类 模 板,9,例9-2 类模板应用举例,#include #include using namespace std; / 结构体student struct student int id; /学号 float gpa; /平均分 ;,类 模 板,template /类模板:实现对任意类型数据进行存取 class store private: t item; / 用于存放任意类型的数据 int havevalue; / 用于标记item是否已被存入内容 public: store(void); / 默认形式(无形参)的构造函数 t getelem(void); /提取数据函数 void putelem(t x); /存入数据函数 ; / 默认形式构造函数的实现 template store:store(void): havevalue(0) ,10,template / 提取数据函数的实现 t store:getelem(void) / 如果试图提取未初始化的数据,则终止程序 if (havevalue = 0) cout / 存入数据函数的实现 void store:putelem(t x) havevalue+; / 将havevalue 置为 true,表示item中已存入数值 item = x; / 将x值存入item ,11,int main() student g= 1000, 23; store s1, s2; store s3; store d; s1.putelem(3); s2.putelem(-7); cout s1.getelem() “ “ s2.getelem() endl; s3.putelem(g); cout “the student id is “ s3.getelem().id endl; cout “retrieving object d “ ; cout d.getelem() endl; /输出对象d的数据成员 / 由于d未经初始化,在执行函数d.getelement()时出错 ,12,13,第二部分群体数据,线性群体 线性群体的概念 直接访问群体-数组类 顺序访问群体-链表类 栈类 队列类,14,群体的概念,群体是指由多个数据元素组成的集合体。群体可以分为两个大类:线性群体和非线性群体。 线性群体中的元素按位置排列有序,可以区分为第一个元素、第二个元素等。 非线性群体不用位置顺序来标识元素。,15,线性群体的概念,线性群体中的元素次序与其位置关系是对应的。在线性群体中,又可按照访问元素的不同方法分为直接访问、顺序访问和索引访问。 在本章我们只介绍直接访问和顺序访问。,16,数组,静态数组是具有固定元素个数的群体,其中的元素可以通过下标直接访问。 缺点:大小在编译时就已经确定,在运行时无法修改。 动态数组由一系列位置连续的,任意数量相同类型的元素组成。 优点:其元素个数可在程序运行时改变。 动态数组类模板:例9-3(9_3.h),直接访问的线性群体,#ifndef array_class #define array_class using namespace std; #include #include #ifndef null const int null = 0; #endif / null enum errortype invalidarraysize, memoryallocationerror, indexoutofrange ; char *errormsg = “invalid array size“, “memory allocation error“, “invalid index: “ ;,动态数组类模板程序,17,template class array private: t* alist; int size; void error(errortype error,int badindex=0) const; public: array(int sz = 50); array(const array,18,19,数组类模板的构造函数,/ 构造函数 template array:array(int sz) if (sz = 0) /sz为数组大小(元素个数),若小于0,则输出错误信息 error(invalidarraysize); size = sz; / 将元素个数赋值给变量size alist = new tsize; /动态分配size个t类型的元素空间 if (alist = null) /如果分配内存不成功,输出错误信息 error(memoryallocationerror); ,直接访问的线性群体,20,数组类的拷贝构造函数,template array:array(const array ,直接访问的线性群体,21,浅拷贝,int main() array a(10); array b(a); ,template array:array( const array ,22,深拷贝,23,数组类的重载“=“运算符函数,template array ,直接访问的线性群体,24,数组类的重载下标操作符函数,template t ,直接访问的线性群体,25,为什么有的函数返回引用,如果一个函数的返回值是一个对象的值,它就被认为是一个常量,不能成为左值。 如果返回值为引用。由于引用是对象的别名,所以通过引用当然可以改变对象的值。,直接访问的线性群体,26,重载指针转换操作符,template array:operator t* (void) const / 返回当前对象中私有数组的首地址 return alist; ,直接访问的线性群体,27,指针转换运算符的作用,#include using namespace std; int main() int a10; void read(int *p, int n); read(a, 10); void read(int *p, int n) for (int i=0; ipi; ,int main() array a(10); void read(int *p, n); read(a, 10); void read(int *p, int n) for (int i=0; ipi; ,直接访问的线性群体,28,array类的应用,例9-4求范围2n中的质数,n在程序运行时由键盘输入。,直接访问的线性群体,#include #include #include “9_3.h“ using namespace std; int main() array a(10); int n; int primecount = 0, i, j; cout = 2 as upper limit for prime numbers: “; cin n; aprimecount+ = 2; / 2是一个质数 for(i = 3; i i/2) aprimecount+ = i; for (i = 0; i primecount; i+) cout setw(5) ai; if (i+1) % 10 = 0) cout endl; cout endl; ,29,30,链表,链表是一种动态数据结构,可以用来表示顺序访问的线性群体。 链表是由系列结点组成的,结点可以在运行时动态生成。 每一个结点包括数据域和指向链表中下一个结点的指针(即下一个结点的地址)。如果链表每个结点中只有一个指向后继结点的指针,则该链表称为单链表。,顺序访问的线性群体,31,单链表,顺序访问的线性群体,32,单链表的结点类模板,template class node private: node *next; public: t data; node(const t,顺序访问的线性群体,33,在结点之后插入一个结点,data1,p,data,template void node:insertafter(node *p) /p节点指针域指向当前节点的后继节点 p-next = next; next = p; /当前节点的指针域指向p ,顺序访问的线性群体,34,删除结点之后的结点,顺序访问的线性群体,data1,node *node:deleteafter(void) node *tempptr = next; if (next = null) return null; next = tempptr-next; return tempptr; ,tempptr,35,链表的基本操作,生成结点 插入结点 查找结点 删除结点 遍历链表 清空链表,顺序访问的线性群体,36,链表类模板(例9-6),/9_6.h #ifndef linkedlist_class #define linkedlist_class #include #include using namespace std; #ifndef null const int null = 0; #endif / null #include “9_5.h“,顺序访问的线性群体,template class linkedlist private: node *front, *rear; node *prevptr, *currptr; int size; int position; node *getnode(const t,37,public: linkedlist(void); linkedlist(const linkedlist,38,void insertfront(const t #endif / linkedlist_class,39,40,链表类应用举例(例9-7),#include using namespace std; #include “9_6.h“ #include “9_6.cpp“ int main() linkedlist link; int i, key, item; for (i=0;i item; link.insertfront(item); ,顺序访问的线性群体,cout key; link.reset();,41,while (!link.endoflist() if(link.data() = key) link.deleteat(); link.next(); cout “list: “; link.reset(); while(!link.endoflist() cout link.data() “ “; link.next(); cout endl; ,42,43,特殊的线性群体栈,栈是只能从一端访问的线性群体,可以访问的这一端称栈顶,另一端称栈底。,特殊的线性群体栈,44,栈的应用举例函数调用,特殊的线性群体栈,45,栈的应用举例表达式处理,特殊的线性群体栈,46,栈的基本状态,栈空 栈中没有元素 栈满 栈中元素个数达到上限 一般状态 栈中有元素,但未达到栈满状态,特殊的线性群体栈,47,48,栈的基本操作,初始化 入栈 出栈 清空栈 访问栈顶元素 检测栈的状态(满、空),特殊的线性群体栈,49,栈类模板(例9-8),特殊的线性群体栈,/9-8.h #ifndef stack_class #define stack_class #include #include using namespace std; const int maxstacksize = 50; template class stack private: t stacklistmaxstacksize; int top;,public: stack (void); void push (const t /类的实现略,50,栈的应用,例9.9 一个简单的整数计算器 实现一个简单的整数计算器,能够进行加、减、乘、除和乘方运算。使用时算式采用后缀输入法,每个操作数、操作符之间都以空白符分隔。例如,若要计算“3+5“则输入“3 5 +“。乘方运算符用“表示。每次运算在前次结果基础上进行,若要将前次运算结果清除,可键入“c“。当键入“q“时程序结束。 9-9.h 9-9.cpp,特殊的线性群体栈,/9_9.h #include #include #include #include using namespace std; enum boolean false, true; #include “9_8.h“ class calculator private: stack s; void enter(int num); boolean gettwooperands(int,51,void calculator:enter(int num) s.push(num); boolean calculator:gettwooperands(int ,52,void calculator:compute(char op) boolean result; int operand1, operand2; result = gettwooperands(operand1, operand2); if (result) switch(op) case +: s.push(operand2+operand1); break; case -: s.push(operand2-operand1); break; case *: s.push(operand2*operand1); break; case /: if (operand1 = 0) cerr “divide by 0!“ endl; s.clearstack(); else s.push(operand2/operand1); break; case : s.push(pow(operand2,operand1); break; cout=s.peek() ; else s.clearstack(); ,53,void calculator:run(void) char c20; while(cin c, *c != q) switch(*c) case c: s.clearstack(); break; case -: if (strlen(c)1) enter(atoi(c); else compute(*c); break; case +: case *: case /: case : compute(*c); break; default: enter(atoi(c); break; ,54,void calculator:clear(void) s.clearstack(); /9_9.cpp #include “9-9.h“ int main() calculator calc; calc.run(); ,55,56,特殊的线性群体队列,队列是只能向一端添加元素,从另一端删除元素的线性群体,57,队列的基本状态,队空 队列中没有元素 队满 队列中元素个数达到上限 一般状态 队列中有元素,但未达到队满状态,特殊的线性群体队列,元素移动方向,元素移动方向,58,59,循环队列,在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头。,特殊的线性群体队列,60,61,例9-10 队列类模板,特殊的线性群体队列,#ifndef queue_class #define queue_class #include #include using namespace std; const int maxqsize = 50; template class queue private: int front, rear, count; t qlistmaxqsize;,public: queue (void); void qinsert(const t /成员函数的实现略,62,第三部分群体数据的组织,插入排序 选择排序 交换排序 顺序查找 折半查找,63,排序(sorting),排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。 数据元素:数据的基本单位。在计算机中通常作为一个整体进行考虑。一个数据元素可由若干数据项组成。 关键字:数据元素中某个数据项的值,用它可以标识(识别)一个数据元素。 在排序过程中需要完成两种基本操作: 比较两个数的大小 调整元素在序列中的位置,群体数据的组织,64,内部排序与外部排序,内部排序:待排序的数据元素存放在计算机内存中进行的排序过程。 外部排序:待排序的数据元素数量很大,以致内存存中一次不能容纳全部数据,在排序过程中尚需对外存进行访问的排序过程。,群体数据的组织,65,内部排序方法,插入排序 选择排序 交换排序,群体数据的组织,66,插入排序的基本思想,每一步将一个待排序元素按其关键字值的大小插入到已排序序列的适当位置上,直到待排序元素插入完为止。,初始状态: 5 4 10 20 12 3,67,直接插入排序,在插入排序过程中,由于寻找插入位置的方法不同又可以分为不同的插入排序算法,这里我们只介绍最简单的直接插入排序算法。 例9-11 直接插入排序函数模板(9_11.h),群体数据的组织,template void insertionsort(t a, int n) int i, j; t temp; for (i = 1; i 0 ,直接插入排序函数模板(9_11.h),68,69,选择排序的基本思想,每次从待排序序列中选择一个关键字最小的元素,(当需要按关键字升序排列时),顺序排在已排序序列的最后,直至全部排完。,3 4 10 20 12 5,3 4 10 20 12 5,第 i 次选择后,将选出的那个记录与第 i 个记录做交换。,70,直接选择排序,在选择类排序方法中,从待排序序列中选择元素的方法不同,又分为不同的选择排序方法,其中最简单的是通过顺序比较找出待排序序列中的最小元素,称为直接选择排序。 例9-12 直接选择排序函数模板(9-12.h),群体数据的组织,template void swap (t ,直接选择排序函数模板(9-12.h),71,72,交换排序的基本思想,两两比较待排序序列中的元素,并交换不满足顺序要求的各对元素,直到全部满足顺序要求为止。,群体数据的组织,73,最简单的交换排序方法 起泡排序,对具有n个元素的序列按升序进行起泡排序的步骤: 首先将第一个元素与第二个元素进行比较,若为逆序,则将两元素交换。然后比较第二、第三个元素,依次类推,直到第n-1和第n个元素进行了比较和交换。此过程称为第一趟起泡排序。经过第一趟,最大的元素便被交换到第n个位置。 对前n-1个元素进行第二趟起泡排序,将其中最大元素交换到第n-1个位置。 如此继续,直到某一趟排序未发生任何交换时,排序完毕。对n个元素的序列,起泡排序最多需要进行n-1趟。,群体数据的组织,74,起泡排序举例,对整数序列 8 5 2 4 3 按升序排序,8 5 2 4 3,5,2,4,3,8,2,4,3,5,8,2,3,4,5,8,2,3,4,5,8,初始状态,第一趟结果,第二趟结果,第三趟结果,第四趟结果,小的逐渐上升,每趟沉下一个最大的,群体数据的组织,75,例9-13 起泡排序函数模板,template void swap (t ,template void bubblesort(t a, int n) int i,j; int lastexchangeindex; i = n-1; while (i 0) lastexchangeindex = 0; for (j = 0; j i; j+) if (aj+1 aj) swap(aj,aj+1); lastexchangeindex = j; i = lastexchangeindex; ,群体数据的组织,76,顺序查找,其基本思想 从序列的首元素开始,逐个元素与待查找的关键字进行比较,直到找到相等的。若整个序列中没有与待查找关键字相等的元素,就是查找不成功。 顺序查找函数模板 例9-14,群体数据的组织,template int seqsearch(t list, int n, t key) for(int i=0;i n;i+) if (listi = key) return i; return -1; ,顺序查找函数模板,77,78,折半查找的基本思想,对于已按关键字排序的序列,经过一次比较,可将序列分割成两部分,然后只在有可能包含待查元素的一部分中继续查找,并根据试探结果继续分割,逐步缩小查找范围,直至找到或找不到为止。,群体数据的组织,79,折半查找举例,用折半查找法,在下列序列中查找值为21的元素:,m=int(l+h)/2)=3,l=m+1=4,m=int(l+h)/2)=4,80,例10-5 折半查找函数模板,template int binsearch(t list, int n, t key) int mid, low, high; t midvalue; low=0; high=n-1; while (low = high) mid = (low+high)/2; midvalue = listmid; if (key = midvalue) return mid; else if (key midvalue) high = mid-1; else low = mid+1; return -1; ,群体数据的组织,第十章 c+标准模板库,清华大学 郑 莉,c+语言程序设计,82,主要内容,泛型程序设计 与标准模板库有关的概念和术语 c+标准模板库中的容器 迭代器 标准c+库中的算法 函数对象,83,泛型程序设计,将程序写得尽可能通用 将算法从特定的数据结构中抽象出来,成为通用的 c+的模板为泛型程序设计奠定了关键的基础 stl是泛型程序设计的一个范例 容器(container) 迭代器(iterator) 算法(algorithms) 函数对象(function object),84,命名空间(namespace),一个命名空间将不同的标识符集合在一个命名作用域(named scope)内 为了解决命名冲突 例如,声明一个命名空间ns: namspace ns class file; void fun (); 则引用标识符的方式如下, ns: file obj; ns: fun (); 没有声明命名空间的标识符都处于无名的命名空间中,概念和术语,85,命名空间(namespace),可以用using来指定命名空间 例如,经过以下声明: using ns:file; 在当前作用域中就可以直接引用file using namespace std; 命名空间std中所有标识符都可直接引用 在新的c+标准程序库中,所有标识符都声明在命名空间std中,头文件都不使用扩展名,概念和术语,86,容器,容器类是容纳、包含一组元素或元素集合的对象。 异类容器类与同类容器类 顺序容器与关联容器 七种基本容器: 向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap),概念和术语,87,容器的接口,通用容器运算符 =,!=,=,=,= 方法(函数) 迭代方法 begin(),end(),rbegin(),rend() 访问方法 size(),max_size(),swap(),empty(),88,适配器,适配器是一种接口类 为已有的类提供新的接口。 目的是简化、约束、使之安全、隐藏或者改变被修改类提供的服务集合。 三种类型的适配器: 容器适配器 用来扩展7种基本容器,它们和顺序容器相结合构成栈、队列和优先队列容器 迭代器适配器 函数对象适配器。,概念和术语,89,迭代器,迭代器是面向对象版本的指针,它们提供了访问容器、序列中每个元素的方法。,概念和术语,90,算法,c+标准模板库中包括70多个算法 其中包括查找算法,排序算法,消除算法,记数算法,比较算法,变换算法,置换算法和容器管理等等。 这些算法的一个最重要的特性就是它们的统一性,并且可以广泛用于不同的对象和内置的数据类型。,概念和术语,91,顺序容器,顺序容器的接口 插入方法 push_front(),push_back(),insert(),运算符“=” 删除方法 pop() ,erase(),clear() 迭代访问方法 使用迭代器 其它顺序容器访问方法(不修改访问方法) front(),back(),下标运算符,容 器,92,顺序容器向量,向量属于顺序容器,用于容纳不定长线性序列(即线性群体),提供对序列的快速随机访问(也称直接访问) 向量是动态结构,它的大小不固定,可以在程序运行时增加或减少。 例10-1 求范围2n中的质数,n在程序运行时由键盘输入。,容 器,93,/10_1.cpp #include #include #include /包含向量容器头文件 using namespace std ; int main() vector a(10); int n; int primecount = 0, i, j; cout=2 as upper limit: “; cin n; aprimecount+ = 2;,93,94,for(i = 3; i i/2) aprimecount+ = i; for (i = 0; iprimecount; i+)/输出质数 coutsetw(5)ai; if (i+1) % 10 = 0) /每输出10个数换行一次 cout endl; coutendl; ,94,95,顺序容器双端队列,双端队列是一种放松了访问权限的队列。元素可以从队列的两端入队和出队,也支持通过下标操作符“”进行直接访问。 例10-2 使用双端队列容器保存双精度数值序列,容 器,96,顺序容器列表,列表主要用于存放双向链表,可以从任意一端开始遍历。列表还提供了拼接(splicing)操作,将一个序列中的元素从插入到另一个序列中。 例10-3 改写例9-7 从键盘输入10个整数,用这些整数值作为结点数据,生成一个链表,按顺序输出链表中结点的数值。然后从键盘输入一个待查找整数,在链表中查找该整数,若找到则删除该整数所在的结点(如果出现多次,全部删除),然后输出删除结点以后的链表。在程序结束之前清空链表。,容 器,97,/10_3.cpp #include #include using namespace std ; int main() list link; /构造一个列表用于存放整数链表 int i, key, item; for(i=0;i item; link.push_front(item); cout“list: “; / 输出链表,97,98,list:iterator p=link.begin(); while(p!=link.end()/输出各节点数据,直到链表尾 cout key; link.remove(key); cout “list: “; / 输出链表 p=link.begin(); / 使p重新指向表头 while(p!=link.end() cout *p “ “; p+; / 使p指向下一个节点 cout endl; ,98,99,容器适配器,容器适配器是用来扩展7种基本容器的 栈容器 使用适配器与一种基础容器相结合来实现 例10-4:应用标准库中的deque顺序容器生成一个整数栈stack。 队列容器 使用适配器与一种基础容器相结合来实现的先进先出数据结构。 例10-5:应用标准库中的deque顺序容器生成一个整数标准队列queue。,容 器,100,什么是迭代器,迭代器是面向对象版本的指针 指针可以指向内存中的一个地址 迭代器可以指向容器中的一个位置 stl的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。,迭代器,101,迭代器的类型,输入迭代器 可以用来从序列中读取数据 输出迭代器 允许向序列中写入数据 前向迭代器 既是输入迭代器又是输出迭代器,并且可以对序列进行单向的遍历 双向迭代器 与前向迭代器相似,但是在两个方向上都可以对数据遍历 随机访问迭代器 也是双向迭代器,但能够在序列中的任意两个位置之间进行跳转。,迭代器,102,迭代器适配器,迭代器适配器是用来扩展(或调整)迭代器功能的类。它本身也被称为迭代器,只是这种迭代器是通过改变另一个迭代器而得到的 逆向迭代器 通过重新定义递增运算和递减运算,使其行为正好倒置 插入型迭代器 将赋值操作转换为插入操作。通过这种迭代器,算法可以执行插入行为而不是覆盖行为 例10-6 应用逆向迭代器和后插迭代器来操作向量容器中的元素,迭代器,103,迭代器相关的辅助函数,advance()函数 将迭代器的位置增加,增加的幅度由参数决定 distance()函数 返回迭代器之间的距离 函数iter_swap() 交换两个迭代器所指向的元素值 例10-7 用三个迭代器辅助函数来操作列表容器中的元素。,迭代器,104,标准c+库中的算法,算法本身是一种函数模板 不可变序列算法(non-mutating algorithms) 不直接修改所操作的容器内容的算法 可变序列算法(mutating algorithms) 可以修改它们所操作的容器的元素。 排序相关算法 数值算法,算 法,105,算法应用举例,例10-9 应用不可变序列算法对数据序列进行分析 例10-10 以可变序列算法对数据序列进行复制,生成,删除,替换,倒序,旋转等可变性操作。 例10-11 应用排序相关算法对序列进行各项操作 例10-12 应用数值算法对数据序列进行操作,算 法,106,函数对象,一个行为类似函数的对象,它可以不需参数,也可以带有若干参数,其功能是获取一个值,或者改变操作的状态。 任何普通的函数和任何重载了调用运算符operator()的类的对象都满足函数对象的特征 stl中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件。,第十一章 流类库与输入/输出,清华大学 郑 莉,c+语言程序设计,108,本章主要内容,i/o流的概念 输出流 输入流 输入/输出流,109,i/o流的概念,当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象。 流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动。 程序建立一个流对象,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用。 读操作在流数据抽象中被称为(从流中)提取,写操作被称为(向流中)插入。,110,输出流,最重要的三个输出流是 ostream ofstream ostringstream,111,输出流对象,预先定义的输出流对象: cout 标准输出 cerr 标准错误输出,没有缓冲,发送给它的内容立即被输出。 clog 类似于cerr,但是有缓冲,缓冲区满时被输出。,输出流,112,输出流对象,ofstream类支持磁盘文件输出 如果在构造函数中指定一个文件名,当构造这个文件时该文件是自动打开的 ofstream myfile(“filename“,iosmode); 可以在调用默认构造函数之后使用open成员函数打开文件 ofstream myfile; /声明一个静态输出文件流对象 myfile.open(“filename“,iosmode); /打开文件,使流对象与文件建立联系 ofstream* pmyfile = new ofstream; /建立一个动态的输出文件流对象 pmyfile-open(“filename“,iosmode); /打开文件,使流对象与文件建立联系,输出流,113,插入运算符(),插入()运算符是所有标准c+数据类型预先设计的。 用于传送字节到一个输出流对象。,输出流,114,控制输出格式,控制输出宽度 为了调整输出,可以通过在流中放入setw操纵符或调用width成员函数为每个项指定输出宽度。 例11-1 使用width控制输出宽度 #include using namesoace std; int main() double values = 1.23,35.36,653.7,4358.24; for(int i=0;i4;i+) cout.width(10); cout valuesi n; ,输出流,输出结果: 1.23 35.36 653.7 4358.24,115,例:使用*填充,#include using namespace std; int main() double values=1.23,35.36,653.7,4358.24; for(int i=0; i4; i+) cout.width(10); cout.fill(*); coutvaluesin; ,输出流,输出结果: *1.23 *35.36 *653.7 *4358.24,116,例11-2使用setw指定宽度,#include #include using namespace std; int main() double values=1.23,35.36,653.7,4358.24; char *names=“zoot“,“jimmy“,“al“,“stan“; for(int i=0;i4;i+) coutsetw(6)namesi setw(10)valuesi endl; ,输出流,输出结果: zoot 1.23 jimmy 35.36 al 653.7 stan 4358.24,117,例11-3设置对齐方式,#include #include using namespace std; int main() double values=1.23,35.36,653.7,4358.24; char *names=“zoot“,“jimmy“,“al“,“stan“; for(int i=0;i4;i+) coutsetiosflags(ios:left) setw(6)namesi resetiosflags(ios:left) setw(10)valuesi endl; ,输出流,输出结果: zoot 1.23 jimmy 35.36 al 653.7 stan 4358.24,118,例11-4控制输出精度,#include #include using namespace std; int main() double values=1.23,35.36,653.7,4358.24; char *names=“zoot“,“jimmy“,“al“,“stan“; coutsetiosflags(ios:scientific); for(int i=0;i4;i+) coutsetiosflags(ios:left) setw(6)namesi resetiosflags(ios:left) setw(10)setprecision(1) valuesiendl; ,输出流,输出结果: zoot 1 jimmy 4e+001 al 7e+002 stan 4e+003,119,进制,dec、oct和hex操纵符设置输入和输出的缺省进制。,输出流,120,输出文件流成员函数,输出流成员函数有三种类型: 与操纵符等价的成员函数。 执行非格式化写操作的成员函数。 其它修改流状态且不同于操纵符或插入运算符的成员函数。,输出流,121,输出文件流成员函数,open函数 把流与一个特定的磁盘文件关联起来。 需要指定打开模式。 put函数 把一个字符写到输出流中。 write函数 把内存中的一块内容写到一个输出文件流中 seekp和tellp函数 操作文件流的内部指针 close函数 关闭与一个输出文件流关联的磁盘文件 错误处理函数 在写到一个流时进行错误处理,输出流,122,例11-5向文件输出,#include using namespace std; struct date int mo,da,yr; ; int main() date dt = 6,10,92; ofstream tfile(“date.dat“,ios:binary); tfile.write(char *) ,输出流,123,二进制输出文件,以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改变模式。 使用ofstream构造函数中的模式参量指定二进制输出模式 使用二进制操作符代替setmode成员函数:ofs binary;,输出流,124,输入流,重要的输入流类: istream类最适合用于顺序文本模式输入。 cin是其派生类istream_withassign的对象。 ifstream类支持磁盘文件输入。 istringstream,125,输入流对象,如果在构造函数中指定一个文件名,在构造该对象时该文件便自动打开。 ifstream myfile(“filename“,iosmode); 在调用缺省构造函数之后使用open函数来打开文件。 ifstream myfile;/建立一个文件流对象 myfile.open(“filename“,iosmode); /打开文件“filename“,输入流,126,提取运算符(),提取运算符()对于所有标准c+数据类型都是预先设计好的。 是从一个输入流对象获取字节最容易的方法。 ios类中的很多操纵符都可以应用于输入流。但是只有少数几个对输入流对象具有实际影响,其中最重要的是进制操纵符dec、oct和hex。,输入流,127,输入流成员函数,open函数把该流与一个特定磁盘文件相关联。 get函数的功能与提取运算符()很相像,主要的不同点是get函数在读入数据时包括空白字符。(第6章介绍过) getline的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符。(第6章介绍过) read成员函数从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数。 如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取。,输入流,128,输入流成员函数,seekg函数用来设置输入文件流中读取数据位置的指针。 tellg函数返回当前文件读指针的位置。 close函数关闭与一个输入文件流关联的磁盘文件。,输入流,129,例11-9 设置位置指针,#include #include using namespace std; int main() char ch; ifstream tfile(“payroll“,ios:binary|ios:nocreate); if(tfile) tfile.seekg(8); while(tfile.good() tfile.get(ch); if (!ch) break; coutch; else cout“error: cannot open file payroll.“endl

温馨提示

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

评论

0/150

提交评论