1. 程式人生 > >c檔案輸出函式printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s

c檔案輸出函式printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s

轉自:https://zh.cppreference.com/w/c/io/fprintf

 

定義於標頭檔案 <stdio.h>

   
  (1)  

int printf( const char *format, ... );

(C99 前)

int printf( const char *restrict format, ... );

(C99 起)
  (2)  

int fprintf( FILE *stream, const char *format, ... );

(C99 前)

int fprintf( FILE *restrict stream, const char *restrict format, ... );

(C99 起)
  (3)  

int sprintf( char *buffer, const char *format, ... );

(C99 前)

int sprintf( char *restrict buffer, const char *restrict format, ... );

(C99 起)

int snprintf( char *restrict buffer, int bufsz, 
              const char *restrict format, ... );

(4) (C99 起)

int printf_s(const char *restrict format, ...);

(5) (C11 起)

int fprintf_s(FILE *restrict stream, const char *restrict format, ...);

(6) (C11 起)

int sprintf_s(char *restrict buffer, rsize_t bufsz,
              const char *restrict format, ...);

(7) (C11 起)

int snprintf_s(char *restrict buffer, rsize_t bufsz,
               const char *restrict format, ...);

(8) (C11 起)
     

從給定位置載入資料,轉換為字串等價物,並寫結果到各種池。

1) 寫結果到 stdout 。

2) 寫結果到檔案流 stream 。

3) 寫結果到字串 buffer 。

4) 寫結果到字串 buffer 。至多寫 buf_size - 1 個字元。產生的字串會以空字元終止,除非 buf_size 為零。若 buf_size 為零,則不寫入任何內容,且 buffer 可以是空指標,然而依舊計算返回值(會寫入的字元數,不包含空終止符)並返回。

5-8) 同 (1-4) ,除了在執行時檢測下列錯誤,並呼叫當前安裝的制約處理函式:

  • format 中存在轉換指定符 %n
  • 任何一個對應 %s 的引數是空指標
  • format 或 buffer 是空指標
  • bufsz 為零或大於 RSIZE_MAX
  • 在任何一個字串及字元轉換指定符中出現編碼錯誤
  • (僅對於 sprintf_s )儲存於 buffer 的字串(包括尾隨空字元)長度將超出 bufsz

同所有邊界檢查函式, printf_s, fprintf_s, sprintf_s, snrintf_s 僅若實現定義了 __STDC_LIB_EXT1__ ,且使用者在包含 <stdio.h> 前定義 __STDC_WANT_LIB_EXT1__ 為整數常量 1 才保證可用。

引數

stream - 要寫入的輸出檔案流
buffer - 指向要寫入的字串的指標
bufsz - 最多會寫入 bufsz - 1 個字元,再加空終止符
format - 指向指定資料轉譯方式的空終止多位元組字串的指標。

格式字串由普通多位元組字元(除了 % )和轉換指定構成,前者被複制到輸出流而無更改。每個轉換指定擁有下列格式:

  • 引入的 % 字元
  • (可選)一或多個修改轉換行為的標籤:
  • - :轉換結果在域內左校正(預設為右校正)
  • + :有符號轉換的符號始終前置於轉換結果(預設結果前置負號僅當它為負)
  • 空格:若有符號轉換的結果不以符號開始,或為空,則前置空格於結果。若存在 + 標籤則忽略空格
  • # :進行另一種形式的轉換。準確的效果見下表,其他情況下行為未定義。
  • 0 :對於整數和浮點數轉換,使用前導零代替空格字元填充域。對於整數,若顯式指定精度,則忽略此標籤。對於其他轉換,使用此標籤導致未定義行為。若存在 - 標籤則忽略 0 。
  • (可選)指定最小域寬的整數值或 * 。若有要求,則結果會以空格字元(預設情況)填充,在右校正時於左,左校正時於右。使用 * 的情況下,以一個額外的 int 型別引數指定寬度。若引數值為負數,則它導致指定 - 標籤和正域寬。(注意:這是最小寬度:決不被截斷值)。
  • (可選)後隨整數或 * 或兩者皆無的 . 指示轉換的精度。在使用 * 的情況下,精度由額外的 int 型別引數指定。若此引數的值為負數,則它被忽略。若既不使用數字亦不使用 * ,則精度採用零。精度的準確效果見下表。
  • (可選)指定引數大小的長度修飾符
  • 轉換格式指定符

下列格式指定符可用:

轉換
指定符
解釋 引數型別
長度修飾符 hh

(C99)

h (無) l ll

(C99)

j

(C99)

z

(C99)

t

(C99)

L
% 寫字面的 % 。完整轉換指定必須是 %% 。 N/A N/A N/A N/A N/A N/A N/A N/A N/A
c

單個字元

引數首先被轉換成 unsigned char 。 若使用 l 修飾符,則引數首先被轉換成字串,如同通過以 wchar_t[2] 引數使用 %ls 。

N/A N/A

int

wint_t

N/A N/A N/A N/A N/A
s

寫一個字串

引數必須是指向字元陣列首元素的指標 精度指定寫入最大的字元數。若未指定精度,則寫每個位元組直到而而不含首個空終止符。 若使用 l 指定符,則引數必須是指向 wchar_t 陣列首元素的指標,陣列會被轉換成 char 陣列,如同通過以零初始化轉換狀態呼叫 wcrtomb 。

N/A N/A

char*

wchar_t*

N/A N/A N/A N/A N/A
d
i

轉換一個有符號整數為十進位制表示 [-]dddd 。

精度指定出現的最小數位數。預設精度是 1 。
若被轉換的值和精度都是  0  ,則轉換結果無字元。

signed char

short

int

long

long long

intmax_t

有符號 size_t

ptrdiff_t

N/A
o

轉換一個無符號整數為八進位制表示 oooo 。

精度指定出現的最小數位數。預設精度是 1 。 若被轉換值和精度都是  0  ,則轉換結果無字元。 在另一種實現中精度按需增加,以寫入一個前導零。 在此情況下若被轉換值和精度都是  0  ,則寫入單個  0  。

unsigned char

unsigned short

unsigned int

unsigned long

unsigned long long

uintmax_t

size_t

ptrdiff_t 的無符號版本

N/A
x
X

轉換一個無符號整數為十六進位制表示 hhhh 。

x 轉換使用字母 abcdef 。
X 轉換使用 ABCDEF 。
精度指定出現的最小數位數。預設精度是 1 。 若被轉換值和精度都是  0  ,則轉換結果無字元。 在另一種實現中若被轉換值為非零則結果有 0x 或 0X 字首。

N/A
u

轉換一個無符號整數為十進位制表示 dddd 。

精度指定出現的最小數位數。 預設精度是 1 。 若被轉換值和精度都是  0  ,則轉換結果無字元。

N/A
f
F

轉換一個浮點數為 [-]ddd.ddd 樣式的十進位制記法。

精度指定小數點字元後出現的最小數位數。 預設精度是 6 。 在另一種實現中即使沒有小數點後數位也寫小數點。 無窮大和非數的轉換樣式見注意。

N/A N/A

double

double (C99)

N/A N/A N/A N/A

long double

e 
E

轉換一個浮點數為十進位制指數記法。

e 轉換樣式使用 [-]d.ddde±dd 。
E 轉換樣式使用 [-]d.dddE±dd 。
指數至少含二個數位,僅當所需時使用更多數位。 若值為  0  ,則指數亦為  0  。 精度指定小數點字元後出現的最小數位數。 預設精度是 6 。 在另一種實現中即使沒有小數點後數位也寫小數點。 無窮大和非數的轉換樣式見注意。

N/A N/A N/A N/A N/A N/A
a 
A

(C99)

轉換一個浮點數為十六進位制記法。

a 轉換樣式使用 [-]0xh.hhhp±d 。
A 轉換樣式使用 [-]0Xh.hhhP±d 。
若引數不是正規化的浮點值,則首個十六進位制數位為 0。 若值為  0  ,則指數亦為  0  。 精度指定小數點字元後出現的最小數位數。 預設精度足以準確表示該值。 在另一種實現中即使沒有小數點後數位也寫小數點。 無窮大和非數的轉換樣式見注意。

N/A N/A N/A N/A N/A N/A
g 
G

轉換一個浮點數為十進位制小數或十進位制指數記法,依賴於值和精度

g 轉換樣式將進行帶樣式 e 或 f 的轉換。
G 轉換樣式將進行帶樣式 E 或 F 的轉換。
令 P 等於精度,若它非零,若精度未指定則為 6 ,若精度為  0  則等於 1 。然後,若帶樣式 E 的轉換會有指數 X ,則:

  • 若 P > X ≥ −4 ,則轉換帶 f 或 F 風格,及精度 P − 1 − X 。
  • 否則,轉換帶 e 或 E 風格,及精度 P − 1 。

除非要求另一種表示,否則末尾零會被移除,且若不留下小數部分則小數點亦被移除。 無窮大和非數的轉換樣式見注意。

N/A N/A N/A N/A N/A N/A
n

返回對函式的此呼叫迄今為止寫入的字元數

結果被寫入到引數所指向的值。 該指定不可含有任何標籤域寬精度

signed char*

short*

int*

long*

long long*

intmax_t*

有符號 size_t*

ptrdiff_t*

N/A
p 寫定義一個指標的實現定義字元序列。 N/A N/A void* N/A N/A N/A N/A N/A N/A

浮點轉換函式轉換無窮大到 inf 或 infinity 。使用哪一個是實現定義的。

非數轉換成 nan 或 nan(char_sequence) 。使用哪一個是實現定義的。

轉換 F 、 E 、 G 、 A 替代上面輸出 INF 、 INFINITY 、 NAN

儘管 %c 期待 int 引數,傳遞 char 是安全的,因為在呼叫變引數函式時發生整數提升。

定寬整數型別( int8_t 等)的正確轉換指定定義於標頭檔案 <inttypes.h> (儘管 PRIdMAX 、 PRIuMAX 等就是 %jd、 %ju 等的別名)。

記憶體寫入轉換指定符 %n 是安全漏洞的常見目標,這裡格式字串依賴使用者輸入,而此轉換指定符不為邊界檢查的 printf_s 系列函式所支援。

在每個轉換指定符的行動後有一個序列點;這允許存入多次 %n 的結果於同一變數,並在同一呼叫中打印出先前以 %n 儲存的值。

若轉換指定非法,則行為未定義。

 

... - 指定要列印資料的引數。若任何預設引數提升後的引數不擁有對應轉換指定符所期待的型別,或若引數數量少於 format 的要求,則行為未定義。若有多於 format 要求的引數,則求值並忽略多出的引數。

返回值

1,2) 傳輸到輸出流的字元數,或若出現輸出錯誤或編碼錯誤(對於字串和字元轉換指定符)則為負值。

3) 寫入到 buffer 的字元數(不計空終止字元),或若輸出錯誤或編碼錯誤(對於字串和字元轉換指定符)發生則為負值。

4) 假如忽略 bufsz 則本應寫入到 buffer 的字元數(不計空終止字元),或若出現輸出錯誤或編碼錯誤(對於字串和字元轉換指定符)則為負值。

5,6) 傳輸到輸出流的字元數,或若出現輸出錯誤、執行時制約違規錯誤或編碼錯誤則為負值。

7) 寫入到buffer的字元數,不計空終止字元(只要 buffer 不是空指標且 bufsz 非零且不大於 RSIZE_MAX ,就寫入它),在執行時制約違規時為零,而在編碼錯誤時為負值。

8) 假如忽略 bufsz 則本應寫入 buffer 的字元數的,不包含空終止字元(只要 buffer 不是空指標而 bufsz 非零且不大於 RSIZE_MAX ,就寫入它),或若出現輸出錯誤、執行時制約違規錯誤或編碼錯誤則為負值。

注意

C 標準及POSIX 指定 sprintf 及其變體的行為在引數與目標緩衝區重疊時未定義。示例:

sprintf(dst, "%s and %s", dst, t); // <- 有錯:未定義行為

POSIX指定在錯誤時設定errno。它亦指定附加的轉換指定,最值得注意的是對引數重排序的支援(緊隨%之後的n$指示第n個引數)。

以零為 bufsz 和空指標為 buffer 呼叫 snprintf 可用於決定包含輸出的緩衝區大小:

const char *fmt = "sqrt(2) = %f";
int sz = snprintf(NULL, 0, fmt, sqrt(2));
char buf[sz + 1]; // 注意為終止空字元 +1
snprintf(buf, sizeof buf, fmt, sqrt(2));

同 snprintf ,但不同於 sprintf_s , snprintf_s 會將輸出截斷在 bufsz-1 之內。

示例

執行此程式碼

#include <stdio.h>
 
int main(void)
{
    printf("Strings:\n");
    const char* s = "Hello";
    printf("\t.%10s.\n\t.%-10s.\n\t.%*s.\n", s, s, 10, s);
 
    printf("Characters:\t%c %%\n", 65);
 
    printf("Integers\n");
    printf("Decimal:\t%i %d %.6i %i %.0i %+i %u\n", 1, 2, 3, 0, 0, 4, -1);
    printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
    printf("Octal:\t%o %#o %#o\n", 10, 10, 4);
 
    printf("Floating point\n");
    printf("Rounding:\t%f %.0f %.32f\n", 1.5, 1.5, 1.3);
    printf("Padding:\t%05.2f %.2f %5.2f\n", 1.5, 1.5, 1.5);
    printf("Scientific:\t%E %e\n", 1.5, 1.5);
    printf("Hexadecimal:\t%a %A\n", 1.5, 1.5);
}

輸出:

Strings:
    .     Hello.
    .Hello     .
    .     Hello.
Characters:     A %
Integers
Decimal:        1 2 000003 0  +4 4294967295
Hexadecimal:    5 a A 0x6
Octal:          12 012 04
Floating point
Rounding:       1.500000 2 1.30000000000000004440892098500626
Padding:        01.50 1.50  1.50
Scientific:     1.500000E+00 1.500000e+00
Hexadecimal:    0x1.8p+0 0X1.8P+0

引用

  • C11 standard (ISO/IEC 9899:2011):
  • 7.21.6.1 The fprintf function (p: 309-316)
  • 7.21.6.3 The printf function (p: 324)
  • 7.21.6.5 The snprintf function (p: 325)
  • 7.21.6.6 The sprintf function (p: 325-326)
  • K.3.5.3.1 The fprintf_s function (p: 591)
  • K.3.5.3.3 The printf_s function (p: 593-594)
  • K.3.5.3.5 The snprintf_s function (p: 594-595)
  • K.3.5.3.6 The sprintf_s function (p: 595-596)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.19.6.1 The fprintf function (p: 274-282)
  • 7.19.6.3 The printf function (p: 290)
  • 7.19.6.5 The snprintf function (p: 290-291)
  • 7.19.6.6 The sprintf function (p: 291)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 4.9.6.1 The fprintf function
  • 4.9.6.3 The printf function
  • 4.9.6.5 The sprintf function

參閱

wprintf
fwprintf
swprintf
wprintf_s
fwprintf_s
swprintf_s
snwprintf_s

(C95)
(C95)
(C95)
(C11)
(C11)
(C11)
(C11)

列印格式化寬字元輸出到stdout、檔案流或緩衝區 
(函式)

vprintf
vfprintf
vsprintf
vsnprintf
vprintf_s
vfprintf_s
vsprintf_s
vsnprintf_s




(C99)
(C11)
(C11)
(C11)
(C11)

列印格式化輸出到stdout、檔案流或緩衝區
使用可變引數列表 
(函式)

fputs

將一個字串寫入檔案流 
(函式)

scanf
fscanf
sscanf
scanf_s
fscanf_s
sscanf_s




(C11)
(C11)
(C11)

stdin、檔案流或緩衝區讀取格式化輸入 
(函式)

printf, fprintf, sprintf, snprintf 的 C++ 文件