# printf函數基本概念
## printf函數介紹
- printf函數是一個標準庫函數,能夠以精確的格式輸出程序運算的結果。
+ `printf`函數的調用格式為:
+ `printf("格式控制字符串",輸出項列表);`
+ 例如:```printf("%d,%d",a, b);```
+ 格式字符串
* 是由格式字符(包括:轉換說明符、標志、域寬、精度)和普通字符組成,轉換說明符和百 分號(%)一起使用,用來說明輸出數據的數據類型、標志、長度和精度
+ 輸出項列表
* 可以是常量、變量和表達式,也可以沒有輸出項,這些輸出項必須與格式控制字符串在類型 和數量上完全對應,否則,結果將不可預測。當有多個輸出項時,各個輸出項之間用逗號 ‘,’分隔
## 格式控制符使用說明
- `printf`的格式控制的完整格式:
+ "% - 0 m.n l或h 格式字符"
- 下面對組成格式說明的各項加以說明:
+ %:表示格式說明的起始符號,不可缺少。
+ -:有-表示左對齊輸出(右側補空格),如省略表示右對齊輸出(左側補空格)。
+ **0:有0表示指定空位填0,如省略表示指定空位不填。**
+ m.n:m指域寬,即對應的輸出項在輸出設備上所占的字符數。N指精度。用于說明輸出的實型 數的小數位數。對數值型的來說,未指定n時,隱含的精度為n=6位。
+ l或h:l對整型指long型,對實型指double型。h用于將整型的格式字符修正為short型。
+ 格式字符(格式字符用以指定輸出項的數據類型和輸出格式)
* d格式:用來輸出十進制整數。有以下幾種用法:
* ```%d %hd %ld```
* o格式:以無符號八進制形式輸出整數
* x格式:以無符號十六進制形式輸出整數
* u格式:以無符號十進制形式輸出整數
* c格式:輸出一個字符
* s格式:用來輸出一個串。有幾中用法
```
%s:例如:printf("%s","CHINA")輸出"CHINA"字符串(不包括雙引號)。
%ms:輸出的字符串占m列,如字符串本身長度大于m,則突破獲m的限制,將字符串全部輸出。若串 長小于m,則左補空格。
%-ms:如果串長小于m,則在m列范圍內,字符串向左靠,右補空格。
%m.ns:輸出占m列,但只取字符串中左端n個字符。這n個字符輸出在m列的右側,左補空格,注 意:如果n未指定,默認為0。
%-m.ns:其中m、n含義同上,n個字符輸出在m列范圍的左側,右補空格。如果n>m,則自動取n 值,即保證n個字符正常輸出,注意:如果n未指定,默認為0。
如果是sprintf(desc, "%m.ns", sour); 如果desc空間夠的話,會在%m.ns 串 的結尾自動補null 字符,不同于strncpy。
例如 :sprintf(desc, "%.3s", "123456"); desc如果空間>=4字節的話,第4個字節將是null字符。
```
## 實型輸出問題
- %f:不指定寬度,整數部分全部輸出并輸出6位小數。
```
// 默認輸出6位小數
printf("%f", 3.1415926535f); // 輸出結果: 3.141593
```
- 指定保留多少位小數
```
// 通過%.nf方式,指定保留多少位小數
printf("%.2f", 3.1415926535f); // 輸出結果: 3.14
```
```
// 指定保留多少位小數時, 可以通過*號占位, 以后賦值具體保留的小數位
printf("%.*f", 4,3.1415926535f); // 輸出結果: 3.1416
```
- 指定輸出數值寬度(左端補空格)
```
// 通過%m方式, 指定輸出數值寬度(左端補空格)
printf("%9f", 3.1415926535f); // 輸出結果: $3.141593 注意'$'代表空格
```
## 實型精度問題
- 對于單精度數,使用%f格式符輸出時,僅前7位是有效數字,小數6位
- 對于雙精度數,使用%lf格式符輸出時,前15位是有效數字,小數6位
|進制|float|double|
|--|--|--|
|十進制有效位數|7位|15位|
|二進制有效位數|24位|53位|
- 有效數字的位數與指定輸出的小數位數(%.7f)是兩碼事。
+ “有效數位為7”:是指此數據從第一個非零數字開始,誤差不超過本數位半個單位的、精確可信 的數位是7位(包括小數點前的非零數位)。
+ %.7f:是指輸出此數據的時候,小數點之后要顯示7位數字(但是如果小數點前還有一些非零數 位,那么小數點后的這7位并不能保證都是精確可信的有效數位,)
- 一個血案
+ 要求輸出`3.1415926535f`所有小數
嘗試通過指定保留位數
```
printf("%.10f", 3.1415926535f); //輸出結果: 3.1415927410
```
> float有效數字是7位, 多余位數則會顯示垃圾數據(不準確)
什么是有效位?
```
printf("%.10f", 314159.26535f); // 輸出結果: 314159.2500000000
```
嘗試指定寬度
```
printf("%12f", 3.1415926535f); // 輸出結果: $$$$3.141593 注意$代表空格
```
嘗試指定寬度和保留位數
```
printf("%12.10f", 3.1415926535f); // 輸出結果: 3.1415927410
```
要想完整輸出必須使用double, 因為double類型精度小數點后6位,有效數字是15位
```
double doubleValue = 3.1415926535; // 注意后面沒有f
printf("%.10lf", doubleValue); // 輸出結果:3.1415926535
```
## printf函數注意事項
### 域寬問題
- %d:按整型數據的實際長度輸出。 如果想輸出指定寬度可以指定域寬
- %md-->m域寬,打印出來以后,在控制臺上,顯示m位
+ 如果我們要打印的數的位數如果超過我們設定 m 則原樣輸出
+ 如果我們要打印的數的位數如果小于我們設定的位數,則補空白,具體如下:
+ 如果m為正數,則左對齊(左側補空白)
+ **如果m為負數,則右對齊(右側補空白)**
```
// 如果m為負數,則右對齊(右側補空白)
printf("|%-5d|",88); // 輸出結果:|88 |
```
```
// 如果m為正數,則左對齊(左側補空白)
printf("|%5d|",88); // 輸出結果:| 88|
```
```
// %0md 表示,位數不足部分補“0”
printf("|%05d|",88);
輸出結果:|00088|
常用于日期, 圖片處理等
```
### 轉義字符問題
- 如果想輸出字符"%",則應該在“格式控制”字符串中用連續兩個%表示
```
printf("%f%%", 1.0/3);
輸出結果: 0.333333%。
```
```
\n 換行,相當于敲一下回車。
\t 跳到下一個tab位置,相當于按一下鍵盤上的tab鍵。 \b 退格,相當于按一下backspace。
\r 使光標回到本行開頭。
\f 換頁,光標移到到下頁開頭。
\\ 輸出\字符,也就是在屏幕上顯示一個\字符。
\' 輸出'字符,也就是在屏幕上顯示一個'字符。
\" 輸出"字符,也就是在屏幕上顯示一個"字符。
```