C++格式化輸入輸出

C++共有15個 輸入輸出 格式標記位,這15個標記位均爲bit位,每個標記位都有自己的含義,且可以單獨設置。

格式標記位的取值爲0或1:0表示關閉(不使用此格式),1表示開啓(使用此格式)。

15個標記位的含義可參考下面三張表:

標記位
含義
boolalpha    如開啓,則輸入和輸出使用bool值(即Ture或False)
showbase     如開啓,則對於輸出,使用C++ 基數前綴(0,0x)
showpoint    如開啓,則顯示末尾的小數點
uppercase    如開啓,則對於16進制,使用大寫字母;對於10進制,使用E表示法
showpos      如開啓,則在正數前面加上+

標記位
含義
dec        如開啓,則使用基數10(進行輸出)
oct        如開啓,則使用基數8
hex        如開啓,則使用基數16
fixed      如開啓,則使用定點計數法
scientific 如開啓,則使用科學計數法
left       如開啓,則使用左對齊
right      如開啓,則使用右對齊
internal   如開啓,則符號或基數前綴左對齊,值右對齊

標記位
含義
skipws     如開啓,則跳過輸入流中的空白字符
unitbuf    如開啓,則每次輸出操作後都會清空緩衝區




先來看一個簡單的程序:

#include <iostream>
using namespace std;

int main()
{
int x;
x = cout.setf(ios::showpos);
cout << x << endl;

x = cout.setf(ios::uppercase);
cout << x << endl;

system("pause");
return 0;
}
輸出結果是:

setf()函數用於設置格式標記,函數接受一個設格式常量作爲參數,在設置成功之後函數會返回一個值,該值指出了所有15個標記的上一次設置情況。

但將這個返回值進行輸出,並不是每一個標記位的bit值,而是一個整數,爲什麼?

實際上,這15個bit值視爲一個整體,從而組成一個二進制數,並能夠轉化爲十進制數。

這15個標記位的排列順序是:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha

比如,setf()函數第一次的返回值是4098,這個值實際上是輸出格式的初始狀態,轉化二進制爲001000000000010,那麼格式狀態爲:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha
0 0 1 0 0 0 0 0 0 0 0 0 0 1 0

而6146轉化爲二進制001100000000010,這一次的值反映的是開啓了showpos位後的格式狀態:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha
0 0 1 1 0 0 0 0 0 0 0 0 0 1 0

兩次對比,我們可以看出,的確是在初始狀態的基礎上開啓了showpos位。

接着我們來看看格式常量,格式常量一共有18個,其中15個用於打開相應的格式標記爲,另外3個做爲指示功能用

#include <iostream>

using namespace std;

int main()
{
cout << "boolalpha " << ios::boolalpha <<endl;
cout << "dec " << ios::dec << endl;
cout << "fixed " << ios::fixed << endl;
cout << "hex " <<ios::hex << endl;
cout << "internal " << ios::internal << endl;
cout << "left " << ios::left << endl;
cout << "oct " << ios::oct << endl;
cout << "right " << ios::right << endl;
cout << "scientific " << ios::scientific << endl;
cout << "showbase " << ios::showbase <<endl;
cout << "showpoint " << ios::showpoint <<endl;
cout << "showpos " << ios::showpos <<endl;
cout << "skipws " << ios::skipws << endl;
cout << "unitbuf " << ios::unitbuf << endl;
cout << "uppercase " << ios::uppercase <<endl;

cout << endl;
cout << "basefield " << ios::basefield << endl;
cout << "adjustfield " << ios::adjustfield << endl;
cout << "floatfield " << ios::floatfield << endl;

system("pause");
return 0;
}

格式常量
十進制值
意義
ios::boolalpha
1 開啓boolalpha標記位,輸入和輸出使用bool值(即Ture或False)
ios::showbase
512 開啓showbase標記位,對於輸出,使用C++ 基數前綴(0,0x)
ios::showpoint
1024 開啓showpoint標記位,顯示末尾的小數點
ios::uppercase
16384 開啓uppercase標記位,對於16進制,使用大寫字母;對於10進制,使用E表示法
ios::showpos
2048 開啓showpos標記位,在正數前面加上+

格式常量
十進制值
意義
格式常量
十進制值
意義
ios::basefield
74 指示相關標記位:dec、oct、hex ios::dec
2 開啓dec標記位,使用基數10
ios::oct
64 開啓oct標記位,使用基數8
ios::hex
8 開啓hex標記位,使用基數16
ios::floatfield
260 指示相關標記位:fixed、scientific ios::fixed
4 開啓fixed標記位,使用定點計數法
ios::scientific
256 開啓scientific標記位,使用科學計數法
ios::adjustfield
176 指示相關標記位:left、right、internal ios::left
32 開啓left標記位,使用左對齊
ios::right
128 開啓right標記位,使用右對齊
ios::internal
16 開啓internal標記位,符號或基數前綴左對齊,值右對齊



注意:這些都是常量,是作爲 函數參數 來設置格式狀態,而不是格式標記位的存儲空間。

15個藍色的格式常量用來打開對應的格式標記位,如果將其十進制值轉化爲二進制,再於標記位順序表比對,就可以看出來。

3個綠色的格式常量用來指示標記位,爲什麼要指示?比如:dec、oct、hex是不可能同時打開的,而ios::basefield則指示這三個標記位爲一組,74=2+64+8,這意味着它轉化爲二進制的比對情況是dec、oct、hex爲1,但它不是設置標記位,而是指示,具體原理在setf()函數中詳細解釋。

最後來看看setf()函數:

setf()函數有兩種原型,一種是fmtflags setf ( fmtflags );

它接收一個參數,該參數是一種 標記類型,提供實參時,可以是整數,該整數轉化爲二進制後賦給格式狀態。但這種方法抽象且不安全。

也可以將格式常量作爲實參提供給函數,在這種情況下,setf()函數會打開相應的標記位,且不會影響其它標記位。但這種方法仍不安全。很明顯,既打開dec標記位,又打開oct標記位是沒有意義的。

另一種原型是fmtflags setf ( fmtflags , fmtflags );

它接收兩個 標記類型 的參數。第一個參數指出要打開的標記位,第二個參數則是指示要清除的一批相關位。

比如:cout.setf( ios::hex, ios::basefield ); 這表示使用16進制輸出格式。首先,ios::basefield指示出了要清除的標記位,setf()函數將ios::basefield所指示的標記位,即dec、oct、hex全部清零。然後ios::hex使得setf()函數打開hex標記位。這是一種安全的方法,避免了同時打開dec、hex兩個標記位等沒有實際意義的情況發生。

setf()是如何實現清除的?

ios::basefield轉化爲二進制000000001001010,這三個1的位置指示的是dec、oct、hex標記位。setf()函數將這個二進制數取反111111110110101,然後與原格式狀態標記位進行“與”操作,使得原格式狀態的dec、oct、hex標記位爲0,而其它標記位不變。(參看《C++ primer plus》683頁位操作)

然後setf()函數根據第一個參數ios::hex將格式狀態的hex標記位打開,其它標記位不變。至此,格式設置就成功完成了。我們也可以看出,setf()函數不會影響無關標記位的狀態。

轉載地址:http://blog.csdn.net/angelcm51/article/details/2330496
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章