17.1.2
一,iostream文件
程序中包含iostream文件将自动创建8个流对象:cin,cout,cerr,clog以及用于宽字符的wcin,wcout,wcerr,wclog。
标准输出cout与标准错误cerr,clog区别在于,如果操作系统重定向输出到文件而不是显示器,则标准输出将与文件相连,但标准错误仍与显示器相连。
17.2.1
二,重载的<<运算符(插入运算符)
ostream类为下面类型的指针类型定义了插入运算符函数:
1,const signed char*
2,const unsigned char*
3,const char*
4,void*
1\2\3都显示字符,但对于其他类型的指针,统一对应为void*,并打印地址的数值表示,如:
int eggs = 12;
char* amount = "dozen";
cout << &eggs; //打印eggs地址的数值
cout << amount; //打印字符串“dozen”
cout << (void*)amount; //打印字符串“dozen”的地址数值
17.2.2
三,其他ostream方法
除了operator<<()函数之外,ostream类还定义了put()和write()方法,前者用于显示字符,后者用于显示字符串.
put()原型: ostream& put(char);
write()模板原型:basic_ostream<charT,traits>& write(const char_type* s, strwamsize n)
需注意,write()并不会在遇到空字符是自动停止,而是打印指定书目的字符,即使超出了字符串的边界。
cout.put('i').put('m'); // im
cout.put(65); // display A
cout.put(66.9); // display B
string a = "imAB";
cout.write(a.c_str(),a.size());
17.2.3
四,刷新输出缓冲区
控制符flush刷新缓冲区,而控制符endl刷新缓冲区,并插入一个换行符。
flush(cout); //控制符也是函数
cout << flush; //ostream对<<进行了重载
17.2.4
五,使用cout进行格式化
1,修改显示时使用的计数系统。
控制以十进制,十六进制,八进制显示,可以使用dec、hex、oct控制符
格式:
hex(cout);
cout << hex;
时效:
直至格式状态设置为其他选项为止。
2,调整字段宽度
可以使用width成员函数将长度不同的数字放到宽度相同的字段中。由于width是成员函数,必须使用对象调用它(cout)。
原型:
int width(); //返回字段宽度的当前设置
int width(int i); //宽度设置为i,并返回以前的宽度值,供恢复使用
格式:
int defalWidth = cout.width(30);
时效:
只影响下一个显示的项目,然后字段宽度恢复到默认值。
3,填充字符
默认情况下cout用空格填充未被使用的部分,可以用fill()成员函数改变填充字符。
格式:
cout.fill('*'); //使用*填充
时效:
新设置的填充字符会一直有效,知道更改它为止。
4,设置浮点数精度。
c++的默认精度是6位,末尾的0不显示。precision()成员函数使得能够选择其他值。
格式:
cout.precision(4);精度设置为4
时效:
新精度设置一直有效,知道被重新设置。
5,打印末尾的0和小数点
ios_base类提供了一个setf()函数,能够控制多种格式化特性,还定义了多个常量(fmtflags为),用作该函数的参数。
格式:
cout.setf(ios_base::showpoint); //显示末尾的小数点,如果是默认浮点格式,则末尾的0也显示出来。显示小数点只对浮点数有效。
时效:
一直有效。
6,再谈setf()
setf()函数有两个原型:
第一个:fmtflags setf(fmtflags)
fmtflags 为bitmask类型,支出要设置那个位,并返回之前的设置。
部分fmtflags 常量含义,请参考,P747的表17.1。
第二个:fmtflags setf(fmtflags, fmtflags)
第一个参数指出要设置哪个位,第二个指出要清楚哪些位。
两个参数如何赋值,参考P748中的表17.2。
可以使用unsetf()消除setf()设置的效果,具体支持那些标准,请参考P751表17.3。
7,头文件iomanip
为了简化设置工作,c++在头文件iomanip中设置了一些控制符,常用的如:setprecision(),setfill(),setw(),分别用来设置精度,填充字符和字段宽度。
格式:
int n = 0;
cout << setw(6) << setfill('%') << setw(5) << n << endl;
17.3.1
六,cin如何检查输入
cin跳过空白(空格、换行符和制表符),知道遇到非空白字符。只读取指定类型的数据,也就是说,它读取从非空白字符开始,与到目标类型不匹配的第一个字母之间的全部内容。
int ele;
cin >> ele;
假设输入-123Z,这种情况下将-123转换为一个整数型付给ele,并将Z留在输入流中,下一个cin将从这开始读取。
假如输入Zcar,这种情况下不会修改ele的值,并返回0;
如下程序输入I LOVE C++<Enter>,输出为ILOVEC++.跳过了空格,并且循环并不会终止,因为也跳过了‘\n’
int ct = 0;
char ch;
cin >> ch;
while ('\n' != ch) //FAILS
{
ct++;
cin >> ch;
}
17.3.2
七,流状态
流状态被定义为iostate类型,是一种bitmask类型,游3个ios_base元素组成:eofbit,badbit,和failbit。
到达文件尾时,置eofbit;
cin操作未能读取到预期的字符或者IO失败时,置failbit;
一些无法诊断的失败破坏流时,置badbit。
1,设置状态
clear()方法将状态设置为它的参数。因为其默认参数为0,则下面的调用将清楚全部3个状态位(eofbit,badbit,failbit):
cin.clear();
下面的调用将设置eofbit,另外两个状态位被清除:
cin.clear(ios_base::eofbit);
setstate()方法只影响其参数中已设置的位。因此下面的调用将设置eofbit,但不会对其他为造成影响。
cin.setstate(ios_base::eofbit);
2,io异常
17.3.3
八,其他istream类方法
1,单字符输入
get()方法读取下一个输入的字符,即使是空格,制表符或换行符,并将输入字符转换为整型(通常是int)并将其返回。get(char& ch)将输入字符赋给其参数。
如果cin.get(char &)到达文件结尾,将调用setstate(failbit),导致cin的测试结果为false:
char ch;
while (cin.get(ch)) //FAILS
{
//process input
}
cin.get()使用返回值将输入传给程序:
int ct = 0;
char ch;
ch = cin.get();
while (ch != '\n') //FAILS
{
ct++;
cin.get();
}
如果到达文件尾,cin.get()将返回EOF。
int ch;
while ((ch = cin.get()) != EOF) //FAILS
{
//process input
}
注意此处应将ch定义为int而不是插入,因为EOF可能无法使用char类型来表示。
2,字符串输入:getlinte(),get()和ignore()
getline()和get()都读取字符串,他们的函数特征标相同:
istream& get(char*, int, char);
istream& get(char*, int);
istream& getline(char*, int, char);
istream& getline(char*, int);
第一个参数用于放置字符串的内存单元的地址。第二个参数比要读取的最大字符数大1。第三个参数指定分界符。
上述函数都在读取最大数目的字符或遇到换行符或遇到分界符后停止.
get()和getline()的区别在于get()将换行符留在输入流内,这样接下来的输入操作首先看到的将是换行符。而getline()抽取并丢弃输入流中的换行符。
ignore()成员函数,接受两个参数,第一为指定的最大字符数,另一个是字符,用作输入分界符。两个参数默认值为1和EOF,该函数的返回类型为istream&。
如下面的函数调用读取并丢弃接下来的255个字符或指导到达第一个换行符:
cin.ignore(255, '\n');
17.3.4
九,其他istream方法
包括read(),peek(),gcount(),putback()。
read()与get()和getline()不同时,read()不会再结尾加上空字符,因此不能转化为字符串。
peek()查看下一个字符,但不抽取。
gcount()方法返回最后一个非格式化抽取方法读取的字符数。
putback()将一个字符插入到输入字符串中,被插入的字符时下一条输入语句读取的第一个字符。
17.4.1
十,简单的文件I/O
写入到文本的流程:
1,必须包含头文件fstream
2,声明一个或多个ofstream对象,与文件关联起来。
3,以使用cout的方式,使用该对象。
4,使用完文件后,应使用方法close()将其关闭。
读取文本文件的流程:
1,同上
2,声明一个或多个ifstream对象,与文件关联起来
3,使用cin的方式,使用该对象(如使用get读取字符,使用getline读取一行,结合eof(),fail()等方法判断读取是否成功)
4,使用完关闭文件。
打开文件的方法为open,如
ofstream outfile;
outfile.open("test.txt");
或者使用另一个构造函数:
ifstream outfile("test.txt");
17.4.2
十一,流状态检查和is_open()
如果文件被成功打开is_open()将返回true。
ifstream infile("test.txt");
if (!infile.is_open())
{
cout << "open file faile";
}
17.4.5
十二,文件模式
ios_base类定义了一个openmode类型,用于表示模式,与fmtfags和iostate一样,它也是一种bitmask类型。文件模式常量见P774表17.7和P775表17.8。
17.4.6
十三,随机存取
ftream类继承了两个方法:seekg()和seekp()。前者将输入指针移动到指定的位置,后者将输出指针移动到指定的位置,也可以说seekg()用于istream对象,seekp()用于ostream对象。
seekg()原型为模板,char类型的具体化等同于下面的代码:
istream& seekg(streamoff, ios_base::seekdir);
istream& seekg(streampos);
第一个原型:
第一个参数streamoff值被用来度量相对于文件特定位置的偏移量(单位为字节)。
第二个参数seekdir有3个可能值:常量ios_base::beg只相对于文件开始出的偏移量,ios_base::cur指相对于当前位置的偏移量,ios_base::end指相对于文件尾的偏移量。
第二个原型:
定位到相对于文件头的streampos位置。
17.5
十四,内核格式化
c++库还提供了sstream族,他们使用相同的借口提供程序和string对象之间的I/O。
读取string对象中的格式信息或将格式化信息写入到string对象中国被称为内核格式化。
头文件sstream定义了一个从ostream类派生而来的ostringstream类,该类有一个名为str()的成员函数,该函数返回一个被初始化为缓冲区内容的字符串对象。
ostringstream outstr;
double price = 380.0;
char* ps = "for test";
outstr.precision(2);
outstr << fixed;
outstr << price <<" "<< ps << endl;
string tst = outstr.str(); //tst = 380.00 for test
总之istringstream和ostringstream类使得能够使用istream和ostream类的方法来管理存储在字符串中的字符串数据。