在C語言裡,我們可以通過函式printf和scanf來進行格式化控制。而在C++中仍然包含了前者,但還提供了以下兩種格式控制的方法:(1)使用流成員函式進行格式控制;(2)使用預定義操作符進行格式控制。下面我來一一介紹:
1.流成員函式主要是指ios類(流基類)中的,分別有:
(1).設定狀態標誌流成員函式setf
一般格式:long ios::setf(long flags),呼叫格式:流物件.setf(ios::狀態標誌)
ios類的狀態標誌有:
因為狀態標誌在ios類中定義為列舉值,所以在引用這些值前要加上ios::,如果有多項標誌,中間則用”|”分隔;
(2).清除狀態標誌流成員函式unsetf
一般格式:long ios::unsetf(long flags),呼叫格式:流物件.unsetf(ios::狀態標誌);
(3).設定域寬流成員函式width
一般格式:int ios::width(int n),呼叫格式:流物件.width(n);//注:它只對下一個流輸出有效,輸出完成後,恢復預設值0
(4).設定實數的精度流成員函式precision
一般格式:int ios::precision(int n),呼叫格式:流物件.precision(n);//注:引數n在十進位制小數形式輸出時代表有效數字。在以fixed形式和scientific形式輸出時代表小數位數
(5).填充字元流成員函式fill
一般格式:char ios::fill(char ch),呼叫格式:流物件.fill(ch);//注:當輸出值不滿寬域時用填充符來填充,預設填充符為空格,它與width函式搭配。
下面用示例來驗證:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include "stdafx.h" #include <iostream> #include <string> int main() { std::cout.setf(std::ios::left|std::ios::showpoint|std::ios::unitbuf); std::cout.precision(6); std::cout<<123.45678; std::cout.width(50); std::cout.fill('-'); std::cout.unsetf(std::ios::left);//清除狀態左對齊 std::cout.setf(std::ios::right); std::cout<<"十進位制小數輸出,有效數字為6位"<<std::endl; std::cout.setf(std::ios::left|std::ios::fixed); std::cout.precision(6); std::cout<<123.45678; std::cout.width(50); std::cout.fill('-'); std::cout.unsetf(std::ios::left|std::ios::fixed);//清除狀態左對齊和定點格式 std::cout.setf(std::ios::right); std::cout<<"固定小數位fixed,小數位為6位"<<std::endl; std::cout.setf(std::ios::left|std::ios::scientific); std::cout.precision(6); std::cout<<123.45678; std::cout.width(50); std::cout.fill('-'); std::cout.unsetf(std::ios::left|std::ios::scientific);//清除狀態左對齊和科學計數法格式 std::cout.setf(std::ios::right); std::cout<<"科學計數法表示,小數位為6位"<<std::endl; std::cout.fill('');//設定填充符為預設空格 std::cout.unsetf(std::ios::right);//清除狀態靠右對齊 std::cout.setf(std::ios::dec|std::ios::showpos|std::ios::internal);//設定狀態基數為10,正整數前顯示"+"和資料符號左對齊,資料本身右對齊,資料和符號之間為填充符' ' std::cout.width(6); std::cout<<128<<std::endl; std::cout.unsetf(std::ios::dec);//清除狀態基數為10 //在輸出整數的八進位制形式或十六進位制形式之前 //先要把預設的十進位制形式的標誌清除std::cout.unsetf(std::ios::dec) std::cout.setf(std::ios::oct|std::ios::showbase);//設定狀態基數為8,輸出整數時顯示基數符號 //std::ios::internal標誌對八進位制不起作用 std::cout<<128<<std::endl; std::cout.unsetf(std::ios::oct);//清除狀態基數為8 std::cout.setf(std::ios::hex|std::ios::uppercase);//設定狀態基數為16,輸出整數時顯示基數符號和科學計數法輸出時E大寫,十六進位制字母大寫 //std::ios::internal標誌對十六進位制不起作用 std::cout<<255<<std::endl; std::cout.unsetf(std::ios::hex);//清除狀態基數為16 return0; } |
結果:
2.用ios類中的成員函式來進行IO格式的控制總需要寫一條單獨的語句,而不能直接嵌入到IO語句中去,顯得很不方便。因此C++又提供了一種用操縱符來控制IO的格式。操縱符分為帶參和不帶參的兩種,帶參的定義在標頭檔案iomanip.h中,不帶參的定義在iostream.h中。下面分別是C++中的預定義操作符:
(1)dec:設定整數基數為10,用於輸出和輸入;
(2)hex:設定整數基數為16,用於輸出和輸入;
(3)oct:設定整數基數為8,用於輸出和輸入;
(4)ws:跳過輸入的空格符,用於輸入;
(5)endl:輸出一個換行符並重新整理輸出流,用於輸出;
(6)ends:插入一個空字元null,通常用來結束一個字串,用於輸出;
(7)flush:重新整理一個輸出流,用於輸出;
(8)setbase(n):設定整數的基數為n(可取0或10代表十進位制,8代表八進位制和16代表十六進位制,預設為0),用於輸入和輸出;
(9)setfill(c):設定填充符(預設為空格),用於輸出;
(10)setprecision(n):設定實數精度n,原理和成員函式precision一樣,用於輸出;
(11)setw(n):設定域寬n,用於輸出;
(12)setiosflags(flags):設定指定狀態標誌,多個用”|”分隔,用於輸出和輸入;
(13)resetiosflags(flags):清除指定狀態標誌,多個用”|”分隔,用於輸出和輸入;
操作符setiosflags(flags)和resetiosflags(flags)的部分狀態標誌:
下面用示例來驗證:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include "stdafx.h" #include <iostream> #include <iomanip>//帶形參的操縱符必須含有該標頭檔案 #include <string> int main() { std::string str="abcdefg"; std::cout<<str<<std::ends<<std::endl;//std::ends用來結束一個字串 std::cout<<std::setiosflags(std::ios::left|std::ios::showpoint|std::ios::unitbuf)<<std::setprecision(6) <<123.45678<<std::setw(50)<<std::setfill('-')<<std::resetiosflags(std::ios::left) <<std::setiosflags(std::ios::right)<<"科學計數法表示,小數位為6位"<<std::endl; std::cout<<std::setiosflags(std::ios::left|std::ios::fixed)<<std::setprecision(6) <<123.45678<<std::setw(50)<<std::setfill('-')<<std::resetiosflags(std::ios::left|std::ios::fixed) <<std::setiosflags(std::ios::right)<<"固定小數位fixed,小數位為6位"<<std::endl; std::cout<<std::setiosflags(std::ios::left|std::ios::scientific)<<std::setprecision(6) <<123.45678<<std::setw(50)<<std::setfill('-')<<std::resetiosflags(std::ios::left|std::ios::scientific) <<std::setiosflags(std::ios::right)<<"科學計數法表示,小數位為6位"<<std::endl; std::cout<<std::setfill('')<<std::resetiosflags(std::ios::right)<<std::flush;//std::flush重新整理一個輸出流 std::cout<<std::dec//或std::setbase(10或0) <<std::setiosflags(std::ios::showpos|std::ios::internal)<<std::setw(6)<<128<<std::endl; std::cout<<std::setbase(8)//或std::oct <<std::setiosflags(std::ios::showbase)<<128<<std::endl; std::cout<<std::setbase(16)//或std::hex <<std::setiosflags(std::ios::showbase|std::ios::uppercase)<<255<<std::endl; return0; } |
結果:
3.除了利用系統預定義的操縱符來進行IO格式的控制外,使用者還可以自定義操縱符來合併程式中頻繁使用的IO寫操作。定義形式如下:
輸出流自定義操縱符
ostream &操縱符名(ostream &s)
{
自定義程式碼
return s;
}
輸入流自定義操縱符
istream &操縱符名(istream &s{
自定義程式碼
return s;
}
返回流物件s很關鍵,否則操縱符就不能用在流的IO操作序列中。
用示例來驗證:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include "stdafx.h" #include <iostream> #include <iomanip> std::ostream& outputNo(std::ostream& s)//編號格式如:0000001 { s<<std::setw(7)<<std::setfill('0')<<std::setiosflags(std::ios::right); return s; } std::istream& To16(std::istream& s)//要求輸入的數為十六進位制數 { s>>std::hex; return s; } int main() { std::cout<<outputNo<<8<<std::endl; int a; std::cout<<"請輸入十六進位制的數:"; std::cin>>To16>>a; std::cout<<"轉化為十進位制數:"<<a<<std::endl; return0; } |
結果: