0
点赞
收藏
分享

微信扫一扫

❥关于C++之用cout进行格式化

紫荆峰 2022-03-21 阅读 73
#include <iostream>
using namespace std;
int main() {
	int i = 273;
	cout << i << endl;
	cout << -i << endl;
	cout << "————————————" << endl;
	double d1 = 1.200;
	cout << d1 << endl;
	cout << (d1 + 1.0) / 9.0 << endl;
	cout << "————————————" << endl;
	double d2 = 1.67E2;
	cout << d2 << endl;
	d2 += 1.0 / 9.0;
	cout << d2 << endl;
	cout << d2 * 1.0e4 << endl;
	cout << "————————————" << endl;
	double d3 = 2.3e-4;
	cout << d3 << endl;
	cout << d3 / 10 << endl;
	return 0;
}
273
-273
————————————
1.2
0.244444
————————————
167
167.111
1.67111e+06
————————————
0.00023
2.3e-05

1.修改显示时使用的计数系统

要控制整数以十进制、十六进制还是八进制显示,可以使用dec、hex和oct控制符。

这句函数调用将cout对象的计数系统格式状态设置为十六进制:hex(cout); 完成设置后,程序将以十六进制形式打印整数值,直到将格式状态设置为其他选项为止。ostream类重载了<<运算符,这使得cout<<hex;与函数调用hex(cout)等价。

#include <iostream>
using namespace std;
int main() {
	int n = 13;
	cout << n << " (decimal)" << endl;
	cout << hex;// set to hex mode
	cout << n << " (hexadecimal)" << endl;
	cout << oct;// set to octal mode
	cout << n << " (octal)" << endl;
	cout << dec;// reset to decimal mode
	cout << n << " (decimal)" << endl;
	return 0;
}
13 (decimal)
d (hexadecimal)
15 (octal)
13 (decimal)

2.调整字段宽度

get (1)	streamsize width() const;
set (2)	streamsize width(streamsize wide);

第一种格式返回字段宽度的当前设置;第二种格式将字段宽度设置为i个空格,并返回以前的字段宽度值。这使得能够保存以前的值,以便以后恢复宽度值时使用。

width()方法只影响将显示的下一个项目,然后字段宽度将恢复为默认值。

#include <iostream>
using namespace std;
int main() {
	cout << "#";
	cout.width(12);
	cout << 12 << "#" << 24 << "#" << endl;
	return 0;
}
#          12#24#

数字12被放到宽度为12个字符的字段的最右边,这被称为右对齐。然后,字段宽度恢复为默认值,并将两个#符号以及24放在宽度与它们的长度相等的字段中。默认填充是空格,默认对齐是右对齐。

注:C++永远不会截短数据,因此如果试图在宽度为2的字段中打印一个7位值,C++将增宽字段,以容纳该数据。

3.填充字符

在默认情况下,cout用空格填充字段中未被使用的部分,可以用fill()成员函数来改变填充字符。

#include <iostream>
using namespace std;
int main() {
	cout.fill('*');
	long bonus[2] = {900, 13508};
	for (int i = 0; i < 2; i++) {
		cout << "$";
		cout.width(7);
		cout << bonus[i] << endl;
	}
	return 0;
}
$****900
$**13508

4.设置浮点数的显示精度

浮点数精度的含义取决于输出模式。在默认模式下,它指的是显示的总位数。在定点模式和科学模式下,精度指的是小数点后面的位数。已经知道,C++的默认精度为6位(但末尾的0将不显示)。precision()成员函数使得能够选择其他值。

#include <iostream>
using namespace std;
int main() {
	float price1 = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;
	cout << "price1 = $" << price1 << endl;
	cout << "price2 = $" << price2 << endl;
	cout.precision(2);
	cout << "now price1 = $" << price1 << endl;
	cout << "now price2 = $" << price2 << endl;
	return 0;
}
price1 = $20.4
price2 = $2.78889
now price1 = $20
now price2 = $2.8

5.打印末尾的0和小数点

对于有些输出(如价格或栏中的数字),保留末尾的0将更为美观。例如,对于上述程序清单的输出,$20.40将比$20.4更美观。

ios_base类提供了一个setf()函数(用于set标记),能够控制多种格式化特性。这个类还定义了多个常量,可用作该函数的参数。例如,下面的函数调用使cout显示末尾小数点:

cout.setf(ios_base::showpoint);

使用默认的浮点格式时,上述语句还将导致末尾的0被显示出来。也就是说,如果使用默认精度(6位)时,cout不会将2.00显示为2,而是将它显示为2.000000。

#include <iostream>
using namespace std;
int main() {
	float price1 = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;
	cout.setf(ios_base::showpoint);
	cout << "price1 = $" << price1 << endl;
	cout << "price2 = $" << price2 << endl;
	cout.precision(2);
	cout << "now price1 = $" << price1 << endl;
	cout << "now price2 = $" << price2 << endl;
	return 0;
}
price1 = $20.4000
price2 = $2.78889
now price1 = $20.
now price2 = $2.8

在上述输出中,第一行显示了;第三行显示了小数点,但没有显示末尾的0,这是因为精度被设置为2,而小数点前面已经包含两位。

6.再谈setf()

ios_base类有一个受保护的数据成员,其中的各位标记分别控制着格式化的各个方面,例如计数系统、是否显示末尾的0等。打开一个标记称为设置标记(或位),并意味着相应的位被设置为1。位标记是编程开关,相当于设置DIP开关以配置计算机硬件。例如,hex、dec和oct控制符调整控制计数系统的3个标记位。setf()函数提供了另一种调整标记位的途径。

set (1)	 fmtflags setf (fmtflags fmtfl);
mask (2) fmtflags setf (fmtflags fmtfl, fmtflags mask);

fmtflags是bitmask类型的typedef名,用于存储格式标记。该名称是在ios_base类中定义的。这个版本的setf( )用来设置单个位控制的格式信息。参数是一个fmtflags值,指出要设置哪一位。返回值是类型为fmtflags的数字,指出所有标记以前的设置。如果打算以后恢复原始设置,则可以保存这个值。应给setf( )传递什么呢?如果要第11位设置为1,则可以传递一个第11位为1的数字。返回值的第11位将被设置为1。对位进行跟踪好像单调乏味(实际上也是这样)。然而,您不必作做这项工作,ios_base类定义了代表位值的常量,下表列出了其中的一些定义。

常量含义
ios_base::boolalpha输入和输出bool值,可以为true或false
ios_base::showbase对于输出,使用C++基数前缀(0,0x)
ios_base::showpoint显示末尾的小数点
ios_base::uppercase对于16进制输出,使用大写字母,E表示法
ios_base::showpos在正数前面加上“+”

 

 

 

 

 

 

#include <iostream>
using namespace std;
int main() {
	int temperature = 63;
	cout.setf(ios_base::showpos);// show plus sign
	cout << temperature << endl;
	cout << hex << temperature << endl;// use hex
	cout.setf(ios_base::uppercase);// use uppercase in hex
	cout.setf(ios_base::showbase);// use 0X prefix for hex
	cout << "check result:" << true << endl;
	cout.setf(ios_base::boolalpha);// can show true/false
	cout << "check result:" << true << endl;
	return 0;
}
+63
3f
check result:0X1
check result:true

注意,仅当基数为10时才使用加号。C++将十六进制和八进制都视为无符号的,因此对它们,无需使用符号。

第二个setf()原型接受两个参数,并返回以前的设置fmtflags setf(fmtflags fmtfl, fmtflags mask);

函数的这种重载格式用于设置由多位控制的格式选项。第一参数和以前一样,也是一个包含了所需设置的fmtflags值。第二参数指出要清除第一个参数中的哪些位。例如,将第3位设置为1表示以10为基数,将第4位设置为1表示以8为基数,将第5位设置为1表示以16为基数。假设输出是以10为基数的,而要将它设置为以16为基数,则不仅需要将第5位设置为1,还需要将第3位设置为0——这叫作清除位(clearing the bit)。聪明的十六进制控制符可自动完成这两项任务。使用函数setf()时,要做的工作多些,因为要用第二参数指出要清除哪些位,用第一参数指出要设置哪位。这并不像听上去那么复杂,因为ios_base类为此定义了常量(如下表所示)。具体地说,要修改基数,可以将常量ios_base::basefield用作第二参数,将ios_base::hex用作第一参数。也就是说,下面的函数调用与使用十六进制控制符的作用相同:

cout.setf(ios_base::hex, ios_base::basefield);

ios_base类定义了可按这种方式处理的3组格式标记。每组标记都由一个可用作第二参数的常量和两三个可用作第一参数的常量组成。第二参数清除一批相关的位,然后第一参数将其中一位设置为1。上表列出了用作setf()的第二参数的常量的名称、可用作第一参数的相关常量以及它们的含义。

例如,要选择左对齐,可将ios_base::adjustfield用作第二参数,将ios_base::left作为第一参数。左对齐意味着将值放在字段的左端,右对齐则表示将值放在字段的右端。内部对齐表示将符号或基数前缀放在字段左侧,余下的数字放在字段的右侧(遗憾的是,C++没有提供自对齐模式)。

定点表示法意味着使用格式123.4来表示浮点值,而不管数字的长度如何,科学表示法则意味着使用格式1.23e04,而不考虑数字的长度。如果你熟悉C语言中printf()的说明符,则可能知道,默认的C++模式对应于%g说明符,定点表示法对应于%f说明符,而科学表示法对应于%e说明符。

在C++标准中,定点表示法和科学表示法都有下面两个特征:

  • 精度指的是小数位数,而不是总位数;
  • 显示末尾的0。

setf()函数是ios_base类的一个成员函数。由于这个类是ostream类的基类,因此可以使用cout对象来调用该函数。例如,要左对齐,可使用下面的调用:

ios_base::fmtflags old = cout.setf(ios::left, ios::adjustfield);

要恢复以前的设置,可以这样做:

cout.setf(old, ios::adjustfield);

。。。。未完待续。。。。

举报

相关推荐

0 条评论