【c++】cout.setf(left)、cout.setf(right)详解
问题引入:今天老师讲解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::left
和ios::right
做了一个或运算(|)
。
那么接着看,ios::left
和ios::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)详解相关推荐
- STL中map和string, vector 用法详解
1. map 用法详解 std map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成 ...
- c++之string类详解
一.包含头文件 要想使用标准C++中string类,必须要包含 #include <string>// 注意是<string>,不是<string.h>,带.h的是 ...
- 天梯赛基础题型详解(2019 - 08 - 12)
A.枚举 (1) 详解:用枚举法,从最开始的只有一层沙漏开始枚举,直至找到一个沙漏所用符号的总和小于等于输入的数(将每一次不同层数的沙漏的符号和都用数组储存起来),然后标记那个最大的和.要注意的是每增 ...
- c 语言的输出函数cout,详解C++ cout格式化输出完全攻略
写算法题的时候突然发现自己忘记基本的C++:cout格式化输出了,赶紧拉出以前的C++学习笔记重新看一看. 部分内容来自教程:C语言中文网(一个很棒的网站) 有时希望按照一定的格式进行输出,如按十六进 ...
- 详解让人闹心的C++语句 cout<<“Hello“<<endl;
语句"cout<<"Hello!"<<endl;"的作用是输出字符串Hello和换行符到屏幕,下面详解这句话! cout是标准库iost ...
- cout的格式控制——关于cout.width()和cout.fill()
今天做C++的高精度的时候发现高精度的模板输出使用到了cout.width()和cout.fill()以便把每个单元存放的四位数字输出 于是就去查找了一下关于cout.width()和cout.fil ...
- cout和std::cout的区别
最近在读C++ Primer Fourth Edition.偶然发现cout和std::cout很有意思.一个是需要引用iostream.h,而另一个需要调用iostream.但他们的功能却又差不多. ...
- C++,cout和std::cout的区别
#include "stdafx.h" #include <stdlib.h> #include <iostream> using namespace st ...
- 计算机基础知识预备知识,计算机预备知识详解.ppt
计算机预备知识详解 Visual C++程序设计 Ch3 简单的输入/输出 > 3.1 cin 输入十六进制或八进制数据 例: int i , j , k , l ; cin>>he ...
- 三维空间刚体运动5:详解SLAM中显示机器人运动轨迹及相机位姿(原理流程)
三维空间刚体运动5:详解SLAM中显示机器人运动轨迹及相机位姿(原理流程) 一.显示运动轨迹原理讲解 二.前期准备 三.git管理子模块及克隆源代码 1.学习使用Git Submodule 2.克隆源 ...
最新文章
- 水稻微生物组时间序列分析
- 某系统响应时间慢TPS低性能瓶颈调优过程
- 【Groovy】Groovy 动态语言特性 ( Groovy 语言与 Java 语言执行效率对比 | 以动态特性编译的 Groovy 类 | 以静态特性编译的 Groovy 类 )
- 字符串,那些你不知道的事
- java编程里的values怎么使用,详解Java编程中super关键字的用法
- 百度之星初赛(1)解题报告
- SecureCRT 中 python 命令行使用退格键(backspace)出现 ^H 解决办法
- springboot超详细教程_CG原画插画教程:超详细线稿教程
- Linux 系统应用编程——网络编程(socket编程)
- 0基础学python做什么工作好-如何快速学习Python编程?可以做什么职业?
- paip.php debug 调试---与OPTIMIZER共存
- 大学里,数据系鄙视物理系,请问二位来自漫画系嘛?
- USB转RS485串口电路设计
- 各大PT网站信息记录(不断更新中)
- 我打算学计算机学英语,英语人教版八年级上册我打算学习计算机科学.doc
- 计算机设置密码打印机无法共享,win7设置开机密码后无法连接共享打印机
- kali无线破解实战
- matlab计算正弦信号基波,Matlab入门篇——正弦信号、实指数信号和复指数信号的仿真.ppt...
- 【创业者活动】运营弱关系型社区以及创业者交流聚会[2012年12月]
- 导出anaconda的代码为pdf
热门文章
- t-paas d-paas_什么是PaaS? 平台即服务的解释
- 关于手机使用中信号强弱 网速快慢 频段的相关常识
- android添加浮动组件,添加悬浮操作按钮 | Android 开发者 | Android Developers
- Spring Cache key生成策略, 不要想当然认为是全类名+方法+参数
- matlab中读取视频的命令,读取视频文件
- MATLAB Simulink
- MathWorks 中国
- 【心情随笔】2021年终总结
- 7.2 Flowable 背压
- 【上海房价预测】代码实现——利用BP神经网络进行上海二手房价预测
- NLP 语义匹配:经典前沿方案整理
- 解决 v-for 出现的 warning:component lists rendered with v-for should have explicit keys