学习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;
   }

}