这段时间学习了文件操作和标准模板库STL,根据所学的知识我做了一些总结。
一、文件操作
1.C++把文件看成无结构的字节流
编码方式: 文本文件 二进制文件
存取方式: 顺序文件 随机文件
ifstream、ofstream 和 fstream 类用于内存与文件之间的数据传输。
2.要执行文件的输入输出,须做以下几件事:
(1) 在程序中包含头文件fstream;
(2) 建立文件流。建立文件流的过程就是定义流类的对象,例如: fstream in; ofstream out;fstream both;分别定义了输入流对象in;输出流对象out,输入输出流对象both。
(3) 使用open()函数打开文件,也就是使某一文件与上面的某一流相联系。
open()函数是上述三个流类的成员函数,其原型是在fstream.h中定义的, 原型为: void open(const unsigned char*,int mode,int access=filebuf::openprot);
( 4) 对open结果进行检查(检查打开操作是否成功。可省略,但不推荐。)
(5)进行读写。在建立(或打开)的文件上执行所要求的输入或输出操作; (6)关闭文件流对象。
3.文件打开方式(三种常用的方式):
ios::in: 用于输入。文件以输入方式打开( ifstream流类的默认打开方式 文件存在,打开文件; 文件不存在,打开失败) ios::out: 用于输出。文件以输出方式打开。( ofstream流类的默认打开方式 如果文件存在,打开文件,并清空原文件中的内容。 如果文件不存在,则创建文件。 如果文件路径错误,创建流对象操作失败)
ios::app: 以追加的方式打开文件。主要用于文件的写操作。如果文件不存在,则创建文件。如果文件存在,则不会删除文件中的内容 (在该模式下,不管文件指针处于何处,新写入的内容永远在文件尾)
4.文件关闭,文件操作结束以后,要随时关闭文件。
文本文件时顺序存取文件
(流对象的构造函数初始化工作相当于open函数的作用)
while ( f1 && f1.get(ch) ) f2.put( ch ) ;//从文件f1开始读字符,如果有数据就复制到f2中
二进制文件:
二进制文件以基本类型数据在内存的二进制表示形式存放数据,不对写入或读出的数据做格式转换 ;二进制文件的读写方式由程序控制;打开二进制文件用binary方式 ;二进制文件是随机存取文件。
用read()函数和write()函数读写文件 (成块的读写)
read()和write()原型如下:
istream &read(unsigned char* buf,int num); //unsigned char* buf:位置
ostream &write(const unsigned char* buf,int num);
文件的随机读写:
在C++的I/O系统中有个文件指针,它有两个名字。 其中一个名字叫get指针,用于指出下一次输入操作的位置; 另一个名字叫做put指针,用于指出下一次输出操作的位置。
(不建议使用二进制文件操作)
二、STL
STL内所有组件都由模板构成,其元素可以是任意类型
1.STL组件:
容器—— 管理某类对象的集合
迭代器—— 在对象集合上进行遍历
算法——处理集合内的元素
容器适配器
函数对象
2.STL类别
序列式容器-排列次序取决于插入时机和位置
关联式容器-排列顺序取决于特定准则
3.STL容器元素的条件
必须能够通过拷贝构造函数进行复制;必须可以通过赋值运算符完成赋值操作;必须可以通过析构函数完称销毁动作;序列式容器元素的默认构造函数必须可用; 某些动作必须定义operator ==,例如搜寻操作 关联式容器必须定义出排序准则,默认情况是重载operator <
4.迭代器对象必须和容器类型一致
5.迭代器分为双向迭代器和随机存取迭代器
6.STL容器vector
vector模拟动态数组;
vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝构造函数和重载的赋值操作符);
vector的大小(size)和容量(capacity) size返回实际元素个数, capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器。(申请新空间,把原来的内容复制过来,然后释放原空间)
vector常见的操作:
操作 | 效果 |
vector<T> c | 产生空的vector |
vector<T> c1(c2) | 产生同类型的c1,并将复制c2的所有元素 |
vector<T> c(n) | 利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector |
vector<T> c(n,e) | 产生一个大小为n的vector,每个元素都是e |
vector<T> c(beg,end) | 产生一个vector,以区间[beg,end]为元素初值 |
~vector<T>() | 销毁所有元素并释放内存。 |
操作 | 效果 |
c.size() | 返回元素个数 |
c.empty() | 判断容器是否为空 |
c.max_size() | 返回元素最大可能数量(固定值) |
c.capacity() | 返回重新分配空间前可容纳的最大元素数量 |
c.reserve(n) | 扩大容量为n |
c1==c2 | 判断c1是否等于c2 |
c1!=c2 | 判断c1是否不等于c2 |
c1<c2 | 判断c1是否小于c2 |
c1>c2 | 判断c1是否大于c2 |
c1<=c2 | 判断c1是否大于等于c2 |
c1>=c2 | 判断c1是否小于等于c2 |
操作 | 效果 |
c1 = c2 | 将c2的全部元素赋值给c1 |
c.assign(n,e) | 将元素e的n个拷贝赋值给c |
c.assign(beg,end) | 将区间[beg,end]的元素赋值给c |
c1.swap(c2) | 将c1和c2元素互换 |
swap(c1,c2) | 同上,全局函数 |
迭代器相关函数:
操作 | 效果 |
begin() | 返回一个迭代器,指向第一个元素 |
end() | 返回一个迭代器,指向最后一个元素之后 |
rbegin() | 返回一个逆向迭代器,指向逆向遍历的第一个元素 |
rend() | 返回一个逆向迭代器,指向逆向遍历的最后一个元素 |
操作 | 效果 |
c.insert(pos,e) | 在pos位置插入元素e的副本,并返回新元素位置 |
c.insert(pos,n,e) | 在pos位置插入n个元素e的副本 |
c.insert(pos,beg,end) | 在pos位置插入区间[beg,end]内所有元素的副本 |
c.push_back(e) | 在尾部添加一个元素e的副本 |
操作 | 效果 |
c.pop_back() | 移除最后一个元素但不返回最后一个元素 |
c.erase(pos) | 删除pos位置的元素,返回下一个元素的位置 |
c.erase(beg,end) | 删除区间[beg,end]内所有元素,返回下一个元素的位置 |
c.clear() | 移除所有元素,清空容器 |
c.resize(num) | 将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除) |
c.resize(num,e) | 将元素数量改为num(增加的元素是e的副本) |
STL容器map/multimap:
元素包含两部分(key,value),key和value可以是任意类型;
根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢 ;
不能直接改变元素的key,可以通过operator []直接存取元素值;
map中不允许key相同的元素,multimap允许key相同的元素。
map可以是下列形式:
map<key,value> 一个以less(<)为排序准则的map,
map<key,value,op> 一个以op为排序准则的map
(它们的操作很多都和vector一样或类似)
pair 模板:
pair模板可以用于生成 key-value对
算法:
(算法是基于泛型也就是模板的)
count:
size_t count(InIt first, InIt last, const T& val);// 计算[first,last) 中等于val的元素个数
count_if:
size_t count_if(InIt first, InIt last, Pred pr); 计算[first,last) 中符合pr(e) == true 的元素 e的个数
min_element:
template<class FwdIt>
FwdIt min_element(FwdIt first, FwdIt last);
返回[first,last) 中最小元素的迭代器,以 “< ”作比较器
max_element:
template<class FwdIt>
FwdIt max_element(FwdIt first, FwdIt last);
返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器
for_each:
template<class InIt, class Fun>
Fun for_each(InIt first, InIt last, Fun f);
对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e
排序和查找算法:
1.find:
template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);
返回区间 [first,last) 中的迭代器 i ,使得 * i == val
2.find_if:
template<class InIt, class Pred>
InIt find_if(InIt first, InIt last, Pred pr);
返回区间 [first,last) 中的迭代器 i, 使得 pr(*i) == true
3.binary_search 折半查找,要求容器已经有序且支持随机访问迭代器,返回是否找到
4. lower_bound,uper_bound, equal_range
5.sort 快速排序
template<class RanIt>
void sort(RanIt first, RanIt last);
按升序排序。判断x是否应比y靠前,就看 x < y 是否为true
template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
按升序排序。判断x是否应比y靠前,就看 pr(x,y) 是否为true
虽然关于算法的老师讲了很多,但是自己理解和使用起来并不是那么容易,自己以后要多多学习和体会。
最后再补充一下关于常成员赋值的问题:
常成员数据类型 temp=const_cast<常成员数据类型>(& 常成员名)
*temp=对象名.常成员名
……
return *this
}
之前在做作业时不知道该怎么正确地对于常成员赋值,后来通过老师讲解的作业才明白了。