之前用endl一直以为它只是一个回车换行的功能,刚刚才知道原来endl还有一个功能使用来刷新缓冲区的。除了endl之外,c++中还有ends,flush,unitbuf,nounitbuf。为什么要刷新缓冲区呢?
一句话,为了让缓冲区的信息立即强制输出。
如: cout << "aaa" << endl;和 cout << "aaa";都能将aaa输出,前一个除了多了一个换行外,它的aaa是被手动强制输出的,而后便一个aaa是系统每隔一段时间进行检测输出的。由于间隔 比较短,让人以为和第一种一样,下面有一段代码让你对刷新缓冲有明显的概念。
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
setvbuf( stdout, NULL, _IOLBF, 1024 ); //设置控制台输出为行缓存模式,把缓冲区与流相关
cout <<"hello world\n";
Sleep(5000);
cout <<"leeboy" <<endl;
system("pause");
return 0;
}
所以编程要形成好的习惯,多使用endl




(1)条件状态
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int ival;
while (cin >> ival, !cin.eof())
{//逗号操作符,从右向左计算每个操作数,返回最右边的操作结果
if (cin.bad()){ // input stream is corrupted; bail out
// throw runtime_error("IO stream corrupted");
//这句不能执行,暂将其注掉}
if (cin.fail())
{ // bad input
cerr<< "bad data, try again\n"; // warn the user
//cin.clear(istream::failbit); // reset the stream
//reset failbit会使程序一直进入这个if陷入死循环,该是goodbit,如下.
cin.clear(istream::goodbit);
//cin.clear();//goodbit,falibit,badbit都重置为true
cin.sync();//清空cin缓冲区里面未读取的信息
//没有sync则cin会一直读取其缓冲区内的错误内容,fail()一直为真,陷入死循环
continue; // get next input
}
cout<<ival;
}
system("PAUSE");
return EXIT_SUCCESS;
}
所有流对象都包含一个iostate类型的由setstate与clear操作管理的条件状态成员.
该状态成员有下面4个位标志位.
badbit系统级错误该流通常不能再用,如无法回复的读写错误
failbit可修正错误,如给整型变量输入字符
eofbit遇到文件结束符
goodbit只有上面三个全不为true时cin.good()返回的goodbit才为true
istream::iostate old_state=cin.rdstate();
//rdstate()返回一个iostate类型值
cin.clear();
{...}//使用全部重置的cin
cin.clear(oid_state);恢复
is.setstate(ifstream::badbit | ifstream::failbit);//给is流添加指定条件
setstate()函数并不强制覆盖流的原状态,而是将括号内参数所代表的状态叠加到原始状态上。
(2)
输出缓冲区:
每个io对象管理一个缓冲区,用于存储程序的读写数据.
os<<"hello world!";将该字符串存入流os关联的缓冲区.下面几种情况导致缓冲区内容被刷新(flush即写入输出设备或文件中)
1,程序正常结束.
2,缓冲区满,会在写下一个值之前刷新.
3,使用操纵符endl,ends,flush.显示刷新
cout<<"hi"<<endl;//插入一个换行,然后flush
cout<<"hi"<<ends;//插入一个null,然后flush
cout<<"hi"<<flush;//直接flush
4,用unitbuf操纵符设置流的内部状态,前面这句我也没看懂反正就是使每次执行完写操作后都添加一个flush
cout<<unitbuf<<"first"<<"second"<<nounitbuf;
上句等价于cout<<"first"<<flush<<"second"<<flush;
5,使用tie将输入和输出流绑定在一起,在读入流时都先flush其输出流关联的缓冲区.
标准库把cout,cin关联一起,cin>>ival时使cout关联的缓冲区被flush.
呵呵,tie看得我蛋疼,估计也没几个人看上面就能明白,继续查资料,
ostream* tie ( ) const; //返回指向绑定的输出流的指针。
ostream* tie ( ostream* tiestr ); //将tiestr指向的输出流绑定到调用该函数的对象上,并返回上一个绑定的输出流指针。
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ostream *prevstr;
ofstream filestr;
filestr.open ("tie.txt");
*cin.tie() << "This is inserted into cout";
//cin.tie()返回与cin绑定的&cout,因此*cin.tie()==cout.
prevstr = cin.tie (&filestr);//将filestr与cin绑定,返回&cout赋值给prevstr
*cin.tie() << "This is inserted into file";
int data;
for(int i=0;i<4;i++)
{//亮点在这里!!
cin>>data;
filestr<<data;
//每次输入一个data后关闭重新打开tie.txt都能立刻看见该data马上写入了文件
//如果把prevstr = cin.tie (&filestr);这句注释掉,
//嘿嘿,每次输入一个data后关闭重新打开tie.txt都是空白,只有程序运行完后才能看见所有输入的data.
//或者加上这句话filestr.flush();后能达到不注释cin.tie (&filestr)时的效果.
//每当被“绑定”的对象cin有输入操作,就会自动刷新“绑定”的对象cout/filestr的缓冲区
}
cin.tie (prevstr);
filestr.close();
return 0;
}
由上列子可知:与cin绑定的filestr在每一次cin>>data时filestr<<data都会自动把filestr缓冲区中的data刷新到tie.txt中去.
而如果把prevstr = cin.tie (&filestr)这句注释掉,她们没绑定,每次cin>>data时filestr<<data只是把data存在filestr缓冲区中除非显示flush或程序结束才把缓冲区的内容全部写入tie.txt中去.
总之,任何输入流的操作都将首先刷新其绑定的输出流缓冲区.
cin>>ival时cout的缓冲区先被flush,没有输出显示是应为此时cout的缓冲区是空的?
....占时这就么理解把,基本是自己推测还是有点虚,要弄明白还要把输入输出缓冲区研究下把,这儿就越扯越远了,下次专门研究下这块~
int i;
cin.tie( &cout );
cout << "Enter a number:";
cin >> i;
保证cout流会在cin流之前被刷新,在上面的代码中保证Enter a number:先被打印出来,
cin.tie(0);//解除两个流的绑定,可能时cout缓冲区的内容还没flush但是已经cin>>i了!!!
哈哈,这样就不虚了,应该就是这样的.
(3)文件
fstream除了继承iostream的>>,<<等还有自己的新操作open,close,形参为要打开文件的构造函数.
ifstream infile("liuhan.txt");
ofstream oitflie("liuhan.txt");
ifstream infile;
ofstream outflie;
infile.open("liuhan.txt");
infile.close();
infile.open("red.txt");//打开另一个文件前先关闭上一个
ifstream input;
vector<string>::const_iterator it=files.begin();//files中存放要读取的一系列文件名
while(it!=files.end())
{
input.open(it->c_str());//open a file
if(!input)break;//打开失败input返回flase.
while(input>>s)
{....}
//读文件直到eof或其它错误上面while结束.都将让input处于错误状态flase.
//input流对象的内部状态被设置为flase,以后不再允许其读写操作.
input.close();
//即使关闭该流也不能改变其内部状态,再次打开依然是flase状态.
input.clear();
//直到执行clear操作重新恢复该流的初始状态.
++it;
}
文件模式,
in默认与ifstream对象关联
out也已经默认了
app每次写之前定位到文件尾
ate打开文件时立即定位到文件尾(只在打开时有效)
trunc打开文件时清空文件
binary
out,trunc,app只能与ofstream或fstream对象关联.
ate,binary能后所有文件关联.
ofstream outfile("liuhan.txt",ofstream::out|ofstream::trunc);
模式是文件的属性,每次打开时都要设置,默认设置为in或out.
(4)字符串流
和fstream一样sstream除了继承iostream还有一个string形参的构造函数,将string类型的实参赋值给stringstream对象.
string line,word;
while(getline(cin,line))//读一行数据给line
{
istringstream stream(line);
while(stream>>word){...}//每次写该行的一个单词给word
}
stringstream的转换和格式化
int val1=23,val2=45;
ostringstream form_message;
form_message<<"val1: "<<val1<<"\n"
<<"val2: "<<val2<<"\n";//放入form_message中的是val1,val2对应的字符串
istringstream input_message(form_message.str());
string dump;
input_message>>dump>>val1>>dump>>val2;
从input_message.str()中读取的值必须与其读入的值一致对应.
把"val1:","val2:"放入dump,再把字符串"23","45"的分别转换为val1,val2的类型放入.
和cin一样,空白和换行作为分割符被忽略
(5)
iostream,fstream,stringsteam都有条件状态成员,输入输出缓冲区.
以上流类是读写char,也支持wchar_t类型,每个类前加前缀'w',wcin,wcerr,wostream,wistringstream,wifstream等
浙公网安备 33010602011771号