printf函數
1. printf函數使用公式
在前面幾節中,我們已經使用過很多次printf函數了。讓我們再來詳細討論一下它。首先,我們看一下,它的使用公式。
- printf是一個變參函數。(參數的數量和類型不確定)
- printf的第一個參數是字符串。
- printf的第一個參數是需要輸出的字符以及需要被替換的佔位符。
- printf的後續參數,是依次被替換的實際值。
- 佔位符的類型和數量需要與後續的參數類型和數量對應。
printf("數值1是:%d,數值2是:%d,字符串3是:%s", 123, 456, "Hello");
printf的第一個參數是字符串
第一個參數是需要輸出的字符以及需要被替換的佔位符
後續參數,是依次被替換的實際值
2. 佔位符
在我們在前面的章節中,使用%d用於整型的佔位,%s用於字符串的佔位,%c用於字符(請參見整型5)的佔位。接下來我們詳細討論一下,佔位符的細節。
佔位符以%百分號開始,依次具有下面這些元素:(以下是簡化版本,初學過程中,先學好常用的即可,避免掉入繁枝細節。完整的版本可以參考《C語言參考手冊》第十五章)
- 零個或多個標誌字符(-,+,0,#,或空格)。
- 一個可選的十進制整數常量表示的最小字段寬度。
- 一個可選的用點號表示的精度範圍,它的後面可以跟一個十進制整數。
- 一個可選的長度指示符,可以用下列字母組合之一來表示:ll,l,L。
- 由單個字符表示的轉換操作,取自下面這個集合:d,e,f,o,s,u,x,X。
下面將會使用實際演示的方法,讓大家理解這5個空格里填什麼會有什麼效果的。
注意:演示中,紅色字體僅僅是第一行代碼的解析。 後續代碼與第一行類似,不再贅述。
2.1 最小字段標誌
最小字段標誌表示打印出來的十進制整數的最小寬度。如果數值大小未達到最小寬度的要求,那麼將會以空格填充。
示例:最小寬度5、6、7位
2.2 標誌
標誌 0 使用0而不是空格作爲填充字符
示例:最小寬度5位,且使用0標誌,使用0填充小於最小寬度的部分。
標誌 - 值在字段寬度左對齊
示例:最小寬度5位,且使用0標誌,使用0填充小於最小寬度的部分且左對齊。
標誌 + 總是產生符號,+(整數)或-(負數)
示例:最小寬度5位,且使用0標誌,使用0填充小於最小寬度的部分。標誌+,始終產生符號。
標誌 空格 總是產生符號-(爲負數時)或空格(爲正數時)
示例:最小寬度5位,且使用0標誌,使用0填充小於最小寬度的部分。標誌 空格 ,始終產生符號,正數爲空格,負數爲-。
標誌 # 後續介紹
2.3 精度
精度控制小數點後的位數。
2.4 轉換操作
在前面小節中,我們用的%d來打印整型,用%s來打印字符串。在這一章中,我們認識到了,d和s,是選擇了不同的轉換操作。d代表將參數使用整型的方式進行轉換,而s則是字符串。
事實上,僅僅用d來進行整型的轉換操作,還是不完整的。我們來認識一下更多的轉換操作。
轉換操作 | 類型 | 備註 |
---|---|---|
d | int | 有符號整型十進制打印 |
u | unsigned int (可以使用int,但是符號位看做數據位) | 無符號整型十進制打印 |
o | unsigned int (可以使用int,但是符號位看做數據位) | 無符號整型八進制打印 |
x | unsigned int (可以使用int,但是符號位看做數據位) | 無符號整型十六進制打印 |
X | unsigned int (可以使用int,但是符號位看做數據位) | 無符號整型十六進制打印(大寫字母) |
f | double | 浮點數打印 |
e | double | 浮點數科學計數法打印 |
s | char * | 字符串打印 |
c | char * | 字符打印 |
接下來,我們再看看o和x、X的用法。
o將參數使用八進制打印。
x將參數使用十六進制打印。
X將參數使用十六進制打印(大寫)。
還記不記得,前面有一個 標誌 # 還沒有介紹呢?對的,這個#標誌加上之後,可以使八進制前加0,十六進制前加0x。
在上面的表格中,我們好像僅僅講了int和unsigned int。但是,short,unsigned short,float怎麼辦呢?有屬於它們的轉換操作嗎?
事實上,short、unsigned short和float在作爲參數,傳入printf的時候。會被自動轉換成爲int,float會被轉換爲double。所以,我們不需要額外去找它們的轉換操作了。使用上面表中的轉換操作即可滿足要求。
TIPS:
上面的這種轉換關係來自於默認函數實參轉換。對於變參函數的可變部分的實參,會在參數傳入時進行轉換。長度小於int的整型數據,在經過轉換後,都會成爲int。長度大於或等於int的整型數據,類型不變。具體參見《C語言參考手冊》6.3.5。
2.5 長度指定符
既然比int小的類型都能轉換成int,float能轉換成double。這是從小到大的轉換。那long,和long long,long double呢。它們總不能從大轉小了吧,從大轉小,就會意味着數據丟失。對的,它們不會被自動轉換。那之前的轉換操作對它們適用嗎?我們知道d是用於轉換int的,int假設有4個字節,那對於long,long long這種,大於4個字節的,肯定是不適用的。所以我們需要在轉換操作前加長度指示符。
長度指示符 | 類型 |
---|---|
l | long |
ll | long long |
L | long double |
2.6 示例
最後,我們用幾個示例,讓大家繼續熟悉一下,佔位符的寫法。