printf ()- 列印格式化字元

格式

#include <stdio.h>
int printf(const char *format-string, argument-list);

語言層次

ANSI

安全執行緒

區分語言環境

此函數的行為可能受到現行語言環境的 LC_CTYPE 及 LC_NUMERIC 種類的影響。 如果在編譯指令上指定 LOCALETYPE (*LOCALEUCS2) 或 LOCALETYPE (*LOCALEUTF) ,則現行語言環境的 LC_UNI_CTYPE 種類也可能影響行為。 如需相關資訊,請參閱 瞭解 CCSID 及語言環境

說明

printf() 函數會將一系列字元和值格式化並列印至標準輸出串流 stdout。 格式規格 (以百分比符號 (%) 開頭) ,決定 format-string後面任何 argument-list 的輸出格式。 format-string 是多位元組字串,以其起始移位狀態開始及結束。

format-string 由左至右讀取。 找到第一個格式規格時,會根據格式規格轉換並列印 format-string 之後的第一個引數值。 第二個格式規格會導致轉換並列印 format-string 之後的第二個引數,依此類推直到 format-string的結尾。 如果引數數目超過格式規格數目,則會評估並忽略額外引數。 如果所有格式規格都沒有足夠的引數,則未定義結果。

格式規格具有下列格式:

讀取語法圖跳過視覺化語法圖%旗標寬度.精準度 (precision)hLlllHDDD類型

轉換可以套用至引數清單中 format-string 之後的第 n 個引數,而不是套用至下一個未用的引數。 在此情況下,轉換字元% 會取代為順序 %n$ ,其中 n 是範圍 1 到 NL_ARGMAX 中的十進位整數,提供引數在引數清單中的位置。 此特性提供以特定語言適用的順序來選取引數之格式字串的定義。

替代格式規格具有下列格式:
讀取語法圖跳過視覺化語法圖%arg-number$旗標 寬度.精準度 (precision)hLlllHDDD類型

作為替代方案,可以使用前一個圖表中概述的格式規格來指派引數清單中的特定項目。 在對 printf()的相同呼叫中,無法混合此格式規格與先前的格式規格。 否則,可能會發生無法預期的結果。

arg-number 是正整數常數,其中 1 是指引數清單中的第一個項目。 引數號碼不能大於引數清單中的項目數,否則未定義結果。 Arg-number 也不能大於 NL_ARGMAX。

在包含轉換規格 %n$ 形式的格式字串中,引數清單中的編號引數可以從格式字串參照任意次數 (視需要而定)。

在包含轉換規格 %n$ 格式的格式字串中,欄位寬度或精準度可以由順序 * m$ 指示,其中 m 是範圍 1 到 NL_ARGMAX 中的十進位整數,提供包含欄位寬度或精準度之整數引數的引數清單中的位置 (在格式引數之後) ,例如:

printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);

格式字串可以包含已編號的引數規格 (即 %n$ 和 * m$) 或未編號的引數規格 (即% 和 *) ,但通常不能同時包含兩者。 唯一例外是 %% 可以與 %n$ 表單混合。 未定義 format-string 字串中混合編號及未編號引數規格的結果。 當使用編號引數規格時,指定第 n 個引數需要在格式字串中指定所有前導引數 (從第 1 個到第n-1個)。

格式規格的每一個欄位都是表示特定格式選項的單一字元或數字。 type 字元 (出現在最後一個選用格式欄位之後) 會決定相關聯的引數是否解譯為字元、字串、數字或指標。 最簡單的格式規格僅包含百分比符號及 type 字元 (例如, %s)。

下列選用欄位控制格式化的其他方面:
欄位
說明
旗標
輸出調整及列印符號、空白、小數點、八進位及十六進位字首,以及 wchar_t 精準度單元的語意。
寬度
輸出位元組數下限。
精準度
請參閱 表 2
h , l , ll , L , H , D , DD
預期的引數大小:
h
字首為 diouxXn 類型,指定引數是 short intunsigned short int
l
字首為 diouxXn 類型,指定引數為 long intunsigned long int
LL
字首為 diouxXn 類型,指定引數是 long long intunsigned long long int
L
字首為 aAeEfFgG 類型,指定引數為 long double
H
字首為 aAeEfFgG 類型,指定引數為 _Decimal32
D
字首為 aAeEfFgG 類型,指定引數為 _Decimal64
DD
字首為 aAeEfFgG 類型,指定引數為 _Decimal128

下面詳細說明格式規格的每一個欄位。 如果百分比符號 (%) 後接沒有意義作為格式欄位的字元,則未定義行為。 此行為的一個例外是 %%。 若要列印百分比符號字元,請使用 %%。

下表提供 type 字元及其意義:

表 1. 鍵入字元
字元 引數 輸出格式
a 浮點數 對於非十進位浮點數字,具有格式 [-] 0xh.hhhhp [sign]ddd,其中 h 是單一十六進位數字, hhhh 是一個以上十六進位數字, ddd 是一個以上十進位數字,而 sign 是 + 或-。 小數點後的十六進位位數等於所要求的精準度。

對於小數浮點數,如果遺漏精準度,則會根據下列準則使用 fe 樣式格式。

  • 當值的 量子指數 小於或等於 0 但大於或等於-(n+ 5) 時,會使用 f 樣式格式化。 可以透過呼叫 quantexp64() 函數來判定數字的 量子指數 。 n 是忽略小數點時數字序列中的位數 (包括尾端零)。 例如:

    0.000005

    在數字序列中包含 1 位數, n = 1

    0.0000050

    在數字序列中包含 2 位數, n = 2

    12.30

    在數字序列中包含 4 位數, n = 4

    精準度等於該值的 量子指數 的絕對值。

  • 當值的 量子指數 不滿足 f 樣式準則時,會使用 e 樣式格式。 精準度等於 n-1。 十進位浮點數值的 e 樣式格式與非十進位浮點數值的 e 樣式格式相同,但有兩個例外: a) 如果值等於 0 ,則指數等於該值的 量子指數 ; 以及 b) 指數一律提供所需的最小位數 (亦即,指數永不包含前導零)。 例如:

    0.0000000 會產生 0e-7

    -1870 會產生 -1.87e+3

如果精準度修飾元存在且至少與值的精準度一樣大,則轉換就如同遺漏精準度修飾元一樣。 如果精準度修飾元存在且小於值的精準度,則該值會先四捨五入至精準度修飾元指定的位數。 然後會轉換結果,如同遺漏精準度修飾元一樣。
A 浮點數 與格式相同,但使用大寫英文字母而非小寫英文字母。
d , i 整數 帶正負號的十進位整數。
u 整數 不帶正負號的十進位整數。
o 整數 不帶正負號的八進位整數。
x 整數 不帶正負號的十六進位整數,使用 abcdef。
X 整數 不帶正負號的十六進位整數,使用 ABCDEF。
D (n , p) 聚進十進位 它具有格式 [-] dddd.dddd ,其中小數點後的位數等於規格的精準度。 如果遺漏精準度,預設值為 p; 如果精準度為零,且未指定 # 旗標,則不會出現小數點字元。 如果 np 是 * ,則引數清單中的引數會提供值。 np 必須在引數清單中格式化的值之前。 小數點之前至少出現一個字元。 該值會四捨五入至適當的位數。
f 浮點數 具有格式 [-]dddd.dddd的帶正負號值,其中 dddd 是一個以上小數位數。 小數點之前的位數視數字的長度而定。 小數點後的位數等於所要求的精準度。2
F 浮點數 與 f 格式相同,但使用大寫英文字母而非小寫英文字母。2
e 浮點數 具有格式 [-]d.dddd e[sign]ddd的帶正負號值,其中 d 是單一小數位數, dddd 是一或多個小數位數, ddd 是 2 或多個小數位數,而 sign 是 + 或-。2
E 浮點數 e 格式相同,但使用大寫英文字母而非小寫英文字母。2
g 浮點數 fe 格式列印帶正負號的值。 只有在值的指數小於 -4 或大於或等於 精準度時,才會使用 e 格式。 尾端零會被截斷,且只有在小數點後面有一或多個數字時才會出現。2
G 浮點數 與 g 格式相同,但使用大寫英文字母而非小寫英文字母。2
c 字元 (位元組) 單一字元。
s 字串 最多列印到第一個空值字元 (\0) 或直到達到 precision 為止的字元 (位元組)。
n 整數指標 到目前為止已順利寫入 串流 或緩衝區的字元數 (位元組); 此值儲存在以位址作為引數的整數中。
p 指標 指標已轉換成一系列可列印字元。 它可以是下列其中一項:
  • 空間指標
  • 系統指標
  • 呼叫指標
  • 程序指標
  • 開啟指標
  • 暫停指標
  • 資料指標
  • 標籤指標
Lc 或 C 寬字元 (wchar_t) 字元會轉換成多位元組字元,如同wct明 () 呼叫一樣,且會印出此字元。1
ls 或 S 寬字元 直到第一個 (wchar_t) 空值字元 (L\0) 為止的 (wchar_t) 字元,或直到達到精準度為止,會轉換成多位元組字元,如同 wcstombs () 呼叫一樣,並印出這些字元。 如果引數是空字串,則會列印 (空值)。1
附註:
  1. 如需相關資訊,請參閱 wctomb() 函數的文件或 wcstombs() 函數的文件。 您也可以在 寬字元中找到其他資訊。
  2. 如果未使用 H、D 或 DD 格式大小指定元,則只會保證輸出有 15 個有效位數。

下列清單顯示 IBM® i 指標的列印值格式,並提供列印值元件的簡要說明。

空間指標: SPP:Context: Object :Offset :AG

Context: type , subtype and name of the context
Object: type , subtype and name of the object
Offset: offset within the space
AG: Activation group ID

系統指標: SYP:Context: Object :Auth :Index :AG

Context: type , 環境定義的子類型和名稱
物件: 類型、子類型和物件的名稱
授權: 權限
索引: 與指標相關聯的索引
AG: 啟動群組 ID

呼叫指標: IVP:Index :AG

索引: 與指標相關聯的索引
AG:      啟動群組 ID

程序指標: PRP:Index :AG

索引: 與指標相關聯的索引
AG: 啟動群組 ID

暫停指標: SUP:Index :AG

索引: 與指標相關聯的索引
AG: 啟動群組 ID

資料指標:  DTP:Index :AG

索引: 與指標相關聯的索引
AG: 啟動群組 ID

標籤指標: LBP:Index :AG

索引: 與指標相關聯的索引
AG: 啟動群組 ID

NULL 指標: NULL

下列限制適用於 IBM i 作業系統上的指標列印及掃描:
  • 如果從相同的啟動群組中印出指標並掃描回,則掃描回的指標會與印出的指標進行比較。
  • 如果 scanf() 系列函數掃描由不同啟動群組印出的指標,則 scanf() 系列函數會將指標設為 NULL。
  • 如果在兆空間環境中印出指標,則只會印出指標的十六進位值。 這些結果與使用%#p時相同。

%#p 格式指定元的效能遠優於 %p 格式指定元。

如需使用 IBM i 指標的相關資訊,請參閱 ILE C/C++ Programmer 's Guide

如果使用 a、e、f 或 g 格式來格式化 INFINITY 或 Not-a-Number (NaN) 的浮點值,則輸出字串是infinitynan。如果浮點數值 INFINITY 或 Not-A-Number (NaN) 是使用 A、E、F 或 G 格式來格式化,則輸出字串是INFINITYNAN.

旗標 字元及其意義如下 (請注意,格式規格中可以出現多個 旗標 ):

旗標 意義 預設
- 將欄位寬度內的結果靠左對齊。 向右對齊。
+ 如果輸出值是帶正負號的類型,則以正負號 (+ 或-) 作為輸出值的字首。 只有負正負號值 (-) 才會出現正負號。
空白('') 如果輸出值是帶正負號且為正數,則以空白作為輸出值的字首。 + 旗標會置換 空白 旗標 (如果兩者都出現的話) ,且正帶正負號的值將以符號輸出。 沒有空白。
# oxX 格式一起使用時, # 旗標會分別以 00x 或 0X 作為任何非零輸出值的字首。 無字首。
D (n , p)aAeEfF 格式一起使用時, # 旗標會強制輸出值在所有情況下都包含小數點。 只有在小數點後面接著數字時,才會出現小數點。
gG 格式搭配使用時, # 旗標會強制輸出值在所有情況下都包含小數點,並防止截斷尾端零。 只有在小數點後面接著數字時,才會出現小數點; 尾端零會被截斷。
ls 或 S 格式搭配使用時,不論字元大小為何, # 旗標會導致以字元為單位測量精準度。 例如,如果列印單位元組字元,則精準度 4 會導致列印 4 個位元組。 如果正在列印雙位元組字元,則精準度 4 會導致列印 8 個位元組。 精準度指出要輸出的位元組數上限。
p 格式一起使用時, # 旗標會將指標轉換為十六進位數字。 除非在兆空間環境中,否則這些十六進位數字無法轉換回指標。 指標已轉換成一系列可列印字元。
0 diD (n , p) ouxXaAeEfFgG 格式一起使用時, 0 旗標會導致前導 0將輸出填補至欄位寬度。 如果為整數指定精準度或指定 - 旗標,則會忽略 0 旗標。 空格填補。 D (n , p) 沒有空格填補。

# 旗標不應與 clcdius 類型一起使用。

寬度 是控制列印字元數下限的非負十進位整數。 如果輸出值中的字元數 (位元組) 小於指定的 寬度,則會在左側或右側新增空白 (視是否指定 - 旗標而定) ,直到達到最小寬度為止。

寬度 永不會截斷值; 如果輸出值中的字元數 (位元組) 大於指定的 寬度,或未提供 寬度 ,則會列印值的所有字元 (遵循 precision 規格)。

對於 ls 或 S 類型,以位元組為單位指定 width 。 如果輸出值中的位元組數小於指定的寬度,則會在左側或右側新增單位元組空白 (視是否指定 - 旗標而定) ,直到達到寬度下限為止。

width 規格可以是星號 (*) ,在此情況下,引數清單中的引數會提供值。 width 引數必須在引數清單中格式化的值之前。

精準度 是前面加上句點的非負十進位整數,指定要列印的字元數或小數位數。 與 width 規格不同, precision 可能會導致輸出值截斷或捨入浮點或 聚集十進位 值。

precision 規格可以是星號 (*) ,在此情況下,引數清單中的引數會提供值。 precision 引數必須在引數清單中格式化的值之前。

當省略 precision 時, precision 值和預設值的解譯取決於 類型,如下表所示:

表 2. 精準度值
類型 意義 預設
  a
A
對於非十進位浮點數字, precision 指定要在小數點之後列印的十六進位數字。

對於小數浮點數, precision 指定要列印的有效位數。

對於非十進位浮點數字,預設 精準度 足以精確呈現該值。 如果 precision 是 0 ,則不會列印任何小數點。 對於十進位浮點數字,預設 精準度 足以精確呈現該值。 如需所使用格式的詳細資料,請參閱 表 1
   i
d
u
o
x
X
精準度 指定要列印的位數下限。 如果引數中的位數小於 precision,則輸出值會在左側以零填補。 當位數超過 precision時,不會截斷該值。 如果 precision0 或完全省略,或如果出現句點 (.) 且後面沒有數字,則 precision 會設為 1。
   f
F
D (n , p)
e
E
精準度 指定要在小數點之後列印的位數。 列印的最後一個數字會四捨五入。 f、F、eE 的預設 精準度 為六。 D (n , p) 的預設 精準度p。 如果 precision0 ,或出現句點且後面沒有數字,則不會列印小數點。
   g
G
精準度 指定列印的最大有效位數。 列印所有有效位數。 預設 precision 是 6。
   c
沒有效果。 列印字元。
lc
沒有效果。 會轉換 wchar_t 字元,並列印產生的多位元組字元。
   s
精準度 指定要列印的字元數上限 (位元組)。 不會列印超出 precision 的字元 (位元組)。 會列印字元,直到發現空字元為止。
ls
精準度 指定要列印的位元組數上限。 不會列印超出 精準度 的位元組; 不過,一律會保留多位元組完整性。 會轉換 wchar_t 個字元,並列印產生的多位元組字元。

回覆值

printf() 函數會傳回列印的位元組數。 錯誤碼的值可以設為:
Value
意義
EBADMODE
指定的檔案模式無效。
ECONVERT
發生轉換錯誤。
EIOERROR
發生非可回復I/O錯誤。
EIORECERR
發生可回復I/O錯誤。
EILSEQ
發現無效的多位元組字元序列。
EPUTANDGET
讀取作業之後發生無效的寫入作業。
ESTDOUT
無法開啟 stdout
附註: printf() 函數的基數字元是區分語言環境的。 基數字元是要用於格式類型 D (n , p)、a、A、e、E、f、F、g 及 G 之格式字串參數的 # 旗標字元的小數點。

範例

此範例以各種格式列印資料。
#include <stdio.h>                                               
#include <stdlib.h>                                              
                                                                 
int main(void)                                                   
{                                                                
    char ch = 'h', *string = "computer";                         
    int count = 234, hex = 0x10, oct = 010, dec = 10;            
    double fp = 251.7366;                                        
    wchar_t wc = (wchar_t)0x0058;                                
    wchar_t ws[4];                                                       
                                                     
    printf("1234567890123%n4567890123456789\n\n", &count);          
    printf("Value of count should be 13; count = %d\n\n", count);   
    printf("%10c%5c\n", ch, ch);                                    
    printf("%25s\n%25.4s\n\n", string, string);                     
    printf("%f    %.2f    %e    %E\n\n", fp, fp, fp, fp);           
    printf("%i    %i     %i\n\n", hex, oct, dec);                   
}                                                                   
/*****************  Output should be similar to:  ***************** 
                                                                    
234   +234    000234     EA    ea     352                           
                                                                    
12345678901234567890123456789                                       
                                                                    
Value of count should be 13; count = 13                             
 
                                                                      
  h    h                                                              
          computer                                                    
              comp                                                    
                                                                      
251.736600    251.74    2.517366e+02    2.517366E+02                  
                                                                      
16    8     10                                                        
 
*******************************************************************/  

使用 printf() 的範例

     #include <stdio.h>
     #include <stdlib.h>
     #include <locale.h>
     /* This program is compiled with LOCALETYPE(*LOCALEUCS2) and             */
     /* SYSIFCOPT(*IFSIO)                                               */
     /* We will assume the locale setting is the same as the CCSID of the */
     /* job.  We will also assume any files involved have a CCSID of      */
     /* 65535 (no convert).  This way if printf goes to the screen or     */
     /* a file the output will be the same.                               */
    int main(void)
    {
        wchar_t wc = 0x0058;     /* UNICODE X */
        wchar_t ws[4];
        setlocale(LC_ALL,
         "/QSYS.LIB/EN_US.LOCALE"); /* a CCSID 37 locale */
        ws[0] = 0x0041;        /* UNICODE A   */
        ws[1] = (wchar_t)0x0042;        /* UNICODE B   */
        ws[2] = (wchar_t)0x0043;        /* UNICODE C   */
        ws[3] = (wchar_t)0x0000;
        /* The output displayed is CCSID 37  */
        printf("%lc   %ls\n\n",wc,ws);
        printf("%lc   %.2ls\n\n",wc,ws);

        /* Now let's try a mixed-byte CCSID example  */
        /* You would need a device that can handle mixed bytes to  */
        /* display this correctly.                         */

        setlocale(LC_ALL,
        "/QSYS.LIB/JA_JP.LOCALE");/* a CCSID 5026 locale */

        /* big A means an A that takes up 2 bytes on the screen   */
        /* It will look bigger then single byte A                 */
        ws[0] = (wchar_t)0xFF21;        /* UNICODE big A   */
        ws[1] = (wchar_t)0xFF22;        /* UNICODE big B   */
        ws[2] = (wchar_t)0xFF23;        /* UNICODE big C   */
        ws[3] = (wchar_t)0x0000;
        wc = 0xff11;                    /* UNICODE big 1   */

        printf("%lc   %ls\n\n",wc,ws);

        /* The output of this printf is not shown below and it   */
        /* will differ depending on the device you display it on,*/
        /* but if you looked at the string in hex it would look  */
        /* like this:  0E42F10F404040400E42C142C242C30F          */
        /* 0E is shift out, 0F is shift in, and 42F1 is the      */
        /* big 1 in CCSID   5026  */

        printf("%lc   %.4ls\n\n",wc,ws);

        /* The output of this printf is not shown below either. */
        /* The hex would look like:                             */
        /* 0E42F10F404040400E42C10F                             */
        /* Since the precision is in bytes we only get 4 bytes  */
        /* of the string.         */

        printf("%lc   %#.2ls\n\n",wc,ws);

        /* The output of this printf is not shown below either. */
        /* The hex would look like:                             */
        /* 0E42F10F404040400E42C142C20F                         */
        /* The # means precision is in characters reguardless   */
        /* of size.  So we get 2 characters of the string.      */
    }
 /*****************  Output should be similar to:  *****************


 X     ABC

 X     AB

 *******************************************************************/
 

使用 printf() 的範例

 #include <stdio.h>
 #include <stdlib.h>
 #include <locale.h>
 /* This program is compile LOCALETYPE(*LOCALE)  and               */
 /* SYSIFCOPT(*IFSIO)    */
 int main(void)
 {
     wchar_t wc = (wchar_t)0x00C4;     /*  D */
     wchar_t ws[4];
     ws[0] = (wchar_t)0x00C1;        /* A   */
     ws[1] = (wchar_t)0x00C2;        /* B   */
     ws[2] = (wchar_t)0x00C3;        /* C   */
     ws[3] = (wchar_t)0x0000;
     /* The output displayed is CCSID 37  */
     printf("%lc   %ls\n\n",wc,ws);

     /* Now let's try a mixed-byte CCSID example  */
     /* You would need a device that can handle mixed bytes to  */
     /* display this correctly.                         */

     setlocale(LC_ALL,
     "/QSYS.LIB/JA_JP.LOCALE"); /* a CCSID 5026 locale */

     /* big A means an A that takes up 2 bytes on the screen   */
     /* It will look bigger than single byte A                 */

     ws[0] = (wchar_t)0x42C1;        /* big A   */
     ws[1] = (wchar_t)0x42C2;        /* big B   */
     ws[2] = (wchar_t)0x42C3;        /* big C   */
     ws[3] = (wchar_t)0x0000;
     wc = 0x42F1;                    /* big 1   */

     printf("%lc   %ls\n\n",wc,ws);

     /* The output of this printf is not shown below and it   */
     /* will differ depending on the device you display it on,*/
     /* but if you looked at the string in hex it would look  */
     /* like this:  0E42F10F404040400E42C142C242C30F          */
     /* 0E is shift out, 0F is shift in, and 42F1 is the      */
     /* big 1 in CCSID   5026  */

     printf("%lc   %.4ls\n\n",wc,ws);

     /* The output of this printf is not shown below either. */
     /* The hex would look like:                             */
     /* 0E42F10F404040400E42C10F                             */
     /* Since the precision is in bytes we only get 4 bytes  */
     /* of the string.         */

     printf("%lc   %#.2ls\n\n",wc,ws);

     /* The output of this printf is not shown below either. */
     /* The hex would look like:                             */
     /* 0E42F10F404040400E42C142C20F                         */
     /* The # means precision is in characters regardless   */
     /* of size.  So we get 2 characters of the string.      */
 }
 /*****************  Output should be similar to:  *****************


 D     ABC


 *******************************************************************/
 

相關資訊