C++面向对象程序设计(七)——输入输出和模板
C++面向对象程序设计(七)——输入输出和模板
程序设计与算法C++面向对象程序设计 github仓库
与输入输出流操作相关的类
isteam
用于输入的流类,例如cin
是该类的对象
ostream
用于输出的流类,例如cout
ifstream
是用于从文件读取数据的类
ofstream
用于向文件写入的类
iostream
既能输入又能输出的类
fstream
既能从文件读取数据,又能向文件写入数据
输出重定向
#include<iostream>
using namespace std;
int main(){
int x,y;
cin >> x >> y;
freopen("test.txt","w",stdout);//输出重定向到text.txt文件
if( y ==0 )
cerr << "error." <<endl;
else
cout<<x/y; //输出结果到test.txt
return 0;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
输入重定向
#include<iostream>
using namespace std;
int main(){
double f;
int n;
freopen("t.txt","r",stdin); //从t.txt读取数据
cin >> f >> n;
cout << f << "," << n << endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
判断输入流结束
int x;
while(cin >> x)
{
......
}
- 1
- 2
- 3
- 4
- 5
istream类的成员函数
istream & getlinnen( char * buf, int bufSize);
从输入流读取bufSize-1
个字符到缓冲区buf
,或读到碰到\n
为止
istream & getlinnen( char * buf, int bufSize,char delim);
从输入流读取bufSize-1
个字符到缓冲区buf
,或读到碰到delim
字符为止
可以使用if(!cin.getline(...))
判断输入是否结束
bool eof();
判断输入流是否结束
int peek();
返回下一个字符,但不从流中去掉
istream & putback( char c);
将字符ch
放回输入流
istream & ignore(int nCout = 1, int delim = EOF);
从流中删掉最多nCout个字符,遇到EOF时结束
流操纵算子
需要#include<iomanip>
整数流的基数
流操纵算子。十进制dec
,八进制oct
,十六进制hex
,setbase
浮点数的精度
precision
是成员函数,调用方式为
cout.precision(5);
- 1
setprecision
是流操作算子,调用方式为
cout << setprecision(5); //可以连续输出
- 1
定点输出浮点数:
cout << setiosflags(ios::fixed) << setprecision(6) << endl;
- 1
设置域宽
setw
成员函数
cin >> setw(4)
cout << setw(4)
- 1
- 2
width
流操纵算子
cin.width(5);
cout.width(5);
- 1
- 2
宽度不足用空格在左边补上
#include <iomanip>
using namespace std;
int main()
{
int n =141;
//十六进制,十进制,八进制先后输出
cout << hex << n << " " << dec << n << " " << oct << n << endl;
double x =1234567.89, y =12.34567;
//保留5位有效数字
cout << setprecision(5) << x << " " << y << " " << endl;
//保留小数点后5位
cout << fixed << setprecision(5) << x << " " << y << endl;
//科学计数法输出,且保留小数点后5位
cout << scientific << setprecision(5) << x << " " << y << endl;
//非负数显示正号,输出宽度12字符,宽度不足使用'*'填补
cout << showpos << fixed << setw(12) << setfill('*') << n << endl;
//非负数不显示正号,输出宽度12字符,宽度不足使用'*'填补
cout << noshowpos << fixed << setw(12) << setfill('*') << n << endl;
//输出宽度12字符,宽度不足左边用填充字符填充
cout << setw(12) << right << n << endl;
//宽度不足时,负号和数值分列左右,中间用填充字符填充
cout << setw(12)<< internal << n<< endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
用户自定义流操作算子
ostream & tab(ostream & output){
return output << '\t';
}
cout << "aa" << tab << "bb" << endl;
- 1
- 2
- 3
- 4
- 5
文件读写
创建文件
#include <fstream>
ofstream outFile("clients.dat",ios::out|ios::binary);
//clients.dat 要创建的文件的名字
//ios::out输出到文件,删除原有内容
//ios::app输出到文件,保留原有内容,总是在末尾添加
//ios::binary以二进制文件格式打开文件
- 1
- 2
- 3
- 4
- 5
- 6
//也可以先创建ofstream对象,再用open打开
ofstream fout;
fout.open("test.out",ios::out|ios::binary);
- 1
- 2
- 3
//判断打开是否成功
if(!fout){
cout << "File open error!" <<endl;
}
- 1
- 2
- 3
- 4
文件名可以给出绝对路径,也可以给相对路径。默认当前文件夹找文件
文件的读写指针
对于输入文件,有一个读指针
对于输出文件,有一个写指针
对于输入输出文件,有一个读写指针
标识文件操作的当前位置,该指针在哪里,读写操作就在哪里进行
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
location
可以为负值
字符文件读写
#include<iostream>
#include<fstream>
#include<vector>
#include<alogrithm>
using namespace std;
int main(){
vector<int> v;
ifstream srcFile("in.txt",ios::in);
ofstream destFile("out.txt",ios::out);
int x;
while(srcFile >> x)
v.push_back(x);
sort(v.begin(),v.end());
for(int i = 0 ;i < v.size();i++)
destFile << v[i] << " ";
destFile.close();
srcFile.close();
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
二进制文件读写
二进制读文件
istream & read (char * s, long n);
/*将文件读指针指向的地方的n个字节的内容,读入到内存地址s,然后将文件读指针向后移动n字节*/
- 1
- 2
二进制写文件
istream & write(const char * s,long n);
/*将内存地址s处n个字节内容,写入到文件中写指针指向的位置,然后将文件写指针向后移动n字节
以ios::out方式打开文件时,文件写指针开始指向文件开头。
以ios::app方式打开文件时,文件写指针指向文件尾部。
*/
- 1
- 2
- 3
- 4
- 5
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ofstream fout("some.dat", ios::out|ios::binary);
int x =120;
fout.write((const char * )(&x),sizeof(int ));
fout.close();
ifstream fin("some.dat",ios::in|ios::binary);
int y;
fin.read((char * ) &y,sizeof(int));
fin.close();
cout << y << endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
#include<iostream>
#include<fstream>
using namespace std;
struct Student{
char name[20];
int score;
};
//输入
int main()
{
Student s;
ofstream OutFile("c:\\tmp\\students.dat",ios::out|ios::binary);
while(cin >> s.name >> s.score)
OutFile.write((char *) & s,sizeof(s));
OutFile.close();
return 0;
}
//读出
int main()
{
Student s;
ifstream inFile("c:\\tmp\\students.dat",ios::in|ios::binary);
if(!inFile){
cout << "error" << endl;
return 0;
}
while(inFile.read((char *)&s,sizeof(s))){
int readedBytes = inFile.gcount();
cout << s.name << "" <<s.score << endl;
}
inFile.close();
return 0;
}
//修改
{
Student s;
fstream iofile("c:\\tmp\\students.dat",ios::in|ios::out|ios::binary);
if(!ioFile){
cout << "error" << endl;
return 0;
}
iofile.seekp(2*sizeof(s),ios::beg);
iofile.write("Mike",strlen("Mike")+1);
iofile.seekg(0,ios::beg);
while(iofile.read((char *)&s,sizeof(s)))
cout << s.name <<" "<< s.score <<endl;
iofile.close();
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
函数模板
template<class 类型参数1, class 类型参数2,……>
返回值类型 模板名 (形参表)
{
函数体
};
- 1
- 2
- 3
- 4
- 5
template <class T>
void Swap(T & x, T & y)
{
T tmp = x;
x = y;
y =tmp;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
实例:
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(duble &,double & )函数
return 0;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
函数模板中可以有不止一个参数
template <class T1,class T2>
T2 print(T1 arg1,T2 arg2)
{
cout << arg1 << " " << arg2 << endl;
return arg2;
}
- 1
- 2
- 3
- 4
- 5
- 6
函数模板可以重载,只要形参表或类型参数表不同即可
多个函数和函数模板名字相同的情况下,编译器处理顺序
1.先找参数完全匹配的普通函数
2.再找参数完全匹配的模板函数
3.实参经过自动类型转换后能够匹配的普通函数
匹配模板函数时,不进行类型自动转换
//函数模板实例Map
#include<iostream>
using namespace std;
template<class T,class Pred>
void Map(T s, T e, T x,Pred op)
{
for(; s!=e;++s,++x){
*x = op(*s);
}
}
int Cube(int x){
return x*x*x;
}
double Square(double x){
return x*x;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
类模板
//类模板定义
template<typename 类型参数1, typename 类型参数2,……>
class 类模板名
{
成员函数和成员变量
};
//类模板成员函数写法:
template<class 类型参数1, class 类型参数2,……>
返回值类型 类模板名<类型参数名列表>::成员函数名 (参数表)
{
函数体
};
//用类模板定义对象的写法:
类模板名<真实类型参数表>对象名(构造函数实参表);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
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
{
return key<p.key;
}
int main(){
Pair<string,int>student("Tom",19);
cout << student.key << " " <<student.value;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
同一个类模板的两个模板类是不兼容的
## 类模板和派生
- 类模板从类模板派生
- 类模板从模板类派生
- 类模板从普通类派生
- 普通类从模板类派生
类模板和友元
函数,类,类的成员函数作为类模板的友元
函数模板作为类模板的友元
函数模板作为类的友元
类模板作为类模板的友元
类模板与static成员
#include<iostream>
using namespace std;
template <class T>
class A
{
private:
static int count;
public:
A(){count++;}
~A(){count--;}
A(A&){count ++ ;}
static void PrintCount(){cout << count <<endl;}
};
template<> int A<int> :: count = 0;
template<>int A<double>::count = 0;
int main(){
A<int> ia;
A<double> da;
ia.PrintCount();
da.PrintCount();
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
文章来源: blog.csdn.net,作者:沧夜2021,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/CANGYE0504/article/details/105390214
- 点赞
- 收藏
- 关注作者
评论(0)