Oracle® Developer Studio 12.5:C++ 用户指南

退出打印视图

更新时间: 2016 年 7 月
 
 

13.7 操纵符

操纵符是可以在 iostream 中插入或提取以产生特殊效果的值。

参数化操纵符是具有一个或多个参数的操纵符。

因为操纵符是普通的标识符,因此会用完可能的名称,而 iostream 不会为每个可能的函数定义操纵符。本章的其他部分讨论了各种操纵符和成员函数。

下表中介绍了 13 个预定义的操纵符。此表假定以下事项属实:

  • i 的类型为 long

  • n 的类型为 int

  • c 的类型为 char

  • istr 是输入流。

  • ostr 是输出流。

表 27  iostream 的预定义操纵符
预定义操纵符
说明
1
ostr << dec, istr >> dec
以 10 为基数进行整数转换。
2
ostr << endl
插入一个换行符 (’\n’) 并调用 ostream::flush()
3
ostr << ends
插入一个空 (0) 字符。这在处理 strstream 时很有用。
4
ostr << flush
调用 ostream::flush()
5
ostr << hex, istr >> hex
以 16 为基数进行整数转换。
6
ostr << oct, istr >> oct
以 8 为基数进行整数转换。
7
istr >> ws
提取空白字符(跳过空白),直至找到非空白字符(留在 istr 中)。
8
ostr << setbase(n), istr >> setbase(n)
将转换基数设置为 n(仅限 0、8、10、16)。
9
ostr << setw(n), istr >> setw(n)
调用 ios::width(n)。将字段宽度设置为 n。
10
ostr << resetiosflags(i), istr>> resetiosflags(i)
根据 i 中设置的位,清除标志位向量。
11
ostr << setiosflags(i), istr >> setiosflags(i)
根据 i 中设置的位,设置标志位向量。
12
ostr << setfill(c), istr >> setfill(c)
将填充字符(用来填充字段)设置为 c
13
ostr << setprecision(n), istr >> setprecision(n)
将浮点精度设置为 n 位数。

要使用预定义的操纵符,必须在程序中包含文件 iomanip.h

您可以定义自己的操纵符。操纵符的两个基本类型为:

  • 无格式操纵符 – 采用 istream&ostream&ios& 参数,对流进行操作,然后返回其参数。

  • 参数化操纵符 – 采用 istream&ostream&ios& 参数以及一个附加参数,对流进行操作,然后返回其流参数。

13.7.1 使用无格式操纵符

无格式操纵符是执行以下操作的一个函数:

  • 执行到流的引用

  • 以某种方式操作流

  • 返回其参数

由于为 iostream 预定义了接受指向此类函数的指针的移位运算符,因此可以在输入或输出运算符序列中放入函数。移位运算符会调用函数而不是尝试读取或写入值。以下示例显示了将 tab 插入 ostreamtab 操纵符:

ostream& tab(ostream& os) {
             return os <<’\t’;
            }
...
cout << x << tab << y;

该示例详细描述了实现以下代码的方法:

const char tab = ’\t’;
...
cout << x << tab << y;

下面示例显示了无法用简单常量来实现的代码。假设要对输入流打开或关闭空白跳过功能。可以分别调用 ios::setfios::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;
}

13.7.2 参数化操纵符

iomanip.h 中包含的其中一个参数化操纵符是 setfillsetfill 设置用于填写字段宽度的字符。该操纵符是按下例所示的方式实现的:

//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 一起使用,所以也可以与 istreamostream 一起使用。上面的示例还使用了另一个类型为 int 的参数。

applicator 创建并返回类对象。在上面的代码示例中,类对象是 smanip_int,其中包含了操纵符和 applicator 的 int 参数。iomanip.h 头文件定义了用于该类的移位运算符。如果 applicator 函数 setfill 在输入或输出操作序列中,会调用该 applicator 函数,且其返回一个类。移位运算符作用于该类,以使用其参数值(存储在类中)调用操纵符函数。

在以下示例中,操纵符 print_hex 执行以下操作:

  • 将输出流设置成十六进制模式

  • long 值插入流中

  • 恢复流的转换模式

此处使用了类 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);
   }