问题引入:今天老师讲解c++的时候,演示cout.setf(left)cout.setf(right)时发现了一个奇怪的问题,setf(left)会被setf(right)覆盖,老师猜测可能是left和right是两个不同的变量,然后优先级不一样,我当时觉得奇怪,就翻开源码一探究竟。

示例代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{cout.fill('_');//为了突出比较,将空白处填充为下划线(_)cout.setf(ios::right);cout.width(8);cout<<"a";cout.setf(ios::left);cout.width(8);cout<<"a";return 0;
}

按照预期,先右对齐再左对齐,输出的应该是长这样_______aa_______,然而实际情况确是:_______a_______a,也就是说,第二次的setf(ios::left)竟然不起作用。

翻看源码:

/***  @brief  Setting new format flags.*  @param  __fmtfl  Additional flags to set.*  @return  The previous format control flags.**  This function sets additional flags in format control.  Flags that*  were previously set remain set.*/fmtflagssetf(fmtflags __fmtfl){fmtflags __old = _M_flags;_M_flags |= __fmtfl;//重载了 |= 运算符return __old;//返回旧的标志}

重载的|=运算函数:

inline const _Ios_Fmtflags&
operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
{ return __a = __a | __b; }//实际上就是将新旧标志做'或'运算

我们可以看到,setf()函数在我们的例子中实际上是将ios::leftios::right做了一个或运算(|)
那么接着看,ios::leftios::right分别是什么呢?

/// Adds fill characters on the right (final positions) of certain
/// generated output.  (I.e., the thing you print is flush left.)
static const fmtflags left =        _S_left;
static const fmtflags right =       _S_right;

再进一步看:

// The following definitions of bitmask types are enums, not ints,
// as permitted (but not required) in the standard, in order to provide
// better type safety in iostream calls.  A side effect is that in C++98
// expressions involving them are not compile-time constants.
enum _Ios_Fmtflags
{ //···(三点代表此处省略了其他标志的定义)_S_left        = 1L << 5,//···_S_right      = 1L << 7,//···
};

那么 1L << 5是什么意思呢?
我们可以简单测试看看:

int main(){int left = 1L << 5;cout<<left<<endl;
}

输出发现left的值为32,也就是说,其实1L<<5是将1左移5位,事实上2^5 = 32;同理right的值也应当是2^7 = 128。读者们可以动手试试。
那么这是什么意思呢?我们假设该标志为是八位的00000000,设置为right后,则变为01000000,再设置为left时,与00010000进行或运算,得到01010000

// 假设初始的 fmtflags 为 0000 0000
cout.setf(ios::right);//此时fmtflags变为 0100 0000,因为right是 1L<<7
//···
cout.setf(ios::left);//此时fmtflags变为 0101 0000,经历过right和left相或

到这里,我们可以大致猜测cout输出时根据fmtflags的标志位,从左往右去判断,因为right的优先级高于left,使得在二者都为1的情况下,使用了right右对齐的格式。(如果有大佬清楚cout输出时是如何读取flag的,恳请留言告诉我,谢谢~)

那么,为了实现一开始我们的目的,有没有别的办法呢?我还发现另一个函数flags(),它可以实现我们的要求:

cout.fill('_');
cout.flags(ios::right);
cout.width(8);
cout<<"a";
cout.flags(ios::left);
cout.width(8);
cout<<"a";

查看输出:_______aa_______,成功~

为啥呢?查看flags()源码:

/***  @brief  Setting new format flags all at once.*  @param  __fmtfl  The new flags to set.*  @return  The previous format control flags.**  This function overwrites all the format flags with @a __fmtfl.*/fmtflagsflags(fmtflags __fmtfl){fmtflags __old = _M_flags;_M_flags = __fmtfl;//直接将flag设置为传入的参数return __old;}

显然,这样的flags()是满足我们的要求的。同时我们如果需要一次设置多个flag,也可以利用上面的源码中的或运算实现cout.flags(FlagA | FlagB)

【c++】cout.setf(left)、cout.setf(right)详解相关推荐

  1. STL中map和string, vector 用法详解

    1. map 用法详解 std map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成 ...

  2. c++之string类详解

    一.包含头文件 要想使用标准C++中string类,必须要包含 #include <string>// 注意是<string>,不是<string.h>,带.h的是 ...

  3. 天梯赛基础题型详解(2019 - 08 - 12)

    A.枚举 (1) 详解:用枚举法,从最开始的只有一层沙漏开始枚举,直至找到一个沙漏所用符号的总和小于等于输入的数(将每一次不同层数的沙漏的符号和都用数组储存起来),然后标记那个最大的和.要注意的是每增 ...

  4. c 语言的输出函数cout,详解C++ cout格式化输出完全攻略

    写算法题的时候突然发现自己忘记基本的C++:cout格式化输出了,赶紧拉出以前的C++学习笔记重新看一看. 部分内容来自教程:C语言中文网(一个很棒的网站) 有时希望按照一定的格式进行输出,如按十六进 ...

  5. 详解让人闹心的C++语句 cout<<“Hello“<<endl;

    语句"cout<<"Hello!"<<endl;"的作用是输出字符串Hello和换行符到屏幕,下面详解这句话! cout是标准库iost ...

  6. cout的格式控制——关于cout.width()和cout.fill()

    今天做C++的高精度的时候发现高精度的模板输出使用到了cout.width()和cout.fill()以便把每个单元存放的四位数字输出 于是就去查找了一下关于cout.width()和cout.fil ...

  7. cout和std::cout的区别

    最近在读C++ Primer Fourth Edition.偶然发现cout和std::cout很有意思.一个是需要引用iostream.h,而另一个需要调用iostream.但他们的功能却又差不多. ...

  8. C++,cout和std::cout的区别

    #include "stdafx.h" #include <stdlib.h> #include <iostream> using namespace st ...

  9. 计算机基础知识预备知识,计算机预备知识详解.ppt

    计算机预备知识详解 Visual C++程序设计 Ch3 简单的输入/输出 > 3.1 cin 输入十六进制或八进制数据 例: int i , j , k , l ; cin>>he ...

  10. 三维空间刚体运动5:详解SLAM中显示机器人运动轨迹及相机位姿(原理流程)

    三维空间刚体运动5:详解SLAM中显示机器人运动轨迹及相机位姿(原理流程) 一.显示运动轨迹原理讲解 二.前期准备 三.git管理子模块及克隆源代码 1.学习使用Git Submodule 2.克隆源 ...

最新文章

  1. 水稻微生物组时间序列分析
  2. 某系统响应时间慢TPS低性能瓶颈调优过程
  3. 【Groovy】Groovy 动态语言特性 ( Groovy 语言与 Java 语言执行效率对比 | 以动态特性编译的 Groovy 类 | 以静态特性编译的 Groovy 类 )
  4. 字符串,那些你不知道的事
  5. java编程里的values怎么使用,详解Java编程中super关键字的用法
  6. 百度之星初赛(1)解题报告
  7. SecureCRT 中 python 命令行使用退格键(backspace)出现 ^H 解决办法
  8. springboot超详细教程_CG原画插画教程:超详细线稿教程
  9. Linux 系统应用编程——网络编程(socket编程)
  10. 0基础学python做什么工作好-如何快速学习Python编程?可以做什么职业?
  11. paip.php debug 调试---与OPTIMIZER共存
  12. 大学里,数据系鄙视物理系,请问二位来自漫画系嘛?
  13. USB转RS485串口电路设计
  14. 各大PT网站信息记录(不断更新中)
  15. 我打算学计算机学英语,英语人教版八年级上册我打算学习计算机科学.doc
  16. 计算机设置密码打印机无法共享,win7设置开机密码后无法连接共享打印机
  17. kali无线破解实战
  18. matlab计算正弦信号基波,Matlab入门篇——正弦信号、实指数信号和复指数信号的仿真.ppt...
  19. 【创业者活动】运营弱关系型社区以及创业者交流聚会[2012年12月]
  20. 导出anaconda的代码为pdf

热门文章

  1. t-paas d-paas_什么是PaaS? 平台即服务的解释
  2. 关于手机使用中信号强弱 网速快慢 频段的相关常识
  3. android添加浮动组件,添加悬浮操作按钮  |  Android 开发者  |  Android Developers
  4. Spring Cache key生成策略, 不要想当然认为是全类名+方法+参数
  5. matlab中读取视频的命令,读取视频文件 - MATLAB Simulink - MathWorks 中国
  6. 【心情随笔】2021年终总结
  7. 7.2 Flowable 背压
  8. 【上海房价预测】代码实现——利用BP神经网络进行上海二手房价预测
  9. NLP 语义匹配:经典前沿方案整理
  10. 解决 v-for 出现的 warning:component lists rendered with v-for should have explicit keys