C 語言的 printf() 函數(shù)全面解析
概述
printf() 的作用: Print formatted output to the standard output stream.
printf() 的函數(shù)原型:
int printf( const char *format, argument1, argument2, ... );
printf() 函數(shù)的基本格式:
printf(格式字符串, 待打印項列表);
或者寫為:
printf(格式字符串, 待打印項 1, 待打印項 2, ...);
待打印項 1, 待打印項 2 等都是要打印的項, 可以是變量, 常量或者在打印之前可以先進行求值的表達式, 然后打印這個表達式的值.
格式字符串中包含兩種不同的信息:
- 實際要打印的字符, 即直接打印的字符, 也叫字面字符.
- 轉換說明.
示意圖 1:

示意圖 2:

向 printf 或其他沒有在函數(shù)原型中指明形參類型的函數(shù)傳遞實參時, short 類型實參被轉換為 int, float 類型實參被轉換為 double.
printf() 格式控制符
printf() 格式控制符的完整形式如下:
%[flag][width][.precision]type
[ ] 表示此處的內(nèi)容可有可無,是可以省略的。
type 表示輸出類型,即基本的轉換說明,或稱為轉換字符。
width 表示最小輸出寬度。
flag 表示標記。
precision 表示精度。
除了 type 之外統(tǒng)稱為修飾符。
轉換說明
整型
int
int 類型, 即基本整型, 通常只有十進制, 轉換說明為:
%d
short int
short int 簡稱為 short, 即短整型. 轉換說明要加前綴 h, 即:
%hd
long int
long int 簡稱為 long, 即長整型. 轉換說明要加前綴 l, 即:
%ld
long long int
long long int 簡稱為 long long, 即長長整型, 是 C99 新增, C90 不支持. 轉換說明要加前綴 ll, 即:
%lld
unsigned int
unsigned int 簡稱 unsigned, 即無符號基本整型.
有三種進制, 即十進制, 八進制, 十六進制.
以八進制和十六進制輸出時, 會將符號位視為數(shù)值位, 故以八進制或十六進制形式輸出整數(shù)時只能用于無符號整數(shù).
printf() 不支持以八進制和十六進制形式輸出有符號數(shù), 也沒有對應的轉換說明符.
十進制:
%u
十進制沒有前綴, 若加了 # 則結果未定義.
八進制:
顯示前綴:%#o(得到前綴 0) 不顯示前綴:%o
十六進制:
顯示前綴:%#x(得到前綴 0x),%#X(得到前綴 0X) 不顯示前綴:%x,%X 使用 x 則十六進制數(shù)用 1-9 和 a-f 表示. 使用 X 則十六進制數(shù)用 1-9 和 A-F 表示.
程序示例:
#include<stdio.h>
int main(void)
{
unsigned int x = 100;
printf("dec = %u; octal = %o; hex = %x\n", x, x, x);
printf("dec = %u; octal = %o; hex = %X\n", x, x, x);
printf("dec = %u; octal = %#o; hex = %#x\n", x, x, x);
printf("dec = %u; octal = %#o; hex = %#X\n", x, x, x);
return 0;
}結果:
dec = 100; octal = 144; hex = 64 dec = 100; octal = 144; hex = 64 dec = 100; octal = 0144; hex = 0x64 dec = 100; octal = 0144; hex = 0X64
unsigned short int
unsigned short int 簡稱 unsigned short, 即無符號短整型, 分三種進制進行打印:
十進制:
%hu
八進制:
顯示前綴: %#ho 不顯示前綴: %ho
十六進制:
顯示前綴: %#hx 或 %#hX 不顯示前綴: %hx 或 %hX
unsigned long int
unsigned long int 簡稱為 unsigned long, 即無符號長整形.
十進制:
%lu
八進制:
顯示前綴: %#lo 不顯示前綴: %lo
十六進制:
顯示前綴: %#lx 或 %#lX 不顯示前綴: %lx 或 %lX
unsigned long long int
unsigned long long int 簡稱為 unsigned long long, 即無符號長長整型.
十進制:
%llu
八進制:
顯示前綴: %#llo 不顯示前綴: %llo
十六進制:
顯示前綴: %#llx 或 %#llX 不顯示前綴: %llx 或 %llX
規(guī)律:
short, long, long long 就是在 int 的 d 前面加前綴 h, l, ll. unsigned short, unsigned long, unsigned long long 就是在 unsigned 的 u, o, x/X 前面加前綴 h, l, ll.
轉換說明中的字母盡量都用小寫,除了表示十六進制的 X(經(jīng)測試,小寫都不會出錯,大寫可能出錯)。
此類前綴稱為修飾符.
有符號類型只能以十進制輸出 (雖然有符號的正數(shù)以十六進制和八進制輸出也不會出錯, 但只是剛好符號位為 0 而已).
無符號類型可以三種進制 (十進制, 八進制, 十六進制) 輸出. 要顯示八進制前綴 0 和十六進制前綴 0x 或 0X 時在轉換說明的 % 后面加 #.
布爾型
轉換說明:
%u
字符型
轉換說明:
%c,%d,%o,%x
程序示例:
#include <stdio.h>
int main(void) {
char c = 'a';
printf("%c\t%d\t%o\t%x\n", c, c, c, c); // a 97 141 61
return 0;
}地址
轉換說明:
%p
指針之差
兩個指針差值的類型為 ptrdiff_t,這是 C99 引入的類型。這是一個底層有符號整數(shù)類型。
%td
sizeof 和 strlen() 的返回值類型
這個類型為 size_t,這是 C99 引入的類型。這是一個底層無符號整數(shù)類型。
%zd
浮點型
float 和 double
十進制:
%f
指數(shù)計數(shù)法:
%e %E
十六進制:
%a %A
long double
十進制:
%Lf
指數(shù)計數(shù)法:
%Le
十六進制:
%La
給未在函數(shù)原型中顯式說明參數(shù)類型的函數(shù)(如 printf)傳遞參數(shù)時,C 編譯器會把 float 類型的值自動轉換為 double 類型。
%f, %e, %E, %Lf, %Le 都是默認小數(shù)點后輸出 6 位。其中,%e, %E, %Le 都是默認小數(shù)點前輸出 1 位。全部都可以四舍五入。
程序示例:
#include<stdio.h>
int main(void) {
float a = 123.123456789;
long double b = 123.123456789L;
printf("%f\n", a);
printf("%e\n", a);
printf("%Lf\n", a);
printf("%Le\n", a);
return 0;
}執(zhí)行結果:
123.123459 1.231235e+02 123.123459 1.231235e+02
程序示例:
#include <stdio.h>
int main()
{
float f = 3.1415926535f;
double d = 3.1415926535;
printf("f = %f, d = %f\n", f, d);
printf("f = %.8f, d = %.8f\n", f, d); // f 的值不再精確
}執(zhí)行結果:
f = 3.141593, d = 3.141593 f = 3.14159274, d = 3.14159265
%g
根據(jù)值的不同, 自動選擇 %f 或者 %e 來打印浮點數(shù), %e 格式用于指數(shù)小于 -4 或者大于或等于精度時.
%G
根據(jù)值的不同, 自動選擇 %f 或者 %E 來打印浮點數(shù), %e 格式用于指數(shù)小于 -4 或者大于或等于精度時.
修飾符
以上各個百分號后面的字母叫做 轉換字符 . 在 轉換字符 和 百分號 之間還可以有 修飾符 . 修飾符可以修飾基本的轉換說明.
轉換說明即由三部分組成: 百分號, 修飾符, 轉換字符 .
數(shù)字
表示寬度
轉換說明中, 小數(shù)點前面的數(shù)字可以表示待打印項的最小字段寬度, 在指定寬度范圍內(nèi), 內(nèi)容右對齊.
如果字段寬度不能容納待打印的內(nèi)容, 系統(tǒng)會自動使用剛好合適的寬度.
就是%[flag][width][.precision]type當中的 width 部分.
程序示例 1:
#include<stdio.h>
int main(void)
{
printf("**********\n");
printf("%10s\n", "hello");
return 0;
}結果:
**********
hello
程序示例 2:
#include<stdio.h>
int main(void)
{
printf("**********\n");
printf("%10d\n", 30);
return 0;
}結果:
**********
30
程序示例 3:
#include<stdio.h>
int main(void)
{
printf("**********\n");
printf("%10s\n", "hello world!");
return 0;
}結果:
********** hello world!
表示精度
轉換說明中, 小數(shù)點后面的數(shù)字還可以表示浮點數(shù)的精度, 即浮點數(shù)的小數(shù)點后面有幾個數(shù)字, 可以四舍五入.
就是%[flag][width][.precision]type當中的 precision 部分.
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
float a = 1235.56789;
printf("%e\n", a); // %e, %f, %Lf 默認小數(shù)點后面 6 個數(shù)字,可以進行四舍五入
printf("%.4e\n", a); // 明確指定小數(shù)點后面 4 個數(shù)字,可以進行四舍五入
printf("%.4f\n", a); // 明確指定小數(shù)點后面 4 個數(shù)字,可以進行四舍五入
return 0;
}結果:
1.235568e+03 1.2356e+03 1235.5679
這種精度表示方式適用于 %e,%E 和 %f.
小數(shù)點前面的數(shù)字表示字段寬度, 小數(shù)點后面的數(shù)字表示輸出的浮點數(shù)的小數(shù)點后面的位數(shù).
可以看出, 這里發(fā)生了四舍五入.
如果轉換說明中, 只是用了小數(shù)點, 則說明輸出的數(shù)字沒有小數(shù)部分, 即沒有小數(shù)點以及小數(shù)點后面的數(shù)字. 也就是說 %.f 和 %.0f 兩者效果相同.
在去掉小數(shù)部分時依然會發(fā)生四舍五入.
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
float a = 12345.88888;
printf("%.f\n", a); // 只有小數(shù)點
printf("%.0f\n", a);
return 0;
}結果:
12346 12346
可以看出這里發(fā)生了四舍五入.
表示待打印字符的最多個數(shù)
在轉換說明 %s 中, 在小數(shù)點后面加數(shù)字, 可以表示待打印的字符的最多個數(shù).
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
char name[20] = "helloworld";
printf("%s\n", name); // 直接輸出整個字符串
printf("%.5s\n", name); // 最多輸出5個字符
printf("********************\n");
printf("%10.6s\n", name); // 輸出的字符串最多占用10個位置,最多輸出6個字符,默認右對齊
printf("%-10.5s\n", name); // 輸出的字符最多占用10個位置,最多輸出5個字符,左對齊
return 0;
}結果:
helloworld
hello
********************
hellow
hello
表示整數(shù)的最少位數(shù)
當 %d 轉換說明中, 小數(shù)點后面有數(shù)字時, 該數(shù)字表示待輸出的整數(shù)最小占用的位數(shù), 如果指定的位數(shù)小于數(shù)字的真實位數(shù), 則忽視這個位數(shù)的要求而直接打印數(shù)字, 如果指定的位數(shù)大于數(shù)字的真實位數(shù), 則數(shù)字靠右打印, 左側用數(shù)字 0 補齊要求的位數(shù). 不論哪種情況待打印的數(shù)字都是完整輸出的.
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
int a = 12345;
// 最小打印四位數(shù)字,原數(shù)字超過了四位,則直接忽視這個4,打印原始的數(shù)字
printf("%.4d\n", a);
// 最小打印六位數(shù)字,原數(shù)字為五位,則打印原始的數(shù)字,原始數(shù)字靠右,左側用0補齊六位
printf("%.6d\n", a);
return 0;
}結果:
12345 012345
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
int a = 12345;
printf("**********\n");
printf("%10.7d\n", a); // 指定字段寬度為 10, 至少輸出 7 個數(shù)字, 不夠的用 0 不足位數(shù)
return 0;
}結果:
********** 0012345
標記
標記有五種: -, +, 空格, #, 0.
可以不使用或者使用多個標記.
就是%[flag][width][.precision]type當中的 flag 部分。
- 標記
- 可以使得在指定的字段范圍內(nèi), 待打印項左對齊.
程序示例:
#include<stdio.h>
int main(void)
{
int a = 123;
printf("**********\n");
printf("%-10d\n", a);
return 0;
}結果:
********** 123
+ 標記
有符號值若為正, 則在前面顯示 +. 若為負, 則在前面顯示 -.
程序示例:
#include<stdio.h>
int main(void)
{
int a = 123;
int b = -123;
printf("%+d\n", a);
printf("%+d\n", b);
return 0;
}結果:
+123 -123
空格
有符號值若為正, 則在前面顯示空格, 不顯示任何符號, 若為負, 則在前面顯示減號.
如果在轉換說明的修飾符中, 正號 + 和空格同時存在, 則正號起作用而空格不起作用.
程序示例:
#include<stdio.h>
int main(void)
{
int a = 123;
int b = -123;
printf("% d\n", a);
printf("%+ d\n", a); // 正號 + 和空格同時存在, 則正號起作用而空格不起作用
printf("% d\n", b);
printf("%+ d\n", b); // 正號 + 和空格同時存在, 則正號起作用而空格不起作用
return 0;
}結果:
123 +123 -123 -123
#標記
對于 %o, 輸出將以 0 開始.
對于 %x 和 %X, 輸出將以 0x 和 0X 開頭.
對于所有的浮點數(shù), 即使沒有小數(shù)部分也會打印一個小數(shù)點.
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
float a = 123e2;
printf("%.0f\n", a);
printf("%#.0f\n", a);
return 0;
}結果:
12300 12300.
對于 %g 和 %G 格式, # 防止結果后面的 0 被刪除.
0 標記
對于數(shù)值格式, 用前導 0 代替空格填充字段寬度.
對于整數(shù)格式, 如果出現(xiàn) - 標記或者指定最少輸出的數(shù)字個數(shù), 則忽略 0 這個標記.
程序示例 1:
#include<stdio.h>
int main(void)
{
int a = 88;
printf("**********\n");
printf("%10d\n", a);
printf("%010d\n", a); // 用前導 0 代替空格填充字段寬度
printf("%-010d\n", a); // 出現(xiàn) - 標記, 標記 0 不起作用
return 0;
}結果:
**********
88
0000000088
88
程序示例 2:
#include<stdio.h>
int main(void)
{
float a = 1.2345;
printf("**********\n");
printf("%10.3f\n", a);
printf("%010.3f\n", a); // 對于浮點數(shù),指定了精度,但標記 0 依然起作用,只有整數(shù)里面的標記 0 可能被覆蓋不起作用
return 0;
}結果:
**********
1.235
000001.235
程序示例 3:
#include<stdio.h>
int main(void)
{
int a = 12345;
printf("**********\n");
printf("%10d\n", a); // 指定字段寬度為10
printf("%10.3d\n", a); // 指定最少輸出3位,實際為5位,因此3被忽視,直接輸出原來的數(shù)字
printf("%010d\n", a); // 不指定整數(shù)最少輸出的數(shù)字個數(shù),標記 0 起作用
printf("%010.3d\n", a); // 指定整數(shù)最少輸出的數(shù)字個數(shù),標記 0 不起作用
return 0;
}結果:
**********
12345
12345
0000012345
12345
轉換說明的意義
數(shù)據(jù)存儲在計算機中是以二進制的數(shù)字形式存儲的, 但是用 printf 將其顯示在屏幕上時顯示的是字符. 比如在屏幕上顯示 42 是顯示字符 4 和字符 2.
轉化說明就負責這一轉換過程. 轉換說明就是一種翻譯說明. 轉換說明把以二進制格式存儲在計算機中的值轉換成一系列字符(字符串)以便于顯示。轉換說明是翻譯說明。
%%
可以使用 %% 打印一個百分號 %
程序示例:
#include<stdio.h>
#include<string.h>
int main(void)
{
printf("Only %d%% students are good.", 30);
return 0;
}結果:
Only 30% students are good.
常見錯誤
1.
用 %d 打印浮點數(shù)時,不會將浮點數(shù)轉換為整型。
程序示例:
#include<stdio.h>
int main(void)
{
float a = 10.1111115;
printf("%d\n", a);
return 0;
}結果:
-1610612736
各個系統(tǒng)結果可能不同。
刷新輸出
printf() 語句先把輸出發(fā)送到一個叫做緩沖區(qū)的中間存儲區(qū)域,然后緩沖區(qū)中的內(nèi)容再不斷地被發(fā)送到屏幕上。
C 標準明確規(guī)定了何時把緩沖區(qū)中的內(nèi)容發(fā)送到屏幕:當緩沖區(qū)滿,遇到換行符或者需要輸入時。
從緩沖區(qū)把數(shù)據(jù)發(fā)送到屏幕或文件被稱為刷新緩沖區(qū)或清空緩沖區(qū)。
C 標準明確規(guī)定了何時向屏幕發(fā)送緩沖區(qū)的內(nèi)容, 即刷新緩沖區(qū): 緩沖區(qū)滿了或遇到換行符或需要輸入。
緩沖區(qū)分為輸入緩沖區(qū)和輸出緩沖區(qū)。輸入分為有緩沖輸入和無緩沖輸入,輸出分為有緩沖輸出和無緩沖輸出。
如果輸入的內(nèi)容能立即被程序使用,則為無緩沖輸入。如果輸入的內(nèi)容需要在刷新了緩沖區(qū)后才能被程序利用,則為有緩沖輸入。C 標準為有緩沖輸入。
某些交互式程序要求輸入必須是無緩沖的,比如打游戲。
有緩沖輸入/輸出分為行緩沖和塊緩沖,塊緩沖也叫完全緩沖。
完全緩沖是指當緩沖區(qū)被填滿時才刷新緩沖區(qū),通常出現(xiàn)在文件輸入中。緩沖區(qū)的大小取決于系統(tǒng),常見的大小為 512 字節(jié)和 4096 字節(jié)。
行緩沖是指在出現(xiàn)換行符時刷新緩沖區(qū)。鍵盤輸入通常是行緩沖輸入,所以在按下 Enter 鍵之后才刷新緩沖區(qū)。
printf 函數(shù)的返回值
returns the number of characters printed, or a negative value if an error occurs.
printf() 函數(shù)返回它打印的字符的個數(shù).
如果輸出有誤, 則 printf() 返回一個負值.
程序示例:
#include<stdio.h>
int main(void)
{
printf("%d\n", printf("Hello\n"));
return 0;
}
結果:
Hello 6
顯然, 需要求 printf("Hello\n") 表達式的返回值, 需要先計算該表達式, 效果是打印出一句話, 即 Hello.
此返回值包括了所有的字符, 尤其是空格和轉義字符如 \n 等.
* 修飾符的用法
輸出時可以不預先指定字段的寬度, 可以通過程序來指定.
可以用 * 修飾符來替換字段寬度.
此時需要另一個參數(shù)來告訴函數(shù), 這個字段寬度應該是多少.
即, 如果轉換說明是 %*d, 則參數(shù)列表中應該包含 * 和 d 對應的值.
該技巧也可用于浮點值指定精度和字段寬度.
程序示例:
#include<stdio.h>
#define NUMBER 123
int main(void)
{
printf("Please enter field width: ");
int width = 0;
scanf("%d", &width);
printf("This integer is %*d\n", width, NUMBER);
return 0;
}
結果:
Please enter field width: 6 This integer is 123
程序示例:
#include<stdio.h>
#define NUMBER 123.456789
int main(void)
{
printf("Please enter field width: ");
int width = 0;
scanf("%d", &width);
printf("Please enter precision: ");
int precision = 0;
scanf("%d", &precision);
printf("This number is %*.*f.\n", width,precision,NUMBER);
return 0;
}
結果:
Please enter field width: 14 Please enter precision: 3 This number is 123.457.
到此這篇關于C 語言的 printf() 函數(shù)全面解析的文章就介紹到這了,更多相關C 語言 printf() 函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C語言函數(shù)指針數(shù)組實現(xiàn)計算器功能
這篇文章主要通過C語言函數(shù)指針數(shù)組實現(xiàn)了計算器的功能,是一個很好而且流程詳細的小例子,感興趣的新手朋友們可以自己動手也寫一遍2022-04-04
Pipes實現(xiàn)LeetCode(193.驗證電話號碼)
這篇文章主要介紹了Pipes實現(xiàn)LeetCode(193.驗證電話號碼),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08

