【转载】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才能够参加布尔运算.

时间: 2024-10-19 09:57:03

【转载】C++ IO库的相关文章

《C++primer(第五版)》学习之路-第八章:IO库

[ 声明:版权所有,转载请标明出处,请勿用于商业用途.  联系信箱:[email protected]] 8.1 IO类 1. istream(输入流)类型,提供输入操作 ostream(输出流)类型,提供输出操作 cin,一个istream对象,从标准输入读取数据 cout,一个ostream对象,向标准输出写入数据 cerr,一个ostream对象,通常用于输出程序错误信息,写入到标准错误 >>运算符,用来从一个istream对象读取输入数据 <<运算符,用来向一个ostrea

C++ Primer 读书笔记: 第8章 标准IO库

第8章 标准IO库 8.1 面向对象的标准库 1. IO类型在三个独立的头文件中定义:iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,而sstream所定义的类型则用于读写存储在内存中的string对象.在fstream和sstream里定义的美中类型都是从iostream头文件中定义的相关类型派生而来. 2. 流对象不能复制,因此不能存储在vector容器中 3. 形参或返回类型也不能为流类型.如果需要传递或返回IO对象,则必须传递或返回指向该对象的指针或引用.

[APUE]标准IO库(下)

一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中"表3-1中的最佳时间即<程序1>","表3-1中的单字节时间指的是<程序1>中BUFSIZE为1时运行时间结果",fgetc/fputc版本程序这里没放出] 对于三个标准IO版本的每一个其用户CPU时间都大于最佳read版本,因为每次读一个字符

在UNIX系统下使用IO库程序

在上一篇文章中,我们已经可以在UNIX下编译一个hello world 程序了.今天介绍UNIX系统下,如何在程序中使用IO库. 主体流程分为以下三步:(代码参考的是:<<C++ Primer>>) 第一步:新建文件,并命名为“Progr1.cpp” 第二步:在Progr1.cpp中写好main函数,并使用cin ,cout 这两个IO库函数.代码如下 #include <iostream>//告诉编译器要使用 iostream 库.尖括号里的名字是一个.头文件.程序使

C++ Primer学习总结 第8章 IO库

 第8章 IO库 1.    IO类继承关系: 2.    查询iostream流状态P280-281 V是一个int,当我们输入1, 'r',或Ctrl+z 时的输出分别如下: cin.clear()可以清楚所有的错误位,使good()返回true. 3.    fstream对文件的读写P284 初始创建读入和写出fstream对象之后,把fin和fout完全看成cin和cout处理即可,它们操作几乎没有区别. 4.    对同一个文件同时打开进行读写会出现不可预知的BUG. 对于文件的操作

读书笔记-APUE第三版-(5)标准IO库

ISO C标准I/O库使用流的概念读写文件.流是对数据传输的抽象,可以把流理解为从起点到终点间的字节序列. 标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率.之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针. typedef struct{ short level;/*缓冲区满程度*/ unsigned flags;/*文件打开状态标志*/ char fd;/*文件描述符*/ unsigned char hol

Node.js websocket 使用 socket.io库实现实时聊天室

认识websocket WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duple).一开始的握手需要借助HTTP请求完成. 其实websocket 并不是很依赖Http协议,它也拥有自己的一套协议机制,但在这里我们需要利用的socket.io 需要依赖到http . 之前用java jsp写过一个聊天,其实实现逻辑并不难,只是大部分时间都用在UI的设计上,其实现原理就是一个基于websocket的通信,要想做一个好的聊天室,我觉得大部

Unix环境之标准IO库

UNIX的文件IO都是针对文件描述符的,而标准IO的操作则是围绕流进行的.当一个流最初被创建时,它并没有定向.若在未定向的流上使用一个多字节IO函数,则将该流的定向设置为宽定向:若在未定向的流上使用一个单字节IO函数,则将该流的定向设置为字节定向. stdio.h定义了三个标准流,stdin.stdout和stderr,分别是标准输入.标准输出和标准出错. 缓冲-- 标准IO库提供缓冲的目的是尽可能减少使用read和write调用的次数.它也对每个IO流自动地进行缓冲管理,从而避免了应用程序需要

嵌入式 Linux系统编程(三)——标准IO库

嵌入式 Linux系统编程(三)--标准IO库 与文件IO函数相类似,标准IO库中提供的是fopen.fclose.fread.fwrite等面向流对象的IO函数,这些函数在实现时本身就要调用linux的文件IO这些系统调用. 一.标准IO库函数的缓冲机制 由于IO设备的访问速度与CPU的速度相差好几个数量级,为了协调IO设备与CPU的速度的不匹配,对于块设备,内核使用了页高速缓存,即数据会先被拷贝到操作系统内核的页缓存区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间. 当应用程序尝