zoukankan      html  css  js  c++  java
  • 【转载】C++ IO库

    本篇随笔为转载,原贴地址:《C++ Primer》第8章 IO库 学习笔记

    1.IO类

     1 #include <iostream>
     2 istream//从流中读取数据
     3 ostream//从流中写入数据
     4 iostream//读写流
     5 
     6 #include <fstream>//文件
     7 ifstream
     8 ofstream
     9 fstream
    10 
    11 #include <sstream>//字符串
    12 istringstream
    13 ostringstream
    14 iostringstream

    fstream和sstream都继承于iostream,所以iostream有的操作他们都有。

    另外流前面加字母w表示针对宽字符。

    2.IO对象无拷贝和赋值

    1 ostream o1,o2;
    2 o1 = o2;
    3 ostream o3(o1);

    错误,不能拷贝和赋值

     因为流不能拷贝和赋值,所以流作为函数参数或者是返回值必须是引用类型,且读写一个IO对象会改变其状态,

    因此传递和返回的引用不能是const的

    就好像

    const成员函数不可改变对象内容,同时也不可通过函数返回值改变对象内容。 所以返回指向对象的指针

    或引用都会被编译器拦住的。 const指针或const引用不会改变对象内容,所以可以返回。

    3.IO条件状态

    1 strm代表一种IO类型,流处于好的状态时这些bit位全部处于0。
    2 
    3 strm::iostate   iostate一种机器相关类型,提供了表达条件状态的完整功能
    4 strm::badbit    指出流已经崩溃
    5 strm::failbit   指出IO操作失败
    6 strm::eofbit    指出流达到了文件的末尾
    7 strm::goodbit   指出流处于未错误状态
    1 s.eof()          若流处于eofbit,返回true
    2 s.fail()         若流处于failbit,返回true
    3 s.bad()          若流处于badbit,返回true
    4 s.good()         若流处于有效状态,返回true
    5 s.clear()        将流所有状态恢复,设置为有效,返回void
    6 s.clear(flag)    将指定bit位恢复,设置为有效,返回void。flag类型为strm::iostate
    7 s.setstate(flag) 根据给定的bit标志位,将流s中对应条件状态位置位。flag类型为strm::iostate
    8 s.rdstate()      读取当前的状态

    例子:

     1 #include <iostream>
     2 #include <fstream>
     3 
     4 using namespace std;
     5 
     6 istream& read(istream& is)
     7 {
     8     int i;
     9     while(is >> i && i != EOF)         
    10     {
    11         cout << i << endl;
    12     }
    13     cout << "eof:" << is.eof() << endl;    
    14     cout << "fail:" << is.fail() << endl;
    15     cout << "bad:" << is.bad() << endl;
    16     cout << "good:" << is.good() << endl;
    17     cout << "rdstate " << is.rdstate() << endl;
    18     
    19     cout << endl;
    20 
    21     //is.clear();和下面等价
    22     is.clear(is.rdstate() & ~is.failbit & ~is.eofbit);
    23     //is.setstate(is.eofbit);设置了后,rdstate()结果是2
    24 
    25     cout << "eof:" << is.eof() << endl;
    26     cout << "fail:" << is.fail() << endl;
    27     cout << "bad:" << is.bad() << endl;
    28     cout << "good:" << is.good() << endl;
    29 
    30     cout << endl;
    31     cout << "rdstate " << is.rdstate() << endl;
    32     
    33     return  is;
    34 }
    35 
    36 int main()
    37 {
    38     read(cin);
    39 
    40     return 0;
    41 }

    结果,上面是未注释掉is.setstate(is.eofbit);的结果

     下面是注释掉的结果:

    还有一种可以保存流当前状态,清空,然后再恢复。

    1 auto old_state = is.rdstate( );
    2 is.clear( );
    3 is.setstate(old_state);

    4.管理缓冲区

    1 #include <iostream>
    2 using namespace std;
    3 
    4 int main()
    5 {
    6     cout << "hi!" << endl;
    7     cout << "hi!" << ends;   //缓冲区插入一个字符,然后刷新
    8     cout << "hi!" << flush;  //刷新缓冲区,不输出任何字符
    9 }

    5.关联输入输出缓冲区

     任何试图从输入流读数据的操作都会先刷新关联的输出流。

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main()
     5 {
     6     int i;
     7     cin >> i;                    //刷新cout 和 cerr;
     8     ostream *old_str;    
     9     old_str = cin.tie(nullptr);  //解开流,传递一个空指针。返回旧解
    10     ostream &os = cout;          //新建一个流
    11     cin.tie(&os);                //绑定这个新流
    12     cin >> i;
    13     cin.tie(old_str);            //恢复以前的状态
    14 }

    6.文件的输入和输出

    头文件定义了三种IO

    ifstream从文件中读取数据

    ofstream向一个文件写数据

    fstream可以读写

     1 //open:流用open和文件关联起来,如果open失败,failbit会被置位。因为open可能会失败,所以检查流是个好习惯
     2 //close:当将流文件关联到另外一个文件时,必须用close关闭当前的文件。
     3 
     4 #include <iostream>
     5 #include <fstream>
     6 #include <string>
     7 
     8 using namespace std;
     9 
    10 std::istream& read(std::istream& is, std::string& s) //不写引用就成为了副本
    11 {
    12     is >> s;
    13     return is;
    14 }
    15 
    16 std::ostream& print(std::ostream& os, std::string& s)//可以向iostream传递fstream,因为是派生类,不过对文件最好使用fstream
    17 {
    18     os << s;
    19     return os;
    20 }
    21 
    22 
    23 int main(int argc, char *argv[])
    24 {
    25     std::ifstream input(argv[1]);
    26     std::ofstream output(argv[2]);
    27 
    28     std::string s;
    29     read(input, s);
    30     std::cout << s << std::endl;
    31     print(output, s);
    32     std::string ss;
    33     //std::getline(ss, argv[1]);  读取一行
    34     std::cin >> ss;
    35 
    36     std::string ifile = "file2";
    37     std::ifstream in(ifile);    //新建一个文件流,并且初始化,初始化意味着open()
    38     std::ofstream out;
    39     out.open(ifile + ".copy");  //调用open()
    40     if(out);                    //如果流没错
    41     out << ss;
    42     out.close();                //没有close()下面error         close关闭流,一个流不能重复打开多个文件
    43     out.open("file");
    44     if(out)
    45         std::cout << out.good() << endl;
    46     else
    47         std::cerr << "error" << std::endl;
    48 } 

    课后题8.5

     1 #include <iostream>
     2 #include <fstream>
     3 #include <string>
     4 #include <vector>
     5 
     6 using namespace std;
     7 
     8 int main(int argc, char *argv[])
     9 {
    10     string s;
    11     fstream input(argv[1]);
    12     vector<string>ivec;
    13 
    14     while(!input.eof())//如果去掉if(input.fail())末尾会多输出一次
    15     {
    16         input >> s;
    17         if(input.fail())
    18         {
    19             cout << "fail " << endl;
    20             break;
    21         }
    22         ivec.push_back(s);
    23     }
    24 
    25     for(string &s : ivec)
    26     {
    27         cout << s << endl;
    28     }
    29 }

     没有if(input.fail( ))检查时,末尾总是会多输出一次文件末尾的内容。

     看代码,文件每次读取到s中,然后push_back(s),当文件读取到最后一次时(它自己不知道读取到最后了),push_back(s)后再次读取,

     发现到达末尾了,此时s中依然存着上一次的内容,push_back(s)后退出循环,所以最后一行s被push了两次,输出时当然输出两遍了。

    7.文件模式

    1 fstream fs("文件名", mode); //mode就是文件模式
    2  
    3 in         以读的方式打开
    4 out        以写的方式打开     
    5 app        每次写操作前均定位到末尾
    6 ate        打开文件后立刻定位到文件末尾
    7 trunc      截断文件
    8 binary     以二进制方式IO

    <1.只对ofstream或fstream设置out模式,out模式打开会丢弃已有数据

    <2.只对ifstream或fstream设置in模式

    <3.只有当out也被设定时才可以设定trunc模式

    <4.只要trunc模式没被设定,就可以设定app模式,在app模式下即使没有规定out也默认为out模式

    <5.没有指定trunc,以out打开也会截断文件,除非指定app,或同时打开in模式

    <6.ate和binary可以用于任何类型的文件流对象,且可以和其他任何文件模式组合。

    <7.每次调用open都可以指定文件模式。

    8.sstream流

    1 三个IO
    2 istringstream
    3 ostringstream
    4 stringstream
    5 特有操作
    6 sstream strm;       strm是一个未绑定的stringstream对象
    7 sstream strm(s);    strm是一个sstream对象,保存s的一个拷贝,此构造函数是explicit的
    8 strm.str();         返回strm所保存的string的拷贝
    9 strm.str(s);        将string s拷贝到strm中,返回void

    使用istringstream流

     istringstream读字符串时遇见空格算一个字符串,就可以读一个句子的单词。

     1 #include <iostream>
     2 #include <vector>
     3 #include <sstream>
     4 #include <string>
     5 #include <fstream>
     6 
     7 using namespace std;
     8 
     9 class record
    10 {
    11     public:
    12         string name;
    13         vector<string>phone;
    14 };
    15 
    16 int main(int argc, char *argv[])
    17 {
    18     ifstream input(argv[1]);
    19     string s;
    20     vector<record>Info;
    21     while(getline(input, s))
    22     {
    23         record re;
    24         istringstream is(s);
    25         is >> re.name;
    26         cout << "eof" << is.eof() << endl;
    27         while(!is.eof())  //while(is >> s)另外一种方法,不用测试eof,且注意eof成立为1
    28         {
    29             string s;
    30             is >> s;
    31             re.phone.push_back(s);
    32         }
    33         Info.push_back(re);
    34     }
    35 
    36     for(record &rec : Info)
    37     {
    38         cout << rec.name << " ";
    39         for(string &ph : rec.phone)
    40         {
    41             cout << ph << " ";
    42         }
    43         cout << endl;
    44     }
    45 }

    使用ostringstream流

    ostringstream流里面可以保存字符串的拷贝。需要时输出。

    比如检查一个字符串是否正确,正确的保存到流里,不正确的不保存,等到结束时输出全为正确的。

    1     string st = "asdasdasdasd";
    2     string st1;
    3     ostringstream os;
    4     os << " " << st<< endl;         //都写到了流里面
    5     os << " " << st << endl;
    6     cout << os.str() << endl;       //输出字符串流里面保存的字符串,返回                          字符串的拷贝
    7     os.str("");                     //使用前清空
    8     os.str(st);
    9     cout << os.str() << endl;        

    小结:

    1.iostream处理控制台IO

    2.fstream处理命名文件IO

    3.stringstream完成内存string的IO

    4.类fstream和sstream都继承自iostream,所以iostream的操作这些类也可以。

    5.每个流都有一组条件状态,保证流正确无误的使用就要保证流的状态正确无误

    6.为什么可以while(cin)来判断流状态,因为cin对象中重载了bool转换操作,如operator bool(),所以cin才能够参加布尔运算.

  • 相关阅读:
    mysql中的where和having的区别
    php解决前后端验证字符串长度不一致
    复习
    SQL语句执行顺序
    领域驱动设计(DDD)
    什么是ORM?为啥要是用ORM?
    Python web框架搭建
    Python web自动化环境搭建
    Jmeter录制手机app脚本
    Charles截取 Https 通讯信息
  • 原文地址:https://www.cnblogs.com/niuxichuan/p/5839314.html
Copyright © 2011-2022 走看看