C++ setf 方法

一直以来,我对 C++ 的流操作说望而生畏一点都不为过,能不用则不用,我一般用 C 的流操作代替 C++ 的。为什么呢?习惯了 C 式的格式化输出,我相信大多数人和我感觉一样;习惯了 fprintf fread fwrite ftell fseek … 面对C++的 fstream 的操作方式是在不感冒。我是一个很安分的人,如果可以用我会的方法去解决掉这个问题,我很不情愿去用另外一种方法,即便是另外一种方法比较新、比较好。这算是个缺点吧,容易固步自封。以前整理过一篇文章:《C/C++输入输出流总结》,主要列出了接口,没有细节说明。

嗯,废话不多说了,说一下本文吧。本文算是一篇半翻译文章吧,setf 的说明文档,加上我一些个人的理解和扩展。

std::iosbase::setf

fmtflags setf ( fmtflags fmtfl );
fmtflags setf ( fmtflags fmtfl, fmtflags mask );

设置指定格式的标记

这两个函数都返回在调用之前流中的格式标记。

流的格式标记影响数据在输入输出函数中的显示方式。 iosbase::fmtflags 列出了这个函数的可能参数值。

参数化操作符 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++程序员也会会心的一笑。这也算是一个思想吧,我没有看过类似的书籍,也不知道具体应该称作什么。"你应该为你做的事情负责"。

Date: 2012-10-07 14:46:16

Author: JerryZhang