iostream的格式控制
因为scanf和pritf能够很好的控制输入和输出的格式,所以我之前比较少使用iostream流进行格式化的输入输出,或者当用的时候再临时查看C++ Reference。现在,将iostream输入输出的格式控制总结记录如下。
iostream的输入格式控制
正在施工中......
iostream的输出格式控制
格式控制标记
对于iostream的输出格式控制而言,我们可以通过继承自ios_base的fmtflags类型变量来控制(一种使用位掩码表示流格式的标志类型),这个类型可以是以下成员常量的任意有效组合:
类型 | 常量 | 作用效果 |
---|---|---|
独立标志 | boolalpha | 将布尔类型按照true和false的形式输出 |
showbase | 在整数类型的值之前加上数字基数前缀 | |
showpoint | 输出浮点数时,显示小数点 | |
showpos | 输出数值时,显示正负号 | |
skipws | 跳过某些输入操作的前导空格 | |
unitbuf | 每次输出操作后刷新输出 | |
uppercase | 在某些输出情况下,使用大写字母替换小写字母,比如数字基数的前缀 | |
数字基数 | dec | 使用十进制的形式读写整数值 |
hex | 使用十六进制的形式读写整数值 | |
oct | 使用八进制的形式读写整数值 | |
浮点型格式 | fixed | 使用定点表示法输出浮点数 |
scientific | 使用科学计数法输出浮点数 | |
格式调整 | internal | 内部分散对齐,从输出字符宽度内部的某个特定位置进行字符填充 |
left | 左对齐,从输出字符宽度的左侧开始输出,其余位置填充字符 | |
right | 右对齐,从输出字符宽度的右侧开始输出,其余位置填充字符 |
这些标记的使用可以通过setf函数生效,也可以直接使用<<操作符使之生效。
独立标志示例
源代码:
#include<iostream>
using namespace std;
std::ios_base::fmtflags fmtflags_backup;
//备份cout的格式标志
void backupFormatflags(){
fmtflags_backup = cout.flags();
}
//重置cout的格式标志
void resetFormatflags(){
cout.setf(fmtflags_backup);
}
void testBoolalpha(){
backupFormatflags();
bool flag = true;
cout << boolalpha << flag << endl; //输出true
resetFormatflags();
}
void testShowbase(){
backupFormatflags();
cout << showbase << hex << 12345 << endl; //输出12345的十六进制表示0x3039,前面加0x
resetFormatflags();
}
void testShowpoint(){
backupFormatflags();
cout << 12345.0 << endl; //输出12345 不加小数点
cout << showpoint << 12345.0 << endl; //输出12345.0 加小数点
resetFormatflags();
}
void testShowpos(){
backupFormatflags();
cout << showpos << 12345 << endl; //输出+12345,前面有正号
resetFormatflags();
}
void testUppercase(){
backupFormatflags();
cout << uppercase << showbase << hex << 12345 << endl; //输出0X3039,数字基数字符为十六进制,大写字母
resetFormatflags();
}
int main(int argc, char const *argv[]){
// 测试boolalpha
testBoolalpha();
//测试showbase
testShowbase();
//测试showpoint
testShowpoint();
//测试showpos
testShowpos();
//测试uppercase
testUppercase();
return 0;
}
输出结果:
true
0x3039
12345
12345.0
+12345
0X3039
数字基数标记示例
源代码:
#include<iostream>
using namespace std;
int main(int argc, char const *argv[]){
//定义一个要输出显示的变量
int num = 123456;
cout << "八进制:" << oct << num << endl; //输出八进制格式数字
cout << "十进制:" << dec << num << endl; //输出十进制格式数字
cout << "十六进制:" << hex << num << endl; //输出十六进制格式数字
return 0;
}
输出结果:
八进制:361100
十进制:123456
十六进制:1e240
浮点型格式标记示例
源代码:
#include<iostream>
using namespace std;
int main(int argc, char const *argv[]){
//定义一个要输出显示的变量
double num = 12345.6789;
cout << "混合小数点:" << fixed << num << endl; //带小数点的一般输出方法
cout << "科学计数法:" << scientific << num << endl; //科学计数法
return 0;
}
输出结果:
带小数点:12345.678900
科学计数法:1.234568e+04
对齐格式调整标记示例
源代码:
#include<iostream>
using namespace std;
int main(int argc, char const *argv[]){
//定义一个要输出显示的变量
int num = 12345;
cout.fill('*'); //设置填充字符
cout.width(15); //设置输出宽度
//添加了前缀的数字基数标记才能表现出和其他格式的不同指出
cout << internal << showbase << hex << num << endl;
cout.fill('*'); //设置填充字符
cout.width(15); //设置输出宽度
cout << left << num << endl;//左对齐
cout.fill('*'); //设置填充字符
cout.width(15); //设置输出宽度
cout << right << num << endl;//右对齐
return 0;
}
输出结果:
0x*********3039
0x3039*********
*********0x3039
读取和设置格式
因为格式控制标记的生效条件不一样,比如cout.width()
只会对下一次生效,而数字基数的设置是长久生效,那么这就打乱了输出的格式控制。因此,如果我们要进行格式的控制,那么最好只在局部范围内进行改变,然后及时恢复格式。C++提供了flags()函数可以进行格式读取和设置,其中flags函数有两个重载:
//返回当前的格式标记
fmtflags flags() const;
//设置新的格式标记,然后返回原有的格式标记
fmtflags flags (fmtflags fmtfl);
//也可是使用setf函数设置特定的格式标记
使用flags进行格式读取和设置的方法如下所示:
#include<iostream>
using namespace std;
int main(int argc, char const *argv[]){
//定义一个要输出显示的变量
int num = 12345;
cout << "原始格式:" << num << endl;
auto fmt = cout.flags(); //保留原有格式
//指定格式进行输出
cout << "格式调整:";
cout.fill('*'); //设置填充字符
cout.width(15); //设置输出宽度
cout << right << showbase << hex << num << endl;
cout.flags(fmt);
cout << "格式恢复:" << num << endl;
return 0;
}
输出结果:
原始格式:12345
格式调整:*********0x3039
格式恢复:12345
输出格式控制示例
在实际使用中要对字节流按照两位十六进制(大写,不带基数)的格式进行输出,每一个字节之间使用空格隔开,并且每个字节输出两位的宽度(不足的位置填充0字符),对其输出的格式控制如下所示:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<unsigned char> data = {0xA5, 0x5A, 0x16, 0xF0, 0x05, 0xDC, 0x05, 0xDD, 0x03, 0xE8, 0x05, 0xDF, 0x07, 0x76, 0x07, 0x5C, 0x07, 0xAD, 0x06, 0x3C, 0x83, 0xE3, 0xD4, 0xAA };
auto fmtflags = cout.flags();
for(int i = 0; i < data.size(); i++){
cout.width(2);
cout.fill('0');
cout << hex << uppercase << (int)data[i] << " ";
}
cout << endl;
cout.flags(fmtflags);
return 0;
}
输出结果:
A5 5A 16 F0 05 DC 05 DD 03 E8 05 DF 07 76 07 5C 07 AD 06 3C 83 E3 D4 AA
Comments | 1 条评论
博客作者 不找到好工作不改网名
最新C++好像引入了Format,C/C++开发,文件操作也是麻烦的一件事