ostream是用于输出的流类,cout就是该类的对象。
ifstream是用于从文件读取数据的类。
ofstream是用于向文件写入数据的类。
iostream是既能用于输入,又能用于输出的类。
fstream是既能从文件读取数据,又能向文件写入数据的类。
缺省情况下 从输入流中读取bufSize-1个字到缓冲区buf,或读到碰到’\n’为止(哪个先到算哪个)。 从输入流中读取bufSize-1个字到缓冲区buf,或读到碰到delim字符为止(哪个先到算哪个)。 两个函数都会自动在buf中读入数据的结尾添加’\0’。’\n’或delim都不会被读入buf,但会被从输入流中取走。如果输入流中’\n’或delim之前的字符个数达到或超过了bufSize个,就导致读入出错,其结果就是:虽然本次读入已经完成,但是之后的读入就都会失败了。 可以用 bool eof(); 判断输入流是否结束 示例: 可以将顺序文件看作一个有限字符构成的顺序字符流,然后像对cin,cout 一样的读写。 – 也可以先创建ofstream对象,再用open函数打开 判断打开是否成功: 文件名可以给出绝对路径,也可以给出相对路径。没有交代路径信息,就是在当前文件夹下找文件 ifstream fin(“a1.in”, ios::ate); long location = fin.tellg(); //取得读指针的位置 location = 10L; fin.seekg(location); //将读指针移动到第10个字节处 fin.seekp(location, ios::beg); //从头数location fin.seekp(location, ios::cur); //从当前位置数location fin.seekp(location, ios::end); //从尾部数location 示例: 将文件读指针指向的地方的n个字节的内容,读入到内存地址s,然后将文件读指针向后移动n字节(以ios::in方式打开文件时,文件读指针开始指向文件开头)。 将内存地址s处的n个字节内容,写入文件中写指针指向的位置,然后将文件写指针向后移动n字节(以ios::out方式打开文件时,文件写指针开始指向文件开头,以ios::app方式打开文件时,文件写指针开始指向文件尾部)。 Linux,Unix下的换行符号:’\n’(ASCII码:0x0a) 导致Linux,Mac OS文本文件在Windows记事本中打开时不换行 求不同类型的变量就要写不同的Swap函数,太麻烦了,能否只写一个Swap,就能交换各种类型的变量? 在有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句 为了多快好省地定义出一批相似的类,可以定义类模板,然后由类模板生成不同的类 数组是一种常见的数据类型,元素可以是: 考虑一个数组类,需要提供的基本操作 编译器由类模板生成类的过程叫类模板的实例化。由类模板实例化得到的类,叫模板类。 通过 任意从 生成的函数,都是任意Pair模板类的友元。 所有从 生成的函数,都成为A的友元; 但是自己写的函数 不会成为A的友元。 类模板中可以定义静态成员,那么从该类模板实例化得到的所有类,都包含同样的静态成员。
cerr<<“Hello,world”<
cout<<“Hello,world”<
istream类的成员函数
istream&getline(char*buf,int bufSize);
istream&getline(char*buf,int bufSize,char delim);
if(!cin.getline(...))
判断输入是否结束istream类的成员函数
int peek(); 返回下一个字符,但不从流中去掉
istream&putback(char c); 将字符ch放回输入流
istream&ignore(int nCount=1,int delim=EOF);
从流中删掉最多nCount个字符,遇到EOF时结束。#include
文件读写
文件和流
创建文件
#include
– ofstream outFile("clients.dat",ios::out|ios::binary); //创建文件
–ios:out:输出到文件,删除原有内容
–ios::app:输出到文件,保留原有内容,总是在尾部添加ofstream fout;
fout.open("test.out",ios::out|ios::binary);
if(!fout){
cout<<"File open error!"<<endl;
}
文件名的绝对路径和相对路径
文件的读写指针
ofstream fout("a1.out",ios::app); //以添加方式打开
long location=fout.tellp(); //取得写指针的位置
location=10;
fout.seekp(location); //将写指针移动到第10个字节处
fout.seekp(location,ios::beg); //从头数location
fout.seekp(location,ios::cur); //从当前位置数location
fout.seekp(location,ios::end); //从尾部数location
//打开文件,定位文件指针到文件尾
字符文件读写
例如,若in.txt的内容为:
1 234 9 45 6 879
则执行本程序后,生成的out.txt的内容为:
1 6 9 45 234 879
#include
二进制文件读写
ifstream和fstream的成员函数:istream&read(char*s,long n);
ofstream和fstream的成员函数:istream&write(const char*s,long n);
#include
#include
#include
#include
文件拷贝程序mycopy示例
/*用法示例:
mycopy src.dat dest.dat
即将src.dat拷贝到dest.dat
如果dest.dat原来就有,则原来的文件会被覆盖*/
#include
二进制文件和文本文件的区别
Windows下的换行符号:’\r\n’(ASCII码:0x0d0a) endl就是’\n’
Mac OS下的换行符号:’\r’(ASCII码:0x0d)
–读取文件时,所有的’\r\n’会被当做一个字符’\n’处理,即少读了一个字节’\r’。
–写入文件时,写入单独的’\n’时,系统自动在前面加一个’\r’,即多写了一个’\r’。函数模板和类函数
函数模板
void Swap(int &x,int &y){
int tmp=x;
x=y;
y=tmp;
void Swap(double &x,double &y){
double tmp=x;
x=y;
y=tmp;
template<class 类型参数1, class 类型参数2, ......>
返回值类型 模板名(形参表)
{
函数体
};
template<class T>
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
int main(){
int n=1,m=2;
Swap(n,m); //编译器自动生成void Swap(int &,int &)函数
double f=1.2,g=2.3;
Swap(f,g); //编译器自动生成void Swap(double &,double &)函数
return 0;
}
template<class T1,class T2>
T2 print(T1 arg1, T2 arg2) {
cout << arg1 << " " << arg2 << endl;
return arg2;
}
template<class T>
T MaxElement(T a[], int size) //size是数组元素个数
{
T tmpMax = a[0];
for (int i = 1; i < size; ++i)
if (tmpMax < a[i])
tmpMax = a[i];
return tmpMax;
}
#include
函数模板的重载
template<class T1,class T2>
void print(T1 arg1, T2 arg2) {
cout << arg1 << " " << arg2 << endl;
}
template<class T>
void print(T arg1, T arg2) {
cout << arg1 << " " << arg2 << endl;
}
template<class T, class T2>
void print(T arg1, T arg2) {
cout << arg1 << " " << arg2 << endl;
}
函数模板和函数次序
#include
template<class T>
T myFunction(T arg1,T arg2){
cout << arg1 << " " << arg2 << "\n";
return arg1;
}
......
myFunction(5, 7); //ok:replace T with int
myFunction(5.8, 8.4); //ok:replace T with double
myFunction(5, 8.4); //error,no matching function for call to 'myFunction(int,double)'
函数模板示例:Map
#include
类模板
类模板–问题的提出
–整数
–浮点数
–字符串
–…
–len():查看数组的长度
–getElement(int index):获取其中的一个元素
–setElement(int index):对其中的一个元素进行赋值
–…类模板的定义
template<typename 类型参数1, typename 类型参数2, ......> //类型参数表
//typename可以是class,同样适用于函数模板
class 类模板名 {
成员函数和成员变量
};
template<class 类型参数1, class 类型参数2, ......> //类型参数表
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表){
......
}
类模板名<真实类型参数表>对象名(构造函数实参表);
类模板示例:Pair类模板
template<class T1,class T2>
class Pair {
public:
T1 key; //关键字
T2 value; //值
Pair(T1 k, T2 v) :key(k), value(v) {
};
bool operator<(const Pair<T1, T2>& p)const;
};
template<class T1, class T2>
bool Pair<T1, T2>::operator<(const Pair<T1, T2>& p)const {
//Pair的成员函数 operator <
return key < p.key;
}
int main() {
Pair<string, int>student("Tom", 19);
//实例化出一个类Pair
用类模板定义对象
Pair<string, int>* p;
Pair<string, double>a;
p = &a; //wrong
函数模板作为类模板成员
#include
类模板与非类型参数
#include
类模板与派生、友元和静态成员变量
类模板与继承
类模板从类模板派生
template<class T1,class T2>
class A {
T1 v1; T2 v2;
};
template<class T1,class T2>
class B :public A<T2, T1> {
T1 v3; T2 v4;
};
template<class T>
class C :public B<T, T> {
T v5;
};
int main() {
B<int, double>obj1;
C<int>obj2;
return 0;
}
B
这个类的名字实例化出来了两个类:class B <int, double>:public A<double,int> {
int v3; double v4;
};
class A < double,int> {
double v1; int v2;
};
类模板从模板类派生
template<class T1, class T2>
class A {
T1 v1; T2 v2;
};
template<class T>
class B :public A<int, double> {
T v;
};
int main() {
B<char>obj1; //自动生成两个模板类:A
类模板从普通类派生
class A {
int v1;
};
template<class T>
class B :public A{
//所有从B实例化得到的类,都以A为基类
T v;
};
int main() {
B<char>obj1;
return 0;
}
普通类从模板类派生
template<class T>
class A {
T v1;
int n;
};
class B :public A<int>{
double v;
};
int main() {
B obj1;
return 0;
}
类模板与友元
函数、类、类的成员函数作为类模板的友元
void Func1(){
}
class A{
};
class B {
public:
void Func() {
}
};
template<class T>
class Tmp1 {
friend void Func1();
friend class A;
friend void B::Func();
}; //任何从Tmp1实例化来的类,都有以上三个友元
函数模板作为类模板的友元
#include
template<class T1,class T2>
ostream& operator<<(ostream& o, const Pair<T1, T2>& p)
函数模板作为类的友元
#include
template<class T>
void Print(const T& p)
void Print(int a){
}
类模板作为类模板的友元
#include
A
类,成了B
类的友元。任何从A模板实例化出来的类,都是任何B实例化出来的类的友元。类模板与static静态成员
#include