阐明一下,我用的是g++7.1.0编译器,规范库源代码也是这个版本的。

始终以来,咱们每次应用cout输入数据的时候,如果要换行,都晓得应用形如cout << endl;这样的模式,那么endl到底是什么呢,它是怎么样实现输入一个换行符的性能的,以前我没有思考过,但当初我想弄懂它,上面就一起看一下吧。

1.endl操作符的实现

在规范库头文件<ostream>中,我找到了endl的操作符重载函数,如下:

template<typename _CharT, typename _Traits>    inline basic_ostream<_CharT, _Traits>&    endl(basic_ostream<_CharT, _Traits>& __os)    { return flush(__os.put(__os.widen('\n'))); }

它是一个内联的函数模板,是一个全局的函数模板,endl正是它的函数名,它的作用是往缓冲区写入一个换行符并且立刻从缓冲区刷新到外部设备中。

那么endl是怎么与<<操作符关联起来的呢,咱们在ostream头文件ostream类的申明中又发现了以下代码:

__ostream_type&      operator<<(__ostream_type& (*__pf)(__ostream_type&))      {    // _GLIBCXX_RESOLVE_LIB_DEFECTS    // DR 60. What is a formatted input function?    // The inserters for manipulators are *not* formatted output functions.    return __pf(*this);      }

这个操作符的入参是一个__ostream_type& (*__pf)(__ostream_type&)类型的函数指针,这个类型与endl的类型是统一的,从而,咱们当初晓得了endl的实现过程。

与endl同样实现的总共是亲兄弟三个,他们类型一样,且都是对缓冲区进行操作,如下:

操作符阐明
endl输入一个换行符到缓冲区,且即时刷新到外部设备
ends输入一个空字符到缓冲区
flush调用flush函数,把数据从缓冲区刷新到外部设备

2. 格式化操作符

说完endl的亲兄弟,接下来说一说它的堂兄弟们,那就是格式化操作符,在某些书籍上也叫做操纵算子,操纵算子用法与endl一样,也是形如cout << oct这样的模式,但它不会对缓冲区间接进行操作,它是对后续的数据输入进行格式化,相似c语言的%d一样,且操纵算子的实现形式与endl相似,只是<<的返回类型与参数类型不一样而已,这里就不再多说。

操纵算子分为两类,一类是无参的,定义在ios_base.h头文件中,还有一类是有参的,定义在iomanip头文件中。

2.1 无参操纵算子
操纵算子阐明
boolalpha针对bool类型变量,不是输入0和1,而是输入true或者false
noboolalphaboolalpha的反向操作
showbase在输入八进制或者十六进制的时候,加上0x这样的前缀,次要它要放在进制操作符的后面
noshowbaseshowbase的反向操作
showpoint强制打印小数点
noshowpointshowpoint的反向操作
showpos针对非负的数字,强制加上+号输入
noshowposshowpos的反向操作
skipws它是一个输出类操作符,作用是在输出时跳过空格,这一点与不应用skipws时是统一的
noskipws这里次要是noskipws会扭转>>的默认输出形式,会把空格,制表符等也读入
uppercase在输入十六进制这样的数据时,对外面的字母进行大写,留神它对输入字符类型或者字符串类型是不起作用的
nouppercaseuppercase的反向操作
unitbuf每次输入当前都刷新缓冲区
nounitbufunitbuf的反向操作
internal在设置了输入宽度的状况下,符号左对齐,值右对齐,两头应用空格填充
left在设置了输入宽度的状况下,输入整体左对齐,没有设置输入宽度,说对齐都是耍流氓
right在设置了输入宽度的状况下,输入整体右对齐,iostream流默认右对齐
dec十进制输入,对浮点数不起成果,只对整型有成果
hex十六进制输入,对浮点数不起成果,只对整型有成果
oct八进制输入,对浮点数不起成果,只对整型有成果
fixed定点十进制进行输入,默认输入6位小数位,小数位有余补0,超出的四舍五入,保留6位
scientific迷信计数法输入
hexfloat十六进制模式输入浮点数
defaultfloat对浮点数输入复原默认状态

一个应用案例如下:

#include <iostream>   using namespace std;   int main() {       // Initializing the integer     double x = 10.2333336;           //将浮点数x以十六进制模式输入,且字母都为大写    cout  << uppercase << hexfloat << x << endl;         cout.width(12);    double y = -11.222;    //勾销指定的浮点数格局,按默认格局输入    cout << defaultfloat;        //符号左对齐,数值右对齐,两头填充空格    cout << internal << y << endl;      return 0; }

输入后果如下:

0X1.47777806A1DABP+3-     11.222
2.2 有参操纵算子

有参的操纵算子实际上是在无参的根底上实现的,是对无参操纵算子的补充,且对无参操纵算子的应用起到了简化的作用。

首先还是看一看有参操纵算子有哪些,如下:

操纵算子参数类型阐明
resetiosflagsios_base::fmtflags,此类型是一个枚举类型,蕴含了上述的无参操纵算子,多的格局之间以单竖线分隔输入输出都可应用,重置以后流的格局
setiosflagsios_base::fmtflags输入输出都可应用,减少以后流的格局
setbaseint输入输出都可应用,设置进制,参数值可为8,10,16,如果是其余值则示意应用默认的
setfill无固定类型,是一个函数模板输入输出都可应用,设定对齐时的填充字符,虽说是模板,但参数个别倡议应用char类型
setprecisionint输入输出都可应用,设置精度,留神默认状况下这里的精度并不是指小数位,而是蕴含整数位在内,总共能够显示多少位数字,然而如果当时应用fixed指定了的话,那该精度就是单指小数位了
setwint输入输出都可应用,设置宽度
get_money有两个参数,第一个参数是一个函数模板,但依据iomanip头文件,它应该是一个long double类型或者string类型,此时该参数其实是一个出参,输出的数据存储在该参数外面,第二个参数是一个bool类型,示意是否国际化输出应用,依据设置的区域文化和编码以及输出的对应的货币表达式,获取相应的数据
put_money有两个参数,第一个参数是一个函数模板,但依据iomanip头文件,它应该是一个long double类型或者string类型,第二个参数是一个bool类型,示意是否国际化输入应用,依据设置的区域文化和编码,输入相应的货币表达式
put_time第一个参数是const std::tm类型指针,第二个类型是对工夫进行格式化的格局字符串依据第二个参数指定格局输入tm中数据
get_time第一个参数是const std::tm类型指针,第二个类型是对工夫进行格式化的格局字符串依据第二个参数指定格局把数据填充到tm中

带参数的这些操作函数,后面6个其实是比拟好了解的,然而前面四个用起来就比拟麻烦了,而且独自应用也是不起作用的,上面咱们就前面四个操作符,看一下应用案例,如下:

#include <iomanip>#include <iostream>#include <time.h>#include <sstream>using namespace std;void test01(){  locale loc_de = locale("en_US.utf-8");  cout.imbue(loc_de);  const string str("720000000000");  cout << put_money(str) << endl;    string str2;  cin.imbue(loc_de);  cin >> get_money(str2);//这里要依照imbue设置的区域和编码进行输出,形如:72,000,000  cout << "str2=" << str2 << endl;    time_t t;  time(&t);  tm *tmp = localtime(&t);  cout << put_time(tmp, "%y %a") << endl;    tm time1;  istringstream iss("15:12:00 2021");  iss >> get_time(&time1, "%H:%M:%S %Y");  cout << "hour:" << time1.tm_hour << ',' << "min:" << time1.tm_min << ',' << "sec:" << time1.tm_sec << endl;}int main(){  test01();  return 0;}

输入显示如下:

[root@mylinux ~]# ./a.out7,200,000,000.0012,00,00       #留神这里是屏幕输出的str2=12000021 Thuhour:15,min:12,sec:0[root@mylinux ~]#
前面四个函数的应用就波及到程序国际化以及区域文化的问题,比方浮点数,在咱们大中国是72000.12,那么到了美国可能又是用72,000.12来示意,对于区域文化,这里就不开展阐明了。