Chap13-輸出格式

Download Report

Transcript Chap13-輸出格式

Chap 13 輸出格式
孟子曰:「離婁之明,公輸子之巧,不以規矩,不能
成方員。師曠之聰,不以六律,不能正五音。」
《孟子﹒離婁篇》
在前幾章中,我們已經多次使用函數setw() 來設定輸
出欄位的寬度,讓輸出資料能夠上下對齊,更容易了解。本章
將詳細介紹其它設定輸出格式的語法。
1/42
Chap 13輸出格式





2/44
13.1
13.2
13.3
13.4
13.5
使用格式操縱子設定輸出格式
輸出格式設定間的交互作用
三種格式設定語法之比較
檔案儲存格式的設定
矩陣和向量間的操作
設定數值的輸出格式
38.7654139
38.7654
3.6854226
3.6854
378.255484
378.2555
很顯然的,右邊的編排方式比較容易
判讀和對照。
3/44
數值輸出格式的四個特性
1.
2.
3.
4.
4/44
靠左或靠右對齊
浮點數表示法 / 科學表示法
佔多少欄位 (亦即每筆資料佔有的寬度)
小數點以下的有效位數數目
使用格式操縱子 (manipulators) 來設
定數值的格式
cout << “The answer is: “ << setw( 5 ) << x ;
式中的setw(5)用來設定欄寬。x值就會被
放置在寬度為5個欄位的空間內,且靠右對
齊。
5/44
表13.1.1 常用的格式操縱子 (需要標頭檔
<iomanip>)
6/44
格式操縱子
效 果
setw(n)
將欄位寬度設定為 n。
setprecision(n)
將浮點精度設為 n 位數。
不管是一般表示法或科學表示法,實數的小數點後的位數,以四捨五
入處理,如果數字不夠,則以 0 補足。對於整數則沒有作用。如果沒
指定精度,則預設值相當於setprecision(6)。
fixed
使用一般的浮點數表示法。
scientific
使用科學表示法。
showpoint
此指令對於整數沒有作用。對於浮點數而言,則預設6個有效位數,且
一定會顯示小數點(例如 1.0將顯示為1.0而不是1):
1. 如果沒有設定ios::fixed
如果整數部份大於6位數,則以科學表示法表示,否則使用一般浮點數
表示。例如2645132.8將表為2.64513e+06。
2. 如果有設定ios::fixed
不用科學表示法表示。
showpos
如果為正數,整數之前加上+ 號。
left
在欄位內靠左對齊。
right
在欄位內靠右對齊。
dec
以十進位法表示。
oct
以8進位法表示。
hex
以16進位法表示。
格式操縱子的保持性
除非再次更動,否則以本程式內最近的設
定為準。
有一個例外: 欄寬的設定setw() 必須在
每個送至cout的數值之前使用才有效。
7/44
旗標 (flags)
格式操縱子 fixed 也可以寫成
setiosflags (ios::fixed)
這裹ios::fixed這類表示式稱為旗標(flags) 。
運算子「::」稱為範圍運算子 (the scope operator),
或範圍確認運算子 (the scope resolution operator)。
使用這個語法時,using宣告必需寫成
using std::setiosflags;
using std::ios;
而不是
using std::fixed;
8/44
格式操縱子的實例
表13.1.2
輸 出
Manipulator
cout << setw(2) << 3
<< endl ; | 3|
cout << setw(5) << 158
<< endl ; |
cout << setw(5) << 69.72
<< endl ; |69.72|
cout << setw(5) << left
<< endl ;
<< 876
cout << setw(6) << fixed <<
setprecision(2)
<< 133.456 << endl ;
9/44
158|
|876
|
|133.46|
setw( ) 的設定規則
欄寬包括整數部份的位數加上小數點,以
及小數點之後由 setprecision 所設定的有效
位數。
當所加總的數量大於欄寬時,setw( ) 的設
定將不執行。
10/44
程式Format_1.cpp



11/44
產生表13.1.2。
為了清楚顯示資料所佔用的欄位,在資料前後
都加了字元 '|' 做為標誌。
setw( ) 不能置於 '|' 之前,否則沒有作用。
範例程式 檔案 Format_1.cpp
// Format_1.cpp
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << '|' << setw(2) << 3
cout << '|' << setw(5) << 158
cout << '|' << setw(5) << 69.72
cout << setiosflags(ios::left)
<< '|' << setw(5) << 876
cout << setiosflags(ios::fixed)
<< setprecision(2)
<< '|' << setw(6) << 133.456
return 0;
12/44 }
<< '|' << endl ;
<< '|' << endl ;
<< '|' << endl ;
<< '|‘ << endl ;
<< '|' << endl ;
操作結果
| 3|
| 158|
|69.72|
|876 |
|133.46|
13/44
程式整齊的顯示欄寬為13,且小數點之後
有效位數為2的值
cout <<
<<
<<
<<
14/44
setw (13)
fixed
showpoint
setprecision ( 2 ) << x <<
endl ;
範例程式Format_2.cpp
進一步示範了上述的格式設定指令,這些
指令有別於Format_1.cpp。
前置處理指令之後的 using指令需要逐一
列舉格式操縱子,比較麻煩,但主程式內
的指令較簡單。
15/44
範例程式 檔案 Format_2.cpp
// Format_2.cpp
#include <iostream>
#include <iomanip>
using namespace std;
// --- 主程式 ------------------------------int main()
{
cout
<< hex << '|' << 14 << '|' << endl;
cout
<< scientific
<< setprecision(2) << '|' << setw(5)
<< 46218.542 << '|' << endl;
cout
<< setprecision (4)
<< fixed
<< showpoint << '|' << setw(13)
<< 64.7766 << '|'
<< endl ;
16/44 }
操作結果
|e|
|4.62e+04|
|
64.7766|
17/44
13.2 輸出格式設定間的交互作用
表13.2
setprecision(2)
旗標
t1
(不指定)
t1
t2
253
1.23457e-01
2.5e+02
1.25e-0
2.5e+02
1.23e-01 253.00
1.23457e-01
showpoint
fixed
253.00
0.13
0.13346
showpoint
scientific
2.53e+02
1.23e-01 2.53000e+02
showopint
18/44
t2
setprecision(5)
253.00000
1.23457e-01
輸出格式設定的規則
19/44
1.
如果不指定showpoint,且原來的數值為整數,則以
整數顯示。
2.
如果指定 showpoint,但不指定 fixed 或 scientific,
則setprecision 所代表的意義不同。如果precision足夠,
則使用fixed,否則使用scientific notation。
在以fixed的方式顯示的情況下,有效位數為小數點
前後位數的和。如果以scientific的方式顯示,則指數
為負值時有效位數只表示小數點之後的位數,指數
為正值時則為小數點前後位數的和。
3.
如果同時指定了fixed或scientific,則setprecision表示
的有效位數為小數點之後的位數。
範例程式 檔案 Format_3_Short.cpp (獲
得表13.2)
// Format_3_Short.cpp
#include <iostream>
#include <iomanip>
using namespace std;
// --- 主程式 -------------------------------int main()
{
double t1=253.0;
double t2=0.123456789;
cout
cout
20/44
<< " (1)The value of t1 is : "
<< std::setprecision(2) << t1 << endl;
<< " (2)The value of t1 is : "
<< std::setprecision(3)
<< std::showpoint << t1 << endl;
cout
<< " (3)The value of t1 is : "
<< std::setprecision(5) << std::showpoint
<< std::fixed << t1 << endl;
cout
<< " (4)The value of t1 is : "
<< std::setprecision(5) << std::showpoint
<< std::scientific << t1 << endl;
return 0;
}
21/44
操作結果
(1) The value of t1 is :
(2) The value of t1 is :
(3) The value of t1 is :
(4) The value of t1 is :
22/44
2.5e+02
253.
253.00000
2.53000e+02
三種格式設定語法之比較 (以下三組敘述
的效果完全相同) (3-1)
(1) 在Format_1.cpp中的語法
cout << setiosflags
(ios::fixed||ios::showpoint)
<< setprecision (2) << t1 << endl;
cout << setiosflags (ios::hex) << 26;
23/44
前置處理指令之後的 using指令
(1) 要配合:
#include <iomanip>
using std::cout;
using std::endl;
using std::setiosflags;
using std::ios;
using std::setprecision;
24/44
三種格式設定語法之比較 (3-2)
(2) 在Format_2.cpp中的語法
cout << fixed << showpoint
<< setprecision (2) << t1 <<endl;
cout << hex << 26;
25/44
前置處理指令之後的 using指令
(2) 要配合:
#include <iomanip>
using std::cout;
using std::endl;
using std::fixed;
using std::showpoint;
using std::setprecision;
using std::hex;
26/44
三種格式設定語法之比較 (3-3)
(2) 在Format_3.cpp中的語法
cout << std::fixed << std::showpoint
<< std::setprecision (2) << t1 << endl;
cout << std::hex << 26;
27/44
前置處理指令之後的 using指令
(3) 要配合 (最簡短):
#include <iomanip>
using std::cout;
using std::endl;
28/44
如果不考慮名稱可能衝突的問題
上述三種寫法的前置處理指令之後的using指
令都可以簡單地寫成:
#include <iomanip>
using namespace std;
這個時候,顯然第二種寫法 (在Format_2.cpp
中的語法) 最簡潔。
29/44
13.4 檔案儲存格式的設定
30/44
使用資料流 (file stream)的概念,所有的輸出
格式設定語法可以直接套用於檔案的儲存格
式。
在以下的範例程式SaveMatrix.cpp中將以矩陣
(matrix) 的儲存為例。將矩陣的儲存封裝成函數
RecMatrix()。
為了避免矩陣的行數太多,同一列數字無法一
次呈現完畢,以致在顯示時折到下一行影響閱
讀,我們在每一列的前面都加上該列的編號以
玆區別。
範例程式 檔案 SaveMatrix.cpp
// SaveMatrix.cpp
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
const int M = 4;
const int N = 5;
// --- 函數 RecMatrix() 的宣告 --------------------void RecMatrix (char *, double [][N], int, int);
// --- 主程式 -------------------------------------int main ()
{
double Matrix[M][N];
31/44
char *FileName
= "Record.txt";
for (int i = 0; i < M; i++)
for(int j = 0; j < N ; j++)
Matrix[i][j]= (i+j*j+0.5)/(i+j+2);
char Ch;
cout << "你要將矩陣存在 " << FileName
<< " 中嗎? (Y/N)"
<< endl;
cin >> Ch;
if (Ch == 'Y' || Ch == 'y')
RecMatrix (FileName, Matrix, M, N);
else
cout << "沒有存檔." << endl;
return 0;
32/44 }
// --- 函數 RecMatrix() 的定義 ---------------------void RecMatrix (char *FileNameOut,
double A[][N], int M, int N)
{
ofstream FileOutput;
FileOutput.open( FileNameOut, ios::out);
if (!FileOutput)
{cout << "檔案: "
<< FileNameOut
<< " 存檔失敗!" << endl; exit(1);}
FileOutput << setprecision(4) << right
<< showpoint
<< fixed;
33/44
for (int i = 0; i < M; i++)
{
FileOutput << "第 " << i+1 << " 列:";
for(int j = 0; j < N ; j++)
FileOutput << setw(8) << A[i][j] << " " ;
FileOutput
<< endl;
}
FileOutput.close();
cout << "成功存於檔案 "
<< FileNameOut << " 內." << endl;
}
34/44
操作結果 (執行SaveMatrix.exe在顯示器
上會看到下列訊息)
你要將矩陣存在 Record.txt 中嗎? (Y/N)
y
成功存於檔案Record.txt內。
檔案Record.txt的內容是:
第 1 列: 0.2500 0.5000 1.1250 1.9000
第 2 列: 0.5000 0.6250 1.1000 1.7500
第 3 列: 0.6250 0.7000 1.0833 1.6429
第 4 列: 0.7000 0.7500 1.0714 1.5625
35/44
2.7500
2.5000
2.3125
2.1667
13.5 矩陣和向量間的操作
顯示矩陣和向量。
取出矩陣的某一列或某一行並將它存成向
量。
將向量存到矩陣的某一列或某一行。
36/44
範例程式 MatrixRow.cpp
函數ShowMatrix() 和ShowVector() 分別用來
顯示矩陣和向量。
函數PickRow() 用來取出矩陣中選定的一整
列,並將它存成向量。
函數SetCol() 用來將向量存到矩陣中選定的某
一列。
37/44
範例程式 檔案 MatrixRow.cpp
// MatrixRow.cpp
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
// --- 函數的宣告 -----------------------------------void ShowMatrix (double A[][N]);
void ShowVector (double A[]);
void PickRow(double A[][N], double B[], int S);
void SetCol(double A[][N], double B[], int S);
// --- 主程式 --------------------------------------int main ()
{
const int M = 4;
38/44
39/44
const int N = 5;
double M2D[M][N];
double PickV [N];
double Data[] = { 1.3, 4.5, 8.32, 45.9, 0.4};
int PRow = 1; int SRow = 2;
for (int i = 0; i < M; i++)
for(int j = 0; j < N ; j++)
M2D[i][j]= (i+j*j+0.5)/(i+j+2);
cout << "原來的矩陣是 :\n";
ShowMatrix (M2D);
cout << "原來的向量 Data 是 :\n";
ShowVector (Data);
cout << "將矩陣的第 " << PRow+1
<< " 列取出成向量 PickV:\n";
PickRow(M2D, PickV, PRow);
ShowVector (PickV);
cout
<< "將矩陣的第 " << SRow+1
<< " 列以向量 Data 取代後,\n矩陣成為:\n";
SetCol(M2D, Data, SRow);
ShowMatrix (M2D);
return 0;
}
40/44
41/44
// --- 函數 ShowMatrix() 的定義 ---------------------void ShowMatrix (double A[][N])
{
cout << setprecision(4) << right << showpoint <<
fixed;
for (int i = 0; i < M; i++)
{
cout << "第 "
<< i+1 << " 列:";
for(int j = 0; j < N ; j++)
cout << setw(8) << A[i][j] << " " ;
cout << endl;
}
cout << endl;
}
// --- 函數 ShowVector () 的定義 --------------------void ShowVector (double A[])
{
cout << setprecision(4) << right
<< showpoint << fixed;
cout << "向量 : ";
for(int j = 0; j < N ; j++)
cout << setw(8) << A[j] << " " ;
cout << endl;
cout << endl;
}
42/44
// --- 函數 PickRow() 的定義 ------------------------void PickRow(double A[][N], double B[], int S)
{
for (int i=0; i < N; i++)
B[i]= A[S][i];
return ;
}
// --- 函數 SetCol() 的定義 -------------------------void SetCol(double A[][N], double B[], int S)
{
for(int j = 0; j < N ; j++)
A[S][j]= B[j];
return;
43/44
}
操作結果
44/44
原來的矩陣是:
第 1 列: 0.2500 0.5000 1.1250 1.9000 2.7500
第 2 列: 0.5000 0.6250 1.1000 1.7500 2.5000
第 3 列: 0.6250 0.7000 1.0833 1.6429 2.3125
第 4 列: 0.7000 0.7500 1.0714 1.5625 2.1667
原來的向量 Data 是:
向量 : 1.3000 4.5000 8.3200 45.9000 0.4000
將矩陣的第 2 列取出成向量 PickV:
向量 : 0.5000 0.6250 1.1000 1.7500 2.5000
將矩陣的第 3 列以向量 Data 取代後,
矩陣成為:
第 1 列: 0.2500 0.5000 1.1250 1.9000 2.7500
第 2 列: 0.5000 0.6250 1.1000 1.7500 2.5000
第 3 列: 1.3000 4.5000 8.3200 45.9000 0.4000
第 4 列: 0.7000 0.7500 1.0714 1.5625 2.1667