C++ setf 方法
一直以来,我对 C++ 的流操作说望而生畏一点都不为过,能不用则不用,我一般用 C 的流操作代替 C++ 的。为什么呢?习惯了 C 式的格式化输出,我相信大多数人和我感觉一样;习惯了 fprintf fread fwrite ftell fseek … 面对C++的 fstream 的操作方式是在不感冒。我是一个很安分的人,如果可以用我会的方法去解决掉这个问题,我很不情愿去用另外一种方法,即便是另外一种方法比较新、比较好。这算是个缺点吧,容易固步自封。以前整理过一篇文章:《C/C++输入输出流总结》,主要列出了接口,没有细节说明。
嗯,废话不多说了,说一下本文吧。本文算是一篇半翻译文章吧,setf 的说明文档,加上我一些个人的理解和扩展。
std::ios_base::setf
fmtflags setf ( fmtflags fmtfl ); fmtflags setf ( fmtflags fmtfl, fmtflags mask );
设置指定格式的标记
- 第一个方法用 fmtfl 设置流的格式标记,但是不会减少之前的流标志,也就是说相当于在原来流标志的基础上加上 fmtfl ,即 flags (fmtfl | flags())。
- 第二个方法使用 fmtfl 和 mask 两个共同设定流格式标记,清除 mask 标签中不属于 fmtl 中的标签,即 flags((fmtfl & mask | (flags() & ~mask)).
这两个函数都返回在调用之前流中的格式标记。
流的格式标记影响数据在输入输出函数中的显示方式。 ios_base::fmtflags 列出了这个函数的可能参数值。
- 第一个 setf 方法通常用来设置单一的格式标记:boolalpha, showbase, showpoint, showpos, shipws, unitbuf 和 uppercase,可以直接使用 unsetf 来取消设置。
- 第二种 setf 方法通常用来设置选择的标记中的一种,使用位掩码作为 mask 参数。
参数化操作符 setioflag 和这个方法实现的效果类似,是这个方法的单参版本。
参数
fmtfl 设置格式化标签。如果使用第二个方法的话,仅仅用 fmtfl 和 mask 设置流格式标志中;设置在 mask 中的 fmtfl 标志。 mask 要修改的标志掩码
返回值
返回调用之前的格式化标志
使用示例:
#include <iostream> using namespace std; int main() { // read/write bool elements as alphabetic strings (true and false). cout.setf(ios_base::boolalpha); bool b = true; cout << b << endl; b = false; cout << b << endl; // write floating-point values including always the decimal point. cout.setf(ios_base::showpoint); float f = 10.0; cout << f << endl; // write non-negative numerical values preceded by a plus sign (+). cout.setf(ios_base::showpos); cout << f << endl; // write floating-point values in scientific notation. cout.setf(ios_base::scientific, ios_base::floatfield); cout << f << endl; // using fmtflags as class member constants: cout.setf (ios_base::hex , ios_base::basefield); cout.setf (ios_base::showbase); cout << 100 << endl; }
例子举得不够充分,的确。因为要牵扯到其他流操作的方法,我就没用。关心的自己研究一下,我只是抛砖引玉。我明白了很多,这就够了;至于你明白多少,如果你想去明白,我想我说的够了,如果你不想去明白,我说多少也是白搭。
我说几点可以学习的设计思想吧,个人理解:
1、这种标志的方式很常见,通常都称为 mask or flag,定义为一些很容易区分的二进制数据,比如:
#define NORTH 0x00000001 -> 00000000 00000000 00000000 00000001 #define SOUTH 0x00000002 -> 00000000 00000000 00000000 00000010 #define EAST 0x00000004 -> 00000000 00000000 00000000 00000100 #define WEST 0x00000008 -> 00000000 00000000 00000000 00001000
以前我做的一个项目,就是这么做的。这么定义的好处是什么呢?非常容易计算。假如给你一个加和
00000000 0000000 0000000 00001001
,我很容易就可以知道是 NORTH 和 WEST
两个方向。
搞 Windows 程序的朋友应该知道 Windows API 中有很多 flag 这样的参数,它们也是这样的,这样设置很容易进行位运算(|,^,&,~等),容易区分。这也是一个很不错的方法,平时做项目的时候也可以使用这个思想。
2、setf 的返回值是设置之前的流格式标志。为什么要这么做呢?答案是"恢复现场"。这是一个很好的习惯,就好像你要租一块场地来举办活动,举办完之后,应该恢复原样,让别人感觉这个事情从来没有发生过。Windows程序员应该会会心的一笑,C++程序员也会会心的一笑。这也算是一个思想吧,我没有看过类似的书籍,也不知道具体应该称作什么。"你应该为你做的事情负责"。