• C++ IO流小结


    撒花庆祝下,终于看完了(C++Primer)第一部分,即将进入第二部分!

    IO部分,最基本的是iostream(istream、ostream),子类有fstream(ifstream、ofstream)和sstream(istringstream、ostringstream)。

    iostream是控制窗口输入输出。

    fstream是文件输入输出。

    sstream是字符串输入输出(内存中)。

    如果两种类型存在继承关系,则可以说一个类“继承”了其父类的行为——接口。
    C++ 中所提及的父类称为基类(base class) ,而继承而来的类 则称为派生类(derived class)

     
    IO 类型在三个独立的头文件中定义:
        iostream 定义读写控制窗口的类型, fstream 定义读写已命名文件的类型,而 sstream 所定义的类型则用于读写存储在内存中的 string 对象。
        在 fstream 和 sstream 里定义的每种类型都是从 iostream 头文件中定义的相关类型派生而来。
    wchar_t、wiostream。。。
     
    IO流不允许赋值或者复制
    所以,
    ①函数形参和返回值不能是IO流对象,必须是引用,而且形参不能是const--因为读写都会改变状态。
    ②只有支持复制的元素类型可以存储在 vector 或其他容器类型里。由于流对象不能复制,因此不能存储在 vector (或其他)容器中 (即不存在存储流对象的 vector 或其他容器)。

    所有的流对象,都包含一个条件状态成员,该成员由setstate clear 操作管理。该成员类型为iostate 。另外有三个常量,代表三种状态,可进行操作。badbitfailbiteofbit
    流的状态检查操作则有:bad、fail、eof、good。如果bad、fail、eof中任一个返回true,则流处于错误状态。否则good操作返回true。
    clear和setstate操作用于改变条件成员的状态。clear会重设为有效状态。setstate用于打开某个条件,用于表示某个问题的发生。setstate会保留其他状态。
     
     
    IO缓冲区每个io流对象都管理一个缓冲区!用于存储程序读写的数据。
    除了自动刷新缓冲区之外,还可以手动刷新缓冲区:endl、flush、ends。
    另外,如果想让io流刷新输出每次读写的数据,可以使用unitbuf
    cout<<unitbuf<<"first"<<" second"<<nounitbuf ; //相当于cout<<"first"<<flush<<"second"<<flush ;
     
    警告:如果程序崩溃了,则不会刷新缓冲区!!    这个特性可以用来查找错误,只能是在最后输出语句的后面。
     
    ----------------------------------
    当输入流和输出流到一起时,任何读输入流的尝试,都将刷新其输出流关联的缓冲区。
    标准库将cout和cin绑定到一起,所以,任何cin语句,都会导致cout缓冲区的刷新。
    注意:只是刷新!没有传递数据!!!且一个对象只能绑定一个对象。
     
    交互式系统通常应确保它们的输入和输出流是绑在一起的。这样可以保证任何输出都是在试图读之前进行。
    cin.tie(0); //断开默认的tie(默认cin.tie(&cout))
    cin.tie(&cerr); //重新绑定
    ----------------------------------
     
    文件操作
    fstream 类型除了继承下来的行为外,还定义了两个自己的新操作—— open close,以及形参为要打开的文件名的构造函数。

    需要读写文件时,则必须定义自己的对象,并将它们绑定在需要的文件上。
    假设 ifile 和 ofile 是存储希望读写的文件名的 strings 对象,可如下编写代码: 
    // construct an ifstream and bind it to the file named ifile 
    ifstream infile(ifile.c_str()); 
    // ofstream output file object to write file named ofile 
    ofstream outfile(ofile.c_str());

    也可以如下编写代码:
    ifstream infile;
    ofstream outfile;
     
    infile.open(ifile.c_str());
    outfile.open(ofile.c_str());
     
    为了实现读写,需要将指定的文件打开定位open 函数完成系统指定的所有需要的操作。
     
    打开文件后,检查是否正确打开是个好习惯:if(!infile)...//如果没打开。
     
    注意:历史原因,只能使用C风格字符串作为文件名。
     
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main(){
        
        cout<<"endl!"<<endl;
        cout<<"flush!"<<flush;//
        cout<<"null-terminated ends!"<<ends;
        
        cout<<"
    ";
        //一次性刷新所有输出
        cout<<unitbuf<<"first"<<" second"<<nounitbuf; //cout<<"first"<<flush<<"second"<<flush;
        
        cout<<"
    ";
        ///=----------------------
        ostream *old_tie = cin.tie(); 
        cout<<"old_tie:"<<old_tie<<endl;
        cin.tie(0);
        cin.tie(&cerr); //why &?
        
        cerr.tie(0);
        cerr.tie(&cout);
        
        string str;
        cin>>str;
        cerr<<"hehe";//如何不刷新? 
        cerr<<"hehe";//如何不刷新? 
        
        cin>>str;//再来一次 
        cerr<<str;
        cout<<str;
        
        return 0;
    }
    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main(){
        string infile="abc";
        string outfile="abc";
        ifstream in(infile.c_str());
        ofstream out(outfile.c_str());
        
        if(!in){
            cerr<<"Error: unable to open file:"<<infile<<endl;
            return -1;
        }
        if(!out){
            cerr<<"Error: unable to open file:"<<outfile<<endl;
            return -1;
        }
            
        return 0;
    }
    //这个代码有问题,忽略吧
    #include <iostream>
    #include <string>
    #include <stdexcept>
    
    using namespace std;
    
    void run1();
    void run2();
    istream &getistream(istream &in);
    
    int main(){
        run1();
    //    run2();
    //    
    //    getistream(cin);//注意,io流不可复制或赋值。 
    //    if(cin){
    //        cout<<"OK!"<<endl;
    //    }else{
    //        cout<<"sth is wrong"<<endl;
    //        if(cin.eof()){
    //            cout<<"eof was not cleared!"<<endl;
    //        }
    //        if(cin.bad()){
    //            cout<<"bad was not cleared!"<<endl;
    //        }
    //        if(cin.fail()){
    //            cout<<"fail was not cleared!"<<endl;
    //        }
    //        return -1;
    //    }
        
        
        return 0;
    }
    
    void run1(){
        int val;
        while(cin>>val, !cin.eof()){//有输入,不是结尾,就继续 。逗号运算符,返回右边的结果 
            if(cin.bad()){
                cout<<"input stream damaged!"<<endl;
                throw runtime_error("IO stream corrupted");
            }
            if(cin.fail()){
                cerr<<"bad input!"<<endl;
    //            cin.clear(istream::failbit);//
    //            cin.clear();
    //            cin.clear(istream::goodbit);
                cin.clear(istream::failbit);
                cin.clear(istream::badbit);
                cin.clear(istream::eofbit);
    //            cin.clear();//why this does not work? 
                
    //            cin.ignore(std::numeric_limits<std::streamsize>::max(), '
    '); 
                cout<<"try again.."<<endl;
                continue;
            }
            cout<<val<<endl;
        }
    }
    
    void run2(){
        string str;
        cout<<"type sth .."<<endl;
        cin>>str;
        iostream::iostate old_state= cin.rdstate();//
        cout<<old_state<<endl;
        cin.clear();//what?
        //...
        cin.clear(old_state);//清除旧状态,而非设置旧状态!设置应该是setstate。这里书上弄错了吧。 
        
    }
    
    istream &getistream(istream &in){
    //    iostream::iostate old_state = in.rdstate();
        cout<<"type sth.."<<endl;
        
        string str;
        while(in>>str, !in.eof()){
            //
            if( in.fail() || in.bad()){
                cerr<<"fail or bad";
                in.clear();
                continue;
            }
            cout<<"you typed: "<<str<<endl;
        }
    //    in.setstate(old_state);
    //    in.clear(old_state);//for what?
        in.clear();//恢复正常 
        return in;
    }
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    ifstream &openfile(ifstream &in, string &filename);
    ofstream &savefile(ofstream &out, string filename);
    
    //复制文件练习 
    int main(){
        string filename="e:/DbUtil.java";
        string filename2="e:/DbUtil1.java";
        ifstream in;
        ofstream out;
        openfile(in, filename);
        savefile(out,filename2);
        
        string line;
        while(getline(in, line)){
            out<<line<<endl;
        }
        in.close();
        out.close();
        
        return 0;
    }
    
    ifstream &openfile(ifstream &in, string &filename){
        in.close();
        in.clear();
        
        in.open(filename.c_str());
        
        return in;
    }
    
    ofstream &savefile(ofstream &out, string filename){
        out.close();
        out.clear();
        
        out.open(filename.c_str(),ofstream::app);
        return out;
    }
    ----------------------------------
     
     
    打开文件需要指定打开的mode,这是文件自身的属性!
    mode:in、out、app、ate、trunc、binary。
    单纯以out打开,会丢失所有内容。类似out|trunc。
    fstream对象默认以in|out模式打开,不清空!!!
    fstream inOut("xxx", fstream::in | fstream::out);

    ate是个什么鬼?app会在每次写操作之前都把写指针置于文件末尾,而ate模式则只在打开时才将写指针置于文件末尾。ate模式在文件操作过程中,可以通过seekp等操作移动指针位置。

     
    ------------------------------------------------
    sstream,用于从内存中的字符串读取数据,或,向内存中的字符串写入数据!
    也可以用于格式转换!!!其实就是通过特定类型的变量来接收!
     
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    ifstream &openfile(ifstream &in, string &filename);
    
    int main(){
        string filename="e:/DbUtil.java";
        ifstream in;
        openfile(in, filename);
        
        string line, word;
        
        while(getline(in, line)){
            istringstream strin(line);
            ostringstream strout(line); 
            while(strin>>word){
                strout<<word<<endl;//输出到string了,看不到 
                cout<<word<<endl;//输出string到控制台 
            }
        }
        in.close();
        in.clear();
        
        return 0;
    } 
    
    ifstream &openfile(ifstream &in, string &filename){
        in.close();
        in.clear();
        
        in.open(filename.c_str());
        
        return in;
    }
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    //字符串格式转换 
    int main(){
        
        int val1=100,val2=500;
        string line, word;
        ostringstream out;
        out<<"val1: "<<val1<<"
    "
            <<"val2: "<<val2<<"
    ";
        
        cout<<out.str()<<endl;
        
        string dump;
        
        istringstream in(out.str());
        in>>dump>>val1>>dump
            >>dump>>val2>>dump;
        
        cout<<val1<<"--"<<val2<<endl;    
        
        return 0;
    } 


     
     注意:i或o是相对内存来说的。将内容读入内存,是in;将内存中的内容输出,是out。
     
     
     
    参考:
     
  • 相关阅读:
    vmware fusion和mac共享目录
    安卓linker源码阅读01
    sublime text 快捷键
    eclipse使用经验汇总
    递归池:
    ubuntu下adb红米
    蛋疼问题汇总you must restart adb and eclipse
    JNI
    ARM寻址
    了解装饰器
  • 原文地址:https://www.cnblogs.com/larryzeal/p/5597163.html
Copyright © 2020-2023  润新知