C++ day43 C++ I/O (二) 深入剖析cout物件

2020-07-31 23:05:17

本文主要介紹cout物件的很多方法,這些方法是機器重要的,是cout可以完成輸出任務的關鍵祕訣。

文章目錄

把數值型別轉換爲字元流(文字格式)

過載插入運算子:把值轉換爲文字格式

insertion operator

  • 所有過載版本的返回值型別都是ostream &

  • <<預設含義是按位元左移運算子。但是由於他長得像資訊流動,所以就被ostream類發現了,並把它過載了,他就獲得了一份新工作,一個新角色。

14個內建數據型別都有過載版本

並且ostream類過載的非常詳細,<<可以識別到C++的所有基本數據型別(14個,11個整型,3個浮點型),即C++給這些數據型別的每一個都提供了一個過載版本。
在这里插入图片描述

比如:

cout << 34;//ostream & operator<<(int);

把14中內建基本型別的值都可以轉換爲文字形式,比如把-2.45轉換爲5個字元,’-’, ‘2’, ‘.’, ‘4’, ‘5’

字元指針型別也有過載版本

在这里插入图片描述
char陣列名,顯式char指針,用引號括起來的C字串都是字串指針,因爲C++就是用字串指針來表示字串的。

除了字串指針之外的指針,C++就認爲是void *,就會列印地址,即指針變數中存的值,而不是列印字串了。

如果你不想列印字串,而是想列印出字串的地址,那就強制轉換爲void *就好啦。

範例:用void *列印字串的地址

#include <iostream>

int main()
{
    using std::cout;
    using std::endl;

    int eggs = 12;
    char * amount = "dozen";
    cout << &eggs << endl;//列印地址
    cout << amount << endl;//列印字串
    cout << (void *) amount << endl;//列印地址
    return 0;
}
0x6efef8
dozen
0x4ba025

拼接輸出:非常好的設計特性!因爲返回值型別都是ostream &

插入運算子的過載版本返回的都是呼叫他們的物件
在这里插入图片描述
在这里插入图片描述

put():用於顯示字元;現爲模板函數;也可以拼接輸出

  • 是ostream類的成員方法,所以cout物件可以呼叫
  • 最開始的原型:
ostream & put(char);

後來爲了用於wchar_t, 把他變成了模板函數,即參數可以是char,可以是wchar_t.

  • 拼接輸出:
cout.put('i').put('t');

write():用於顯示整個字串

basic_ostream<charT, traits> & write(const char_type * s, streamsize n);//第一個參數是字串的地址,第二個參數是要顯示的字元的數目

範例

#include <iostream>
#include <cstring>

int main()
{
    using std::cout;
    using std::endl;

	const char * state1 = "Florida";
	const char * state2 = "Kansas";
	const char * state3 = "Euphoria";

	int len = std::strlen(state2);
	cout << "Increasing loop index:\n";
	int i;
	for (i=1;i<=len;++i){
		cout.write(state2, i);
		cout << endl;
	}

	cout << "Decreasing loop index:\n";

	for (i=len;i>=1;--i){
		cout.write(state2, i);
		cout << endl;
	}

	cout.write(state2, len + 10) << endl;

    return 0;
}

state1, state3兩個字串只是爲了便於觀察長度超出state2的長度時會顯示什麼。

這幾個C字串都存在一起的誒,地址連着的。

Increasing loop index:
K
Ka
Kan
Kans
Kansa
Kansas
Decreasing loop index:
Kansas
Kansa
Kans
Kan
Ka
K
Kansas Euphoria
  • 我又試了試超出的多一點:
cout.write(state2, len + 20) << endl;

輸出是:

Kansas Euphoria     Index

可以看到,記憶體中有啥就輸出啥了

  • 注意,write方法也可以和插入運算子拼接:
cout.write(state2, len + 10) << endl;

給write()傳入數值,它會逐位元組解釋爲ascii碼(神奇)

#include <iostream>

int main()
{
	long val = 560031841;
	cout.write((char *) &val, sizeof(long));
    return 0;
}
aha!
Process returned 0 (0x0)   execution time : 0.575 s
Press any key to continue.

560031841轉換爲32二進制是(我的計算機上,long佔4個位元組):

00100001 01100001 01101000 01100001

分別轉換爲是十進制,對應於:33 97 104 97

把他們當做ascii碼,倒着看就是aha!

重新整理輸出緩衝區:endl控制符,flush控制符

控制符 manipulator

之前說過了,C++使用緩衝區來匹配不同的傳輸速率,但是如果輸出不是輸出到檔案,而是輸出到螢幕,則其實速率差別並不大,而且我們也絕對不想等到緩衝區的512位元組都滿了,才全部一起顯示到螢幕呀,畢竟我們需要看輸出的資訊。

所以輸出到螢幕的話,重新整理輸出緩衝區的條件不是緩衝區滿,而是使用控制符,C++定義了兩個控制符用來強行重新整理緩衝區,即把緩衝區的所有數據轉移到螢幕:flush和endl。

  • flush控制符:重新整理緩衝區
  • endl控制符:重新整理緩衝區並插入一個換行符

其實大多數場景都是希望在輸入即將發生時輸出緩衝區,因爲一般輸入都需要提前輸出對應的輸入提示資訊。

範例:輸出到螢幕不需要等緩衝區滿才重新整理

#include <iostream>
#include <cstring>

int main()
{
    using std::cout;
    using std::endl;

	cout << "Hello good-looking! " << std::flush;
	cout << "Wait just a moment, please." << endl;
	cout << "Hello good-looking! " << std::flush;
    return 0;
}
Hello good-looking! Wait just a moment, please.
Hello good-looking!

控制符的本質是函數

cout << flush;//相當於flush(cout);

這是因爲ostream類對<<進行了過載,當參數爲函數物件時,就呼叫這個函數並把cout作爲參數。

用cout格式化輸出:使用ios_base類的成員函數來控制欄位寬度和小數位數等格式狀態

ostream是ios_base類的間接基礎類別(ios_base是ios類的基礎類別,ios類是ostream類的基礎類別),所以ostream類的物件cout可以使用ios_base類的方法。

範例:先看看cout的預設格式

#include <iostream>

int main()
{
    using std::cout;

	cout << "12345678901234567890\n";
	char ch = 't';
	int t = 123;
	cout << ch << ":\n";
	cout << t << ":\n";
	cout << -t << ":\n";

	double f1 = 1.200;
	cout << f1 << ":\n";
	cout << (f1+1.0/9.0) << ":\n";

	double f2 = 1.57e2;
	cout << f2 << ":\n";
	f2 += 1.0/9.0;
	cout << f2 << ":\n";
	cout << (f2*1.0e4) << ":\n";

	double f3 = 2.3e-4;
	cout << f3 << ":\n";
	cout << f3/10 << ":\n";

    return 0;
}

加個冒號是爲了看欄位寬度的。

可以看到,1.200末尾的0沒有被顯示。這是因爲,C++預設不顯示浮點數結尾的0

12345678901234567890
t:
123:
-123:
1.2:
1.31111:
157:
157.111:
1.57111e+006:
0.00023:
2.3e-005:

修改顯示整數的計數系統:控制符dec, hex, oct(十進制,十六進制,八進制)

//設定cout物件的計數系統格式狀態爲十六進制,即以十六進制來列印整數
hex(cout);//相當於cout << hex;

和剛纔的flush一樣,控制符是函數。但是注意,不是成員函數哈。

範例

#include <iostream>

int main()
{
    using std::cout;

	int n = 15;
	cout << n << ' ' << n*n << " decimal\n";

	//十六進制
	cout << std::hex;
	cout << n << ' ' << n*n << " hexadecimal\n";

	//八進制
	cout << std::oct << n << ' ' << n*n << " octal\n";

	//回到十進制
	dec(cout);
	cout << n << ' ' << n*n << " decimal\n";
    return 0;
}
15 225 decimal
f e1 hexadecimal
17 341 octal
15 225 decimal

調整欄位寬度:對齊;width()成員方法

在这里插入图片描述

欄位寬度是指一個字串的最大長度,如果設定爲10, 則就只能顯示最多10個字元,但是如果字串多於10個字元,C++當然不會給你截短,只顯示前10個字元,沒那麼僵硬,而是會自動增長欄位長度,然後完整的顯示字串。

範例:預設右對齊,用空格填滿左邊空位

#include <iostream>

int main()
{
    using std::cout;

	int w = cout.width(30);
	cout << "default field width = " << w << ":\n";
	cout.width(5);
	cout << "N" << ":\n";
	cout << "N * N" << ":\n";
	for (long i=1;i<=100;i *= 10){
		cout.width(5);
		cout << i << ':';
	    cout.width(8);
		cout << i*i << ":\n";
	}
    return 0;
}
  • 預設欄位寬度竟然是0?????是的!!!

這是因爲C++會增長欄位,以完整地容納數據

  • 欄位都是預設右對齊的,左邊用空格填充。

用來填充的字元叫做填充字元,fill character, 這裏是空格。

        default field width = 0:
    N:
N * N:
    1:       1:
   10:     100:
  100:   10000:

如果想要左對齊,可以用left控制符

#include <iostream>

int main()
{
    using std::cout;
    cout << std::left;
	int w = cout.width(30);
	cout << "default field width = " << w << ":\n";
	cout.width(5);
	cout << "N" << ":\n";
	cout << "N * N" << ":\n";
	for (long i=1;i<=100;i *= 10){
		cout.width(5);
		cout << i << ':';
	    cout.width(8);
		cout << i*i << ":\n";
	}
    return 0;
}
default field width =         0:
N    :
N * N:
1    :1       :
10   :100     :
100  :10000   :

範例:用fill()成員函數改變填充字元

但是fill()不同於width(), 它一旦設定了,就一直有效。

#include <iostream>

int main()
{
    using std::cout;

	int w = cout.width(30);
	cout.fill('-');
	cout << "default field width = " << w << ":\n";
	cout.width(5);
	cout << "N" << ":\n";
	cout << "N * N" << ":\n";
	for (long i=1;i<=100;i *= 10){
		cout.width(5);
		cout << i << ':';
	    cout.width(8);
		cout << i*i << ":\n";
	}
    return 0;
}
--------default field width = 0:
----N:
N * N:
----1:-------1:
---10:-----100:
--100:---10000:

設定浮點數的顯示精度,precision()成員函數

  • 和fill()一樣,一旦設定,一直有效。
  • C++的預設精度是6
  • 浮點數有三種輸出模式:定點模式,科學模式,預設模式。精度的具體含義取決於輸出模式,如果在預設模式,則精度指的是顯示的總位數;而科學模式和定點模式中,精度指的是小數點後面的位數

在这里插入图片描述

範例:預設模式

#include <iostream>

int main()
{
    using std::cout;

	float price1 = 20.40;
	float price2 = 1.9 + 8.0/9.0;
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

    return 0;
}

可以看到,第三行連小數點都不顯示了,因爲只讓顯示2位。這裏的截短不是C++做的,是程式設計師自己要截短的,怪不着C++,C++沒有私自背地裏偷摸摸的給截短。

"Furry Friends" is $20.4!
"Fiery Friends" is $2.78889!
"Furry Friends" is $20!
"Fiery Friends" is $2.8!

要怎麼進入科學輸出模式和定點輸出模式呢??

——使用控制符fixed和scientific!

定點模式

#include <iostream>

int main()
{
    using std::cout;


	float price1 = 20.40;
	float price2 = 1.9 + 8.0/9.0;

	cout << std::fixed;//定點輸出模式
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

    return 0;
}
"Furry Friends" is $20.400000!
"Fiery Friends" is $2.788889!
"Furry Friends" is $20.40!
"Fiery Friends" is $2.79!

科學模式:

#include <iostream>

int main()
{
    using std::cout;

	float price1 = 20.40;
	float price2 = 1.9 + 8.0/9.0;

	cout << std::scientific;//定點輸出模式
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

    return 0;
}
"Furry Friends" is $2.040000e+001!
"Fiery Friends" is $2.788889e+000!
"Furry Friends" is $2.04e+001!
"Fiery Friends" is $2.79e+000!
顯示小數點和末尾的0:ios_base類的setf()函數,ios_base類的靜態常數showpoint

從上面的範例可以看到,C++預設是不會顯示末尾的0,如果精度太少,則也不會顯示小數點。

但是有時候,比如顯示賬目,把小數點和0都顯示出來更加美觀。但是iostream類沒有提供相關方法,ios_base類提供了。

注意showpoint是ios_base類的類級靜態常數,即其具有類作用域,所以如果在類的成員方法外面用它,則要用作用域運算子說明ios_base類。

#include <iostream>

int main()
{
    using std::cout;
    using std::ios_base;

	float price1 = 20.40;
	float price2 = 1.9 + 8.0/9.0;

	cout.setf(ios_base::showpoint);//顯示小數點,且顯示末尾0
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

    return 0;
}

20已經佔用了2位,所以小數點顯示了就不會再顯示後面的了。而且可以看到,小數點並沒有佔精度位。

"Furry Friends" is $20.4000!
"Fiery Friends" is $2.78889!
"Furry Friends" is $20.!
"Fiery Friends" is $2.8!

setf():調整標記位的另一種途徑

setf()是ios_base類的一個成員函數

ios_base類的其他格式常數

ios_base類有一個受保護的數據成員,它的每一位,都表示和控制着輸出格式化的一個方面。比如有3個bit表示計數系統,hex,dec, oct。

除了上面展示的用控制符來改變輸出格式狀態外,還可以用setf()方法。

setf()有兩種過載版本
第一種:

fmtflags setf(fmtflags);//用於設定單個位控制的格式資訊,返回的是設定之前的資訊

fmtflags是bitmask類的typedef名稱,用來儲存格式標記,在ios_base類中定義。bitmask類的關鍵思想是每一位都可以單獨存取,且都有自己的含義。iostream包使用bitmask來儲存狀態資訊。bitmask型別可以是整型,列舉或者STL的bitset容器。

fmtflags常數已經被ios_base類定義了, 我們不需要記住數位,直接傳入這些常數就好啦,但是要知道他們實際上就是bitmask型別的值哦,即fmtflags的值。

在这里插入图片描述

範例:setf()的第一個原型
#include <iostream>

int main()
{
    using std::cout;
    using std::endl;
    using std::ios_base;

    int temperature = 63;
    cout << "Today's water temperature:";
    cout.setf(ios_base::showpos);//在十進制正數前面顯示+符號
    cout << temperature << endl;

    cout << "For our programming friends, that's ";
    cout << std::hex << temperature << endl;
    cout.setf(ios_base::uppercase);//對16禁進位制輸出,用大寫字母(只針對16進位制)
    cout.setf(ios_base::showbase);//顯示基數字首0x
    cout << "or\n";
    cout << temperature << endl;
    cout << "How " << true << "! oops -- How ";
    cout.setf(ios_base::boolalpha);//顯示true或者false
    cout << true << "!\n";

    return 0;
}
Today's water temperature:+63
For our programming friends, that's
3f
or
0X3F
How 0X1! oops -- How true!

學到的點:

  • showpos只適用於十進制,因爲C++把八進制和十六進制都當做是無符號的,所以沒有給十六進制的正數前面顯示+
  • uppercase只適用於十六進制,因爲8進位制和10進位制都沒有字母。
範例:setf()的第二個原型
fmtflags setf(fmtflags, fmtflags);//返回的也是設定之前的資訊

第一個參數用來表示要設定哪些位(比如floatfield則設定科學位和定點位這兩個位元,其他位置完全不影響),和第一個原型的那個參數的功能一樣;第二個參數用來表示要清除哪些位,比如你要把進位制從十進制改爲16進位制,則要把hex那一位改爲1,還要把dec那一位改爲0呀。

而且由於ios_base類已經定義好了常數,就特別方便。
在这里插入图片描述
左對齊:把值放在欄位的左端。
內部對齊:把符號或者基數字首放在欄位左端,而數位放在欄位右邊。

範例

#include <iostream>
#include <cmath>

int main()
{
    using std::cout;
    using std::endl;
    using std::ios_base;

    cout.setf(ios_base::left, ios_base::adjustfield);//左對齊left justification
    cout.setf(ios_base::showpos);//顯示正數前面的符號
    cout.setf(ios_base::showpoint);//顯示小數點
    cout.precision(3);

    //使用科學模式
    ios_base::fmtflags old = cout.setf(ios_base::scientific, ios_base::floatfield);//存住舊的儲存格式
    long n;
    cout << "左對齊\n";
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << " \n";
    }
    cout.setf(ios_base::internal, ios_base::adjustfield);
    cout.setf(old, ios_base::floatfield);
    cout << "內部對齊\n";
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << "|\n";
    }
    cout << "右對齊\n";
    cout.setf(ios_base::right, ios_base::adjustfield);
    cout.setf(ios_base::fixed, ios_base::floatfield);
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << "|\n";
    }

    return 0;
}
左對齊
+1  |+1.000e+000
+11 |+3.317e+000
+21 |+4.583e+000
+31 |+5.568e+000
+41 |+6.403e+000
內部對齊
+  1|+       1.00|
+ 11|+       3.32|
+ 21|+       4.58|
+ 31|+       5.57|
+ 41|+       6.40|
右對齊
  +1|      +1.000|
 +11|      +3.317|
 +21|      +4.583|
 +31|      +5.568|
 +41|      +6.403|

學到的點:

  • 科學輸出模式的指數位數隨實現而異,這裏是三位。
  • 沒有預設模式的一個標記位。只有科學位和定點位兩位,只有科學位被設定則爲科學模式,只有定點位被設定則爲定點模式,否則(都沒設定或者都設定)則爲預設模式。

可以用下面 下麪這句程式碼設定爲預設模式,注意要強制轉換,不然會報錯,說不能把int轉換爲fmtflags型別:

 cout.setf((ios_base::fmtflags)0, ios_base::floatfield);//第一個參數表示不設定任何位(科學位和定點位都不設定)
#include <iostream>
#include <cmath>

int main()
{
    using std::cout;
    using std::endl;
    using std::ios_base;

    cout.setf(ios_base::left, ios_base::adjustfield);//左對齊left justification
    cout.setf(ios_base::showpos);//顯示正數前面的符號
    cout.setf(ios_base::showpoint);//顯示小數點
    cout.precision(3);

    //使用科學模式
    ios_base::fmtflags old = cout.setf(ios_base::scientific, ios_base::floatfield);//存住舊的儲存格式
    long n;
    cout << "左對齊(科學模式)\n";
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << " \n";
    }
    cout.setf(ios_base::internal, ios_base::adjustfield);
    cout.setf(old, ios_base::floatfield);
    cout << "內部對齊(預設模式)\n";
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << "|\n";
    }
    cout << "右對齊(定點模式)\n";
    cout.setf(ios_base::right, ios_base::adjustfield);
    cout.setf(ios_base::fixed, ios_base::floatfield);
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << "|\n";
    }
    //使用預設模式
    cout << "右對齊(預設模式)\n";
    cout.setf((ios_base::fmtflags)0, ios_base::floatfield);
    for (n=1;n<=41;n+=10){
        cout.width(4);
        cout << n << "|";
        cout.width(12);
        cout << sqrt(double(n)) << "|\n";
    }

    return 0;
}
左對齊(科學模式)
+1  |+1.000e+000
+11 |+3.317e+000
+21 |+4.583e+000
+31 |+5.568e+000
+41 |+6.403e+000
內部對齊(預設模式)
+  1|+       1.00|
+ 11|+       3.32|
+ 21|+       4.58|
+ 31|+       5.57|
+ 41|+       6.40|
右對齊(定點模式)
  +1|      +1.000|
 +11|      +3.317|
 +21|      +4.583|
 +31|      +5.568|
 +41|      +6.403|
右對齊(預設模式)
  +1|       +1.00|
 +11|       +3.32|
 +21|       +4.58|
 +31|       +5.57|
 +41|       +6.40|
  • 可以用unsetf()方法復原剛纔setf()的設定,原型:
    在这里插入图片描述

範例:

#include <iostream>

int main()
{
    using std::cout;
    using std::ios_base;

	float price1 = 20.40;
	float price2 = 1.9 + 8.0/9.0;

	cout.setf(ios_base::showpoint);//顯示小數點,且顯示末尾0
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

	cout.unsetf(ios_base::showpoint);
	cout.precision(2);
	cout << "\"Furry Friends\" is $" << price1 << "!\n";
	cout << "\"Fiery Friends\" is $" << price2 << "!\n";

    return 0;
}
"Furry Friends" is $20.4000!
"Fiery Friends" is $2.78889!
"Furry Friends" is $20.!
"Fiery Friends" is $2.8!
"Furry Friends" is $20!
"Fiery Friends" is $2.8!

另一個範例:

#include <iostream>

int main()
{
    using std::cout;
    using std::endl;
    using std::ios_base;

    int temperature = 63;
    cout << "Today's water temperature:";
    cout.setf(ios_base::showpos);//在十進制正數前面顯示+符號
    cout << temperature << endl;

    cout << "For our programming friends, that's ";
    cout << std::hex << temperature << endl;
    cout.setf(ios_base::uppercase);//對16禁進位制輸出,用大寫字母(只針對16進位制)
    cout.setf(ios_base::showbase);//顯示基數字首0x
    cout << "or\n";
    cout << temperature << endl;
    cout << "How " << true << "! oops -- How ";
    cout.setf(ios_base::boolalpha);//顯示true或者false
    cout << true << "!\n";
    cout.unsetf(ios_base::boolalpha);//不顯示true或者false
    cout << true << "!\n";

    return 0;
}
Today's water temperature:+63
For our programming friends, that's 3f
or
0X3F
How 0X1! oops -- How true!
0X1!
  • 無論cout現在處於哪種模式unsetf(ios_base::field);都會切換回預設模式

標準控制符:對使用者最友好的格式化方法,可替代setf()方法

setf()成員方法可以設定格式,但是需要提供各種常數參數,不是很方便,C++爲了使用者控制格式更方便,就提供了很多控制符。比如dec, hex, oct

cout << dec << left << fixed;//使用十進制計數,顯示左對齊,定點模式輸出浮點數

其他的控制符還有:
在这里插入图片描述
在这里插入图片描述

這張表的右邊是用setf()或者unsetf()方法,可以看到使用控制符真的方便很多,打字都少了好多。

這都要歸功於過載的插入運算子哇。

標頭檔案iomanip:提供了除了標準控制符外的其他控制符,用於設定欄位寬度,精度,填充字元等

io manipulator 輸入輸出控制符

前面的標準控制符不能設定欄位寬度,所以iomanip標頭檔案又加了一些控制符,但是這些控制符和標準控制符不一樣,=他們帶參數,但是他們不是成員函數,仍然是控制符,所以還是用插入運算子使用它們!!

  • setprecision():設定精度,接受一個指定精度的整數參數
  • setfill():接受一個指定填充字元的char參數
  • setw():接受一個指定欄位寬度的整數參數

範例:非常好!美觀

#include <iostream>
#include <iomanip>
#include <cmath>

int main(){
    using namespace std;
    cout << fixed << right;
    cout << setw(6) << "N" << setw(14) << "square root"
         << setw(15) << "fourth root\n";

    double root;
    for (int n=10;n<=100;n+=10){
        root = sqrt(double(n));
        cout << setw(6) << setfill('.') << n << setfill(' ')
             << setw(12) << setprecision(3) << root
             << setw(14) << setprecision(4) << sqrt(root)
             << endl;
    }
    return 0;
}
     N   square root   fourth root
....10       3.162        1.7783
....20       4.472        2.1147
....30       5.477        2.3403
....40       6.325        2.5149
....50       7.071        2.6591
....60       7.746        2.7832
....70       8.367        2.8925
....80       8.944        2.9907
....90       9.487        3.0801
...100      10.000        3.1623

總結

  • cout最重要的功能就是型別轉換,即把各種型別的數據全部轉換爲字元流,以放入輸出流去顯示。它的實現方法就是通過提供了一系列插入運算子的過載原型,每一個數據型別都有一個過載版本,比如cout << 1.25就會呼叫ostream & operator<<(double)原型,而這個函數的功能就是把double浮點數轉換爲文字,在這裏就是轉換爲四個字元。
  • C++提供了很多控制符,比如hex,oct, dec, left, fixed,非常好用。
  • 只有width()一個函數需要不斷設定,其他方法都是設定一次一直有效。
  • iomanip的控制符好好用,控制格式真的很棒