8.1、面向对象的标准库
iostream继承层次:istream和ostream是最上层,istream派生出ifstream和istringstream,ostream派生出ofstream和ostringstream。他们两者共同派生出iostream。iostream派生出stringstream和fstream。
标准库类型不允许做复制或赋值操作。导致的现象:(1)如切记这个定义不能定义在main中,要为全局变量àofstream out1,out2;out1=out2;则是不可以的。将out2传递给print(ofstream);函数也是不可以的。由于流对象不能复制,因此不能存储在vector(或其他)容器中。
(2)形参或返回类型也不能为流类型,要传递或返回,必须传递或返回指向该对象的指针或引用。如:ofstream &print(ofstream&){}。或ofstream *print(ofstream*){}
8.2、条件状态
IO标准库的条件状态:(1)strm::iostate,由各个iostream类定义,用于定义条件状态;(2)strm::badbit,strm::iostate类型的值,用于指出被破坏的流;(3)strm::failbit,strm::iostate类型的值,用于指出失败的IO操作;上述三个为特定的位模式,可用于位操作符;(4)strm::eofbit,strm::iostate类型的值,用于指出流已经达到文件结束符;
流方法:(1)s.good()如果流s处于有效状态,该函数返回true。(2)cin.rdstate()能读取流当前的状态,返回一个iostate类型的值。
流必须处于无错状态才能用于输入或输出,如(1)if(cin)//直接检查流的状态;(2)while(cin>>word)//检测条件表达式返回的流,从而间接地检查了流的状态。
多状态的处理:可以这么做,如:is.setstate(ifstream::badbit |ifstream::failbit);
8.3、输出缓冲区的管理
缓冲区内容被刷新的情况:(1)程序正常结束;(2)在一些不确定的时候,缓冲区可能已经满了;(3)用操纵符显示地刷新缓冲区,如endl;(4)在每次输出操作执行完后,用unitbuf操纵符设置流的内部状态,从而清空缓冲区;(5)可将输出流与输入流关联(tie)起来。这种情况,在读输入流时将刷新其关联的输出缓冲区。
程序崩溃了,不会刷新缓冲区。
flush用于刷新流,但与endl不同在于不添加任何字符;ends在缓冲区插入空字符null,然后刷新它,即cout<<1<<ends,1后面会有空格。
unitbuf操纵符:cout<<unitbuf<<”output”<<nounitbuf;//nounitbuf操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。
将输出和输入捆绑在一起:感觉没多大意思···如,cin.tie(&cout);…cin.tie(0);//调用tie传递0表示打破该流上存在的捆绑。
8.4、文件的输入和输出
头文件是fstream。如输入文件:ofstream/ifstream infile(ifile.c_str());//ifile是希望读写的文件名的string对象。或者写法为ofstream outfile;再用outfile.open(“out.txt”);。打开文件后,检查打开是否成功(这种习惯要养成)。if(!outfile){cerr<<相关信息;}
如果outfile要关联其他的文件,则要先关闭原先的文本,再打开另一个文件。
如果打算重用已存在的流对象,那么while循环必须在每次循环时记得关闭(close())和清空(clear())文件流。这边关闭和清空顺序随意~。
8.4.2、文件模式
文件模式:(1)in——打开文件做读操作;(2)out——打开文件做写操作;(3)app——在每次写之前找到文件尾;(4)ate——打开文件后立即将文件定位在文件尾;(5)trunc——打开文件时清空已存在的文件流;(6)binary——以二进制模式进行IO操作。
ofstream对象指定out模式等效于同时指定out和trunc模式。对于ofstream打开的文件,要保存文件中已存在的数据,唯一方法是显示地指定app模式打开:ofstream outfile(“a.txt”,ofstream::out |ofstream::trunc);
默认情况下,fstream对象以in和out模式同时打开。当文件同时以in和out打开时不清空。
8.5、字符串流
头文件为sstream。
stringstream特定的操作:(1)stringstream strm;创建自由的stringstream对象;(2)stringstream strm(s);创建存储s的副本的stringstream对象,其中s是string类型的对象(不能用字符串字面值直接进行赋值···如strm(“hello”)是错误的);(3)strm.str();创建strm中存储的string类型对象;(4)strm.str(s);将string类型的s复制给strm,返回void。这边可以用字符串字面值,如strm.str(“word”);是可以的。
有些处理基于每行实现(getline可以实现),而其他处理则要操纵每行中每个单词(每次一个单词可以cin>>string类型变量),可借助stringstream对象实现,如:
string line,word;
while(getline(cin,line)){//读取一行
istringstreamstream(line);
while(stream>> word){//读取单个词
cout<<word<<endl;
}
}
stringstream提供的转换和/或格式化,如:
int val1 = 512,val2 = 1024;
ostringstreamformat_message;
format_message << "val1: " << val1 <<"\n" << "val2:" << val2 << "\n";
istringstreaminput_istring(format_message.str());
string dump1,dump2;
input_istring >> dump1 >>val1 >> dump2 >>val2;//注意这边的顺序,相当于输入了format_message.str(),即输入val1:512\nval2:1024。这边\n没关系,就好比cin>>s1>>s2>>s3>>s4;
你输入各种回车,都是忽略的。
cout<<dump1<<"--"<<dump2<<endl;
cout<<val1<<" "<<val2<<endl;
当i=0时:cout<<i++<<i++<<i++<<endl;为210,网上说跟编译器有关,无需太纠结
cout<<++i<<++i<<++i<<endl;为333。