在C++里,我们使用cout进行控制台文本输出。这在学习编程的阶段很常用,但在真实的工作场合却极少使用,毕竟大部分的应用程序都是基于图形界面,而不是终端的。甚至,在C/C++的某些应用场合,比如单片机编程里,嵌入式设备甚至连屏幕都没有。
考虑到部分OJ系统中的在线编程题可能对输出格式作出精细要求,这里我们对cout控制输出进行“详细”讨论:包括cout的基本工作原理,以及通过cout进行精细格式输出的方法。
下述代码可以帮助我们理解通过cout的插入操作符(insertion operator<<)进行控制台文本输出的基本原理。
- //Project - COUT
- #include
- using namespace std;
-
- int main() {
- cout << "pi = " << 3.14159 << endl;
- operator<<(cout,"pi = ").operator<<(3.14159).operator<<(endl);
- return 0;
- }
上述代码的执行结果为:
pi = 3.14159
pi = 3.14159
在iostream头文件中,很容易找到cout的定义。cout是一个类型为ostream的对象,其被连接到了标准输出流,即控制台。
extern ostream cout; /// Linked to standard output
上述程序的第6行与第7行完全等价。相关代码的执行过程如下:
<<操作符在C语言里用作左移位操作,C++的标准模板库通过定义与该操作符“同名”的函数,扩展了该操作符的功能:向cout输出对象内容。
总结:iostream定义了多个重载的operator<<()操作符函数,这些不同版本的函数接受不同类型的参数,包括int, char, float, double, const char*, string等,并将这些参数对象转换成字符串,并输出到控制台屏幕上。
2. 改变进制
- //Project - HexOct
- #include
- #include
- using namespace std;
-
- int main(){
- int b = 0x17; //十六进制 hexadecimal
- int c = 017; //八进制 octal
- int d = 0b01111110; //二进制 binary
-
- cout << "0x17 = " << b << ", 017 = " << c << ", 0b01111110 = " << d << endl;
- printf("17: %x, %d, %o\n", 17, 17, 17);
- cout << "17: " << hex << 17 << ", " << dec << 17 << ", " << oct << 17 << endl;
-
- hex(cout);
- cout << "17: " << 17 << ", ";
- dec(cout);
- cout << 17 << ", ";
- oct(cout);
- cout << 17 << endl;
-
- return 0;
- }
上述代码的执行结果为:
0x17 = 23, 017 = 15,0b01111110= 126
17: 11, 17, 21
17: 11, 17, 21
17: 11, 17, 21
上述代码可以看出,通过执行cout << hex,可以改变cout的内部状态,使用在后续输出数值时使用16进制。cout << dec (十进制),cout << oct (八进制)同理。
事实上,这里的hex, dec, oct是一种被称之为操作算子(manipulator)的特殊函数。下述3行代码事实上等价:
- cout << hex;
- cout.operator<<(hex);
- hex(cout);
在ios_base.h中我们可以找到hex()函数的定义:
- inline ios_base&
- hex(ios_base& __base)
- {
- __base.setf(ios_base::hex, ios_base::basefield);
- return __base;
- }
在形式上,cout << hex被解释成多轮函数调用,首先是:
cout.operator<<(hex);
这个被重载的operator<<()函数将hex函数名当成一个函数指针,然后通过这个函数指针调用hex()函数:
hex(cout);
而hex()函数又通过cout的setf()函数发挥作用。读者或许会疑惑说,这么多层的函数调用是否会降低代码的执行效率,事实上,由于相关函数多是内联(inline)的,编译器的优化会消除这些“形式”上的不必要的函数调用。
- #include
- #include
- using namespace std;
-
- int main(){
- cout << "12345678901234567890" << endl;
- cout << "--------------------" << endl;
-
- cout.width(5);
- cout << "N";
- cout.width(15);
- cout << "2**N" << endl;
- cout << "--------------------" << endl;
-
- for (auto n=0;n<=10;n++){
- cout.width(5);
- cout << n;
- cout.width(15);
- cout << pow(2,n) << endl;
- }
-
- return 0;
- }上述代码的执行结果为:12345678901234567890
- --------------------
- N 2**N
- --------------------
- 0 1
- 1 2
- 2 4
- 3 8
- 4 16
- 5 32
- 6 64
- 7 128
- 8 256
- 9 512
- 10 1024
cout的成员函数width( )可以设定下一个输出项的宽度,但其作用范围仅限后一个输出项。当输出项的实际宽度小于设定宽度时,其左侧以空格填充。可以看到,上述程序借助于width( )函数,输出了一个严格右对齐的表格,第一列的宽度为5,第2列的宽度为15。
通过fill( )成员函数,可以修改填充字符。请参见下述程序及其执行结果。
- #include
- using namespace std;
-
- int main(){
- cout.fill('*'); //修改填充字符为*
- cout.width(5);
- cout << "idx";
- cout.width(15);
- cout << "content";
- return 0;
- }
上述程序的执行结果为:
**idx********content
4. 浮点数的输出格式
通过cout的precision( )函数可以设置其输出浮点数时的精度。见下述代码。
- #include
- using namespace std;
-
- int main(){
- float v1 = 17.90f;
- float v2 = 3.1415926535798932f;
- cout << "before .precision(2)" << endl;
- cout << "v1 = " << v1 << endl;
- cout << "v2 = " << v2 << endl;
-
- cout.precision(2);
- cout << "after .precision(2)" << endl;
- cout << "v1 = " << v1 << endl;
- cout << "v2 = " << v2 << endl;
-
- return 0;
- }
执行结果为:
before .precision(2)
v1 = 17.9
v2 = 3.14159
after .precision(2)
v1 = 18
v2 = 3.1
上述执行结果与我们的期望有很大不同。
在默认情况下,cout输出浮点数的精度为6,且这个精度并不是指小数点后的位数,而是所有的位数。cout会借助于四舍五入的方法输出指定“精度”的字符串,同时会舍弃末尾多余的0。
执行结果的第2行显示,17.90被舍弃掉末尾的0,输出为17.9。
执行结果的第3行显示,3.1415926535798932被四舍五入为3.14159,正好6位数字。
接下来,cout.precision(2)设定浮点数输出精度为2,此时,17.90被四舍五入输出为18,3.1415926535798932被四舍五入输出为3.1,都是两位数字。
如果期望cout输出的浮点数的位数确定,当位数不足时用0补齐,可以执行cout.setf(ios_base::showpoint)。
- #include
- using namespace std;
-
- int main(){
- float v1 = 17.90f;
- float v2 = 3.1415926535798932f;
-
- cout.setf(ios_base::showpoint);
- cout.precision(4);
- cout << "v1 = " << v1 << endl;
- cout << "v2 = " << v2 << endl;
-
- return 0;
- }
执行结果为:
v1 = 1.7900e+001
v2 = 3.1416e+000
然后今天就讲到这里啦,大家记得点赞收藏,分享转发,关注小哥哥哦! 最后,如果你想学或者正在学C/C++编程,可以加入小编的编程学习C/C++企鹅圈
https://jq.qq.com/?_wv=1027&k=vLNylJeG