操纵符是可以在 iostream 中插入或提取以起到特殊作用的值。
参数化操纵符是具有一个或多个参数的操纵符。
因为操纵符是普通的标识符,因此会用完可能的名称,而 iostream 不会为每个可能的函数定义操纵符。本章的其他部分讨论了各种操纵符和成员函数。
有 13 个预定义的操纵符,如表 14–2 中所列。使用该表时,要进行以下假设:
i 的类型为 long。
n 的类型为 int。
c 的类型为 char。
istr 是输入流。
ostr 是输出流。
要使用预定义的操纵符,必须在程序中包含文件 iomanip.h。
您可以定义自己的操纵符。操纵符共有两个基本类型:
无格式操纵符-采用 istream&、ostream& 或 ios& 参数,对流进行操作,然后返回其参数。
参数化操纵符-采用 istream&、ostream& 或 ios& 参数以及一个附加参数,对流进行操作,然后返回其流参数。
无格式操纵符是具有如下功能的函数:
执行到流的引用
以某种方式操作流
返回操纵符的参数
由于为 iostream 预定义了采用(指向)此类函数(的指针)的移位运算符,因此可以在输入或输出运算符序列中放入函数。移位运算符会调用函数而不是尝试读取或写入值。例如,下面是将 tab 插入 ostream 的 tab 操纵符:
ostream& tab(ostream& os) { return os <<’\t’; } ... cout << x << tab << y; |
详细描述实现以下操作的方法:
const char tab = ’\t’; ... cout << x << tab << y; |
下面示例显示了无法用简单常量来实现的代码。假设要对输入流打开或关闭空白跳过功能。可以分别调用 ios::setf 和 ios::unsetf 来打开和关闭 skipws 标志,也可以定义两个操纵符。
#include <iostream.h> #include <iomanip.h> istream& skipon(istream &is) { is.setf(ios::skipws, ios::skipws); return is; } istream& skipoff(istream& is) { is.unsetf(ios::skipws); return is; } ... int main () { int x,y; cin >> skipon >> x >> skipoff >> y; return 1; } |
iomanip.h 中包含的其中一个参数化操纵符是 setfill。setfill 设置用于填写字段宽度的字符。该操作按照下例所示实现:
//file setfill.cc #include<iostream.h> #include<iomanip.h> //the private manipulator static ios& sfill(ios& i, int f) { i.fill(f); return i; } //the public applicator smanip_int setfill(int f) { return smanip_int(sfill, f); } |
参数化操纵符的实现分为两部分:
操纵符。它使用一个额外的参数。在上面的代码示例中,采用了额外的 int 参数。由于未给这个操纵符函数定义移位运算符,所以您无法将它放至输入或输出操作序列中。相反,您必须使用辅助函数 applicator。
applicator。它调用该操纵符。applicator 是全局函数,您会为它生成在头文件中可用的原型。通常操纵符是文件中的静态函数,该文件包含了 applicator 的源代码。只有 applicator 可以调用该操纵符,如果您将操纵符设置为静态,就要使操纵符名称始终位于全局地址空间之外。
头文件 iomanip.h 中定义了多个类。每个类都保存一个操纵符函数的地址和一个参数的值。manip(3CC4) 手册页中介绍了 iomanip 类。上面的示例使用了 smanip_int 类,它是与 ios 一起使用。因为该类与 ios 一起使用,所以也可以与 istream 和 ostream 一起使用。上面的示例还使用了另一个类型为 int 的参数。
applicator 创建并返回类对象。在上面的代码示例中,类对象是 smanip_int,其中包含了操纵符和 applicator 的 int 参数。iomanip.h 头文件定义了用于该类的移位运算符。如果 applicator 函数 setfill 在输入或输出操作序列中,会调用该 applicator 函数,且其返回一个类。移位运算符作用于该类,以使用其参数值(存储在类中)调用操纵符函数。
在以下示例中,操纵符 print_hex:
使用类 omanip_long 的原因是该代码示例仅用于输出,而且操作对象是 long 而不是 int:
#include <iostream.h> #include <iomanip.h> static ostream& xfield(ostream& os, long v) { long save = os.setf(ios::hex, ios::basefield); os << v; os.setf(save, ios::basefield); return os; } omanip_long print_hex(long v) { return omanip_long(xfield, v); } |