接触C++两年了,每次遇到文件格式化读取总是不能一气呵成,出现这样那样的问题,所以总结一下:
首先看一眼C++输入输出流的继承关系:
class ios_base关于格式化的函数:
class ios 关于格式化的函数:
既然ostream继承自class ios,ios继承自ios_base,那么 ostream的对象std::cout 可以使用上面继承来的函数,调用方式cout.setf()、cout.precision(); cout的类型是 ostream对象, ostream使用了单例模式,
原型有两个: fmtflags setf(fmtflags _Newfmtflags);
fmtflags setf(fmtflags _Newfmtflags, fmtflags _Mask);
参数 _Newfmtflags | 参数 _Mask | 含义
ios_base::basefield | ios_base::dec 使用基数10
| ios_base::oct 使用基数8
| ios_base::hex 使用基数16 |
ios_base::floatfield | ios_base::fixed 使用定点计数法
| ios_base::scientific 使用科学计数法
|
ios_base::adjustfield | ios_base::left 左对齐
| ios_base::right
| ios_base::internal
返回值fmtflags 记录当前格式标记,比如取消当前设置的格式恢复默认格式:
cout.unsetf(cout.flags());
这个函数只需记住:cout.width()只影响接下来显示的第一个cout<<输出。 接下来字段宽度恢复为默认值。所以,要想每个字段输出都设置宽度,必须每次都要写一遍cout.width()
这个函数“精度”设置的是小数点后位数,不是总位数。
设置填充字符。
清除格式标识,恢复默认的格式方法:cout.unsetf(cout.flags());
使用cout进行格式输出:
#include
using namespace std;
int main()
{
//浮点数默认保留六位(整数和小数的和保留六位,末尾的0,不显示),左对齐,
float dataF = 155.63636;
cout << dataF << endl; //155.636
double dataD = 5.9336521;
cout << dataD << endl; //5.93365
double scientific = 3.0 / 7;
cout << scientific << endl;
cout << "Result:";
cout.width(10); //调整字段宽度,返回原来的字段宽度 width()只影响接下来显示的第一个cout<<输出。 //接下来字段宽度恢复为默认值。
cout.fill('#'); //设置一次一直起作用
cout << dataD << ',' << dataF << ',' << endl; //之后就恢复了宽度
//Result:###5.93365,155.636,
cout.setf(ios_base::left, ios_base::adjustfield);
cout << "Result:";
cout.width(10);
cout << dataD << ',' << dataF << ',' << endl; //之后就恢复了宽度
//Result:5.93365###,155.636,,
cout.setf(ios_base::right);
cout << "Result:";
cout.width(10);
cout << dataD << ',' << dataF << ',' << endl; //之后就恢复了宽度
//begin:###5.93365,155.636,
//cout.precison() 保留小数点之后多少位
streamsize oldsize = cout.precision(6);
ios_base::fmtflags oldformat = cout.setf(ios_base::scientific); //等价于cout.setf(ios_base::scientific,ios_base::floatfield)
cout << "Result:"
<< dataD << ',' << dataF << ','<< scientific<< endl; //Result:5.9336521000e+00,1.5563635254e+02,4.2857142857e-01
cout.setf(ios_base::fixed);
cout.precision(oldsize);
cout << "Result:"
<< dataD << ',' << dataF << ',' << scientific << endl;
system("pause");
return 0;
}
有不懂的C++控制符操作符都可以查阅:http://www.cplusplus.com/reference
然而使用ostream对象cout调用函数设置输出格式对用户不友好,C++提供了多个控制符能够调用比如setf(),setw(),setfill(),setprecision()等;
可以直接用的控制符(使用方法:cout<<控制符)
boolalpha,noboolalpha,showbase,noshowbase,showpoint,noshowpoint,showpos,noshowpoint,uppercase,nouppercase,left,right,initernal,dec,hex,fixed,scientific;
注意添加
使用控制符控制输出格式
控制符 |
作用 |
dec |
设置整数的基数为10 |
hex |
设置整数的基数为16 |
oct |
设置整数的基数为8 |
setbase(n) |
设置整数的基数为n(n只能是16,10,8之一) |
setfill(c) |
设置填充字符c,c可以是字符常量或字符变量 |
setprecision(n) |
设置实数的精度为n位。在以一般十进制小数形式输出时,n代表有效数字。在以fixed(固定小数位数)形式和scientific(指数)形式输出时,n为小数位数。 |
setw(n) |
设置字段宽度为n位。 |
setiosflags(ios::fixed) |
设置浮点数以固定的小数位数显示。 |
setiosflags(ios::scientific) |
设置浮点数以科学计数法(即指数形式)显示。 |
setiosflags(ios::left) |
输出数据左对齐。 |
setiosflags(ios::right) |
输出数据右对齐。 |
setiosflags(ios::shipws) |
忽略前导的空格。 |
setiosflags(ios::uppercase) |
在以科学计数法输出E和十六进制输出字母X时,以大写表示。 |
setiosflags(ios::showpos) |
输出正数时,给出“+”号。 |
resetiosflags |
终止已设置的输出格式状态,在括号中应指定内容。 |
一个重要的应用就是:输出带有几位小数的浮点数,数字末尾控制出现0的个数:
cout << fixed << setprecision(4) << 3.1415926 << endl; //3.1416
cout << fixed << setprecision(6) << 3.14 << endl; //3.140000
cout << showpos << fixed << setprecision(6) << 3.14 << endl; //+3.140000
cout << hex << noshowbase << showpos << 256<<" " //100
<< showbase << 256 << " " //0x100
<< uppercase<<256; //0X10
需要包含c++头文文件#include
最后,讨论一下为什么要使用C++的iostream:
C++的iostream家族与C的printf/scanf/gets/puts/getchar/putchar家庭相比究竟有何优势?首先是类型处理更安全、智能,想想printf中对付int、float等的"%d"、"%f"等说明符真是多余且麻烦,万一用错了搞不好还会死掉;其次是扩展性更强:我要是新定义一个复数类Complex,printf对其是无能为力,最多只能分别输出实、虚部,而iostream使用的<<、>>操作符都是可重载的,你只要重载相关的运算符就可以了;而且流风格的写法也比较自然简洁,不是么?
但是,iostream也有缺点:他们的速度比prints/scanf等函数慢得多(毕竟得检测类型),而且如果你要进行一些特殊操作(如保留小数点后n位),printf比cin方便得多。
参考:
https://baike.baidu.com/item/cout/9272732
http://www.cplusplus.com/reference
C++ primer plus
https://www.cnblogs.com/huashanqingzhu/p/3544797.html