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()函式不會影響無關標記位的狀態。
相關文章
- 格式化輸入和輸出
- 【C++】輸入輸出C++
- c++入門:輸入輸出流C++
- C++中的檔案輸入/輸出(3):掌握輸入/輸出流 (轉)C++
- [C++]輸入/輸出流類庫C++
- C/C++程式語言中的基礎知識(一)--格式化輸入輸出C++
- 格式化輸出
- 【C++】標準檔案的輸入輸出!!!C++
- 第四章 字串和格式化輸入/輸出字串
- 輸入輸出
- C++中的檔案輸入/輸出(4):檢測輸入/輸出的狀態標誌 (轉)C++
- 入門計劃->使用(C++庫)ostringstream輸出(格式化) (轉)C++
- C++ 學習筆記之——輸入和輸出C++筆記
- C++輸入輸出常用格式(cin,cout,stringstream)C++
- 輸入輸出流
- C++名稱空間、標準輸入輸出、引用C++
- C++ 資料輸入cin (解決CLoin輸入中文程式出錯)C++
- pythonformat格式化輸出PythonORM
- 字串拼接格式化輸出字串
- Python格式化輸出Python
- java日期格式化輸出Java
- SQL*PLUS 格式化輸出SQL
- Java 輸入輸出流Java
- 輸入輸出系統
- JAVA輸入輸出流Java
- [vue] 表單輸入格式化,中文輸入法異常Vue
- 入門計劃->使用(C++庫)istringstream輸入(格式化) (轉)C++
- linux中的輸入與輸出管理(重定向輸入,輸出,管道符)Linux
- C++筆記:輸入輸出、變數、變數加減乘除C++筆記變數
- C++ 中輸入輸出流及檔案流操作筆記C++筆記
- 資料的輸入輸出
- Java —— 標準輸入輸出Java
- 排序,檔案輸入輸出排序
- 03 資料輸入-輸出
- Python 輸入和輸出Python
- Python的輸入輸出Python
- 檔案操作-輸入輸出
- C語言輸入輸出C語言