学习C++ Primer IO库
IO库类型及头文件:iostream(istream、ostream、iostream)、fstream(ifstream、ofstream、fstream)、sstream(istringstream、ostringstream、stringstream)
IO对象无拷贝或者赋值
ofstream os(path);//对
ofstream os1;
os1=os;//错,不能赋值
ofstream os2(os1);//错,不能初始化
读写一个io对象,会改变其状态,因此传递或者返回的对象必须是引用,且不能是const.
IO的一些条件状态(C++ primer 279)。
/*
练习8.1
*/
istream& printOut(istream& is){
auto old_state=is.rdstate();
is.seekg(0,ios::end);
long len=is.tellg();
is.seekg(0,ios::beg);
char* data=(char*)malloc(len);
is>>data;
cout<<data;
free(data)
is.clear();
is.setstate(old_state);
return is;
}
关联输入和输出流
当一个输入流关联到任何一个输出流的时候,任何试图去操作输入流的数据时,都会先刷新关联的输出流。标准库将cout和cin关联在一起,因此
cin>>val;会刷新cout的缓冲区.
tie函数有两个重载版本,一个是不带参数的tie(),如果本对象没有关联到任何一个输出流的对象时,返回的是一个空指针,否则返回的是关联的输出流指针.
带参数的tie(iostream*),传递一个ostream的指针,将本对象与传递的ostream对象相关联.
ostream os*=cin.tie(nullptr);//cin不再与其他流关联
cin.tie(&cerr);//cin与cerr关联
cin.tie(os);//cin与cout重新关联
文件的输入与输出
ifstream in(path);//创建一个文件输入流并打开path路径下的文件
ofstream out;//输入流未关联到文件
/*
读取path路径下的文件;
*/
ifstream in;//构造一个文件输入流
in.open(path,ios::in);//以读取模式打开指定路径下的文件,如果并未指定打开的模式,那么将以默认的模式打开,ifstream默认的模式就是读取模式
string data;
in>>data;//将in流中的数据出入到data中
in.close();//关闭in流
/*
写出路径为path的文件
*/
ofstream out(path);
string data="Hello C++";
out<<data;
out.close();
注意: 当文件流是以out模式打开的时候,如果原文件本身存在,那么会先清空文件原来的数据,然后重新写入新的数据,如果不想清空原来的数据,那么可以以app模式打开文件
ofstream out(path,ios::app);//会直接在文件末尾添加新的内容
ofstream out(path,ios::ate);//打开文件会直接定位到文件末尾
我们要养成检查流的状态,然后再进行下一步操作的习惯
eg: if(out) or while(out){
//........
}
/*
8.4练习
*/
void lineVec(string path){
ifstream is(path);
vector<char*> vecStr;
char line[1024];
while (is.getline(line,sizeof(line))) {
vecStr.push_back(line);
}
is.close();
}
/*
8.5练习
*/
void charVec(string path){
ifstream is(path);
vector<char> charVec;
char little;
while(is.get(little))
charVec.push_back(little);
for (auto c:charVec) {
cout<<c;
}
is.close();
}
string流
/*
phone.txt的内容
wade 12331231 123123123
kobe 2131 123123 123123
james 87713 2323 1231278
*/
char line[1024];
char word[1024];
vector<PersonInfo> persons;
ifstream is("/Users/jy/Downloads/phone.txt",ios::in);
while (is.getline(line, 1024)) {
PersonInfo info;
istringstream ss(line);
ss>>info.name;
while (ss>>word) {
info.phones.push_back(word);
}
persons.push_back(info);
}
我们常用的处理字符串的流为:sstream(istringstream,ostringstream),上面的例子,存在的疑问就是ss>>info.nam,为什么只把一行的名字输入进info.name,而不是整行的数据,下面的while(ss>>word),输入word只是后面的数字,而不是整行的内容??
/*
假定valid()是校验手机号码格式是否正确的函数,format()是格式化字符串的函数
ostringstream用法
*/
for(auto const& entry:persons){
ostringstream badnums,formatted;//每一步循环创建一个输出格式不正确,和格式化的字符串输出流
for(auto& const phone:entry.phones){
if(!valid(phone)){
badnums<<phone;
}else{
formatted<<phone;
}
}
if(badnums.str().empty()){
os<<entry.name<<" "<<formatted.str()<<endl;
}else{
cerr<<"error phone:"<<entry.name<<""<<badnums.str()<<endl;
}
}