1. 程式人生 > 實用技巧 >C++面向物件(四十四)格式化輸入輸出

C++面向物件(四十四)格式化輸入輸出

#include <iostream>
#include <iomanip>
using namespace std;

/*
格式化輸入輸出: 在實際工作中, 需要按特定格式進行輸入輸出. 
C++的I/O流類庫提供了兩種控制格式輸入輸出的方法:
1 使用ios類的成員函式進行格式控制: 
(1) 使用ios類成員函式設定標誌字: ios類中聲明瞭一個數據成員, 用於記錄當前流的格式化狀態, 這個資料成員被稱為標誌字.
標誌字的每一位用於記錄一種格式. 為了便於記憶, 為每一種格式定義了對應的列舉量. 在程式中可以使用標準常量或直接用對應的十六進位制
值設定輸入輸出流的格式. ios類有幾個成員函式可以設定格式標誌字, 域寬, 填充字元以及輸出精度來控制輸入輸出的格式,

格式控制常量及含義:

ios有幾個直接操作標誌字的公有成員函式:
long flags(): 該函式用來返回標誌字
long flags(long): 該函式使用引數值來更新標誌字, 並返回更新前的標誌字
long setf(long setbits, long field): 該函式用來將field所指定的標誌位清零, 將setbits為1的標誌位置為1, 並返回設定前的標誌字
long setf(long): 該函式用來設定引數所指定的標誌位, 並返回更新前的標誌字
void unsetf(long): 該函式用來清除引數所指定的標誌位

流格式標誌字每一位表示一種格式, 格式位直接會有依賴關係:
dec, oct和hex在同一時刻只能有一個位被設定, 所以設定一個位之前應該清除其他有排斥的位, 為了便於清除同類排斥位, ios定義了幾個
用於作為setf(long setbits, long field)的第二個引數field的公有靜態符號常量:
static const long ios::basefield: dec| oct| hex
static const long ios::adjustfield: left| right| internal
static cosnt long ios::floatfield: scientific| fixed

(2) 使用ios類成員函式設定域寬, 填充字元及輸出精度: 在ios類還定義了設定域寬, 填充字元和輸出精度的成員函式:
<1> 設定輸出資料所佔寬度的函式:
int width(): 該函式用來返回當前輸出的資料寬度
int width(int): 該函式用來設定輸出的資料寬度, 並返回更新前的寬度值
注意事項: 
<1>.1 預設值為輸出該資料所需的最小字元數
<1>.2 如果設定的域寬小於資料所需的最小字元數, 採用預設寬度
<1>.3 只對一個數據的輸出有效, 需要不斷設定

<2> 設定當前寬度內的填充字元的函式:
char fill(): 該函式用來返回當前所使用的填充字元.
char fill(char): 該函式用類設定當前填充字元為引數所表示的字元, 並返回更新前的值
注意事項:
<2>.1 預設填充字元為空格

<3> 設定浮點數輸出精度函式:
int precision(): 該函式用來返回當前浮點數的有效數字的個數
int precision(int): 該函式用來設定當前浮點數輸出時的有效數字個數為該函式的引數值, 並返回更新前的值
注意事項:
<3>.1 單精度浮點數(float)有效數字個數最多為7個, 雙精度浮點數(double)有效數字個數最多為15個, 長雙精度浮點數(long double)
有效數字個數最多為19個

2 使用控制符(操作子)控制進行格式控制
C++的I/O流類庫提供了一種使用控制符進行格式輸出的方法, 這種方法比前面的方法操作起來簡單.控制符域成員函式呼叫的效果
一致, 但是可以直接插入, 不必單獨呼叫, 還可以直接被插入符和提取符操作, 但是控制符沒有實現的功能還需要通過呼叫成員函式
實現, 其本質是特殊的函式, 其中不帶形式引數的函式在標頭檔案iostream.h中定義, 帶形式引數的函式則定義在iosmanip.h中

I/O流類庫定義的控制符

*/ void test1(); void test2(); void test3(); void test4(); void test5(); void test6(); int main() { //test1(); //test2(); //test3(); //test4(); //test5(); system("pause"); } /* ios使用控制符控制輸入輸出格式 */ void test6() { cout << "oct form of 15 is " << oct << 15
<< endl; cout << dec << 10 << endl; cout << setbase(16) << "hex form of 32 is " << 31 << endl; cout << "hex form of 32 is " << setw(8) << setfill('*') << setiosflags(ios::left | ios::showpos) << 31 << endl; cout
<< setprecision(3) << setw(8) << 15.456f << endl; cout << setprecision(3) << setw(8) << resetiosflags(ios::left) << 15.445f << endl; } /* ios成員函式控制域寬, 填充字元和資料精度 */ void test5() { char a[] = "hello world"; cout << a << endl; cout.width(20); cout << a << endl; cout.fill('-'); cout.width(20); cout << a << endl; cout.setf(ios::left); cout.width(20); cout << a << endl; cout.fill(' '); cout.width(20); cout << a << endl; cout.setf(ios::internal, ios::adjustfield); cout.setf(ios::showpos); cout.width(20); cout.precision(6); cout.fill('_'); cout << 12.34 << endl; } /* ios成員函式清除排斥位, 並重新設定 */ void test4() { int a = 1024; cout.setf(ios::showbase); cout << "a = " << a << endl; long flags = cout.flags(); cout << "flags = " << flags << endl; flags = cout.setf(ios::oct, ios::basefield); cout << "a = " << a << endl; cout << "flags = " << flags << endl; flags = cout.setf(ios::hex, ios::basefield); cout << "a = " << a << endl; cout << "flags = " << flags << endl; } /* ios成員函式返回標誌字的值 */ void test3() { long flags = cout.setf(ios::left | ios::oct); cout << "flags = " << flags << endl; flags = cout.setf(ios::oct | ios::showbase); cout << "flags = " << flags << endl; flags = cout.setf(ios::showpoint | ios::fixed); cout << "flags = " << flags << endl; cout.unsetf(ios::showpoint | ios::fixed); flags = cout.flags(); cout << "flags = " << flags << endl; } ///ios成員函式setf(long| long|...)多個標誌常量在setf函式中做引數一起設定標誌字的值, 使用"|"分隔 void test2() { double a = 12.34; cout << "a = " << a << endl; //long flags = cout.setf(ios::showpos | 0x1000); long flags = cout.setf(0x1000 | ios::showpos); cout << "flags = " << flags << endl; cout << "a = " << a << endl; } //ios成員函式setf(long)分別設定標誌字的不同位 void test1() { double a = 12.34; cout << "a = " << a << endl; //設定標誌字, 使正數的輸出帶"+", 使用標誌常量ios::showpos(0x0400)設定顯示"+" //使用變數flags接收修改前的值 long flags = cout.setf(ios::showpos); //long flags = cout.setf(0x0400); cout << "flags = " << flags << endl; //設定標誌字, 使浮點數以科學計數法的形式輸出, 使用標誌常量ios::scientific(0x1000)設定浮點數顯示形式為科學計數法形式 flags = cout.setf(0x1000); flags = cout.setf(ios::scientific); cout << "flags = " << flags << endl; cout << "a = " << a << endl; }

格式化輸入輸出: 在實際工作中, 需要按特定格式進行輸入輸出.
C++的I/O流類庫提供了兩種控制格式輸入輸出的方法:
1 使用ios類的成員函式進行格式控制:
(1) 使用ios類成員函式設定標誌字: ios類中聲明瞭一個數據成員, 用於記錄當前流的格式化狀態, 這個資料成員被稱為標誌字.
標誌字的每一位用於記錄一種格式. 為了便於記憶, 為每一種格式定義了對應的列舉量. 在程式中可以使用標準常量或直接用對應的十六進位制
值設定輸入輸出流的格式. ios類有幾個成員函式可以設定格式標誌字, 域寬, 填充字元以及輸出精度來控制輸入輸出的格式, 格式控制常量及含義:

ios有幾個直接操作標誌字的公有成員函式:
long flags(): 該函式用來返回標誌字
long flags(long): 該函式使用引數值來更新標誌字, 並返回更新前的標誌字
long setf(long setbits, long field): 該函式用來將field所指定的標誌位清零, 將setbits為1的標誌位置為1, 並返回設定前的標誌字
long setf(long): 該函式用來設定引數所指定的標誌位, 並返回更新前的標誌字
void unsetf(long): 該函式用來清除引數所指定的標誌位 流格式標誌字每一位表示一種格式, 格式位直接會有依賴關係:
dec, oct和hex在同一時刻只能有一個位被設定, 所以設定一個位之前應該清除其他有排斥的位, 為了便於清除同類排斥位, ios定義了幾個
用於作為setf(long setbits, long field)的第二個引數field的公有靜態符號常量:
static const long ios::basefield: dec| oct| hex
static const long ios::adjustfield: left| right| internal
static cosnt long ios::floatfield: scientific| fixed (2) 使用ios類成員函式設定域寬, 填充字元及輸出精度: 在ios類還定義了設定域寬, 填充字元和輸出精度的成員函式:
<1> 設定輸出資料所佔寬度的函式:
int width(): 該函式用來返回當前輸出的資料寬度
int width(int): 該函式用來設定輸出的資料寬度, 並返回更新前的寬度值
注意事項:
<1>.1 預設值為輸出該資料所需的最小字元數
<1>.2 如果設定的域寬小於資料所需的最小字元數, 採用預設寬度
<1>.3 只對一個數據的輸出有效, 需要不斷設定 <2> 設定當前寬度內的填充字元的函式:
char fill(): 該函式用來返回當前所使用的填充字元.
char fill(char): 該函式用類設定當前填充字元為引數所表示的字元, 並返回更新前的值
注意事項:
<2>.1 預設填充字元為空格 <3> 設定浮點數輸出精度函式:
int precision(): 該函式用來返回當前浮點數的有效數字的個數
int precision(int): 該函式用來設定當前浮點數輸出時的有效數字個數為該函式的引數值, 並返回更新前的值
注意事項:
<3>.1 單精度浮點數(float)有效數字個數最多為7個, 雙精度浮點數(double)有效數字個數最多為15個, 長雙精度浮點數(long double)
有效數字個數最多為19個 2 使用控制符(操作子)控制進行格式控制
C++的I/O流類庫提供了一種使用控制符進行格式輸出的方法, 這種方法比前面的方法操作起來簡單.控制符域成員函式呼叫的效果
一致, 但是可以直接插入, 不必單獨呼叫, 還可以直接被插入符和提取符操作, 但是控制符沒有實現的功能還需要通過呼叫成員函式
實現, 其本質是特殊的函式, 其中不帶形式引數的函式在標頭檔案iostream.h中定義, 帶形式引數的函式則定義在iosmanip.h中 I/O流類庫定義的控制符

程式碼示例: