printf()函数
C语言中的printf函数使用转换说明(Conversion Specifier)来格式化输出。一个完整的格式控制符通常以百分号 % 开头,后跟一个或多个字符来指定输出的类型和格式。
其基本结构可以理解为:%[标志][宽度][.精度][长度修饰符]转换说明符。前四个可选参数统称为转换说明修饰符。
转换说明符
用于指定输出数据类型。可单独使用。
| 转换说明符 | 含义 |
d | 输出有符号十进制整数,i与其等价。单独使用时参数类型应为int。 |
u | 输出无符号十进制整数。单独使用时参数类型应为unsigned int。 |
f | 输出十进制单精度/双精度浮点数。默认精确到小数点后六位。单独使用时参数类型应为float或double。 |
a | 输出用p记数法表示的十六进制浮点数。若改为A则将输出内容中的小写字母替换为大写。单独使用时参数类型应为float或double。 |
g | 根据值的不同,自动判断是否使用科学计数法。科学计数法默认在指数小于-4时使用;若指定精度,也会在指数大于或等于精度时使用。若改为G则将输出内容中的e替换为E。单独使用时参数类型应为 float或double。 |
e | 输出科学计数法形式的浮点数。若改为E则将输出内容中的e替换为E。 |
o | 输出无符号八进制整数,不含前缀。单独使用时参数类型应为unsigned int,若传入有符号整数则输出其八进制补码。 |
x | 输出无符号十六进制整数,不含前缀。若改为X则将输出内容中的小写字母替换为大写。单独使用时参数类型应为unsigned int,若传入有符号整数则输出其十六进制补码。 |
c | 输出一个字符。参数应为int,在使用时被转换为unsigned char。 |
s | 输出一个字符串。参数应为指向数组的指针。 |
p | 输出指针地址。输出内容为十六进制数,包含前缀。 |
标志
用于控制输出的对齐、前缀等。需要紧跟在 % 后面使用。
| 标志字符 | 含义 |
- | 左对齐,在指定字段宽度的右侧填充空格。 |
+ | 为数据显示正负号,对unsigned型不生效。 |
| 如果输出值为非负数且没有符号则添加空格。在同时指定+标志时被忽略。 |
# | 对于八进制和十六进制分别添加0和0x/X的前缀;对于小数则强制输出小数点,即使后面没有数字。 |
0 | 使用0而不是空格进行填充。如果指定了左对齐标志或对整数指定精度则被忽略。 |
字符宽度
一个数字,位于标志字符之后,指定输出的最小字符宽度。如果输出的字符数小于此宽度,则用空格(若指定了0标志则用0)填充。如果输出的字符超过此宽度则不会生效。
数据精度
以一个点号开头,位于字符宽度之后。当输出的数据类型为整数(转换说明字符为d, i, o, u, x, X)时,指定要显示的最小数字位数,不足时在前面补0。当输出的数据类型为浮点数(转换说明字符为f, F, e, E, a, A)时,指定小数点后的位数,不足在后面补0。当转换说明字符为g或G时,指定保留的有效数字位数。当输出的数据类型为字符串时(转换说明字符为s),指定将会输出的最大字符数。
特别地,若将字符宽度和数据精度用*代替,则会采用参数列表中在输出内容之前的两项内容来代替。
长度修饰符
位于数据精度之后,转换说明符之前。用于指定输出数据的大小以便处理不同长度的数据。
| 长度修饰符 | 含义 |
h | 表示short或unsigned short类型。适用于所有整数转换说明符。 |
hh | 表示signed char或unsigned char类型。适用于所有整数转换说明符。 |
l | 表示long或unsigned long。适用于所有整数转换说明符。 |
ll | 表示long long或unsigned long long。适用于所有整数转换说明符。 |
L | 表示long double。适用于所有浮点转换说明符。 |
z | 表示size_t(sizeof运算符返回)。 |
t | 表示ptrdiff_t(指针相减返回)。 |
示例
接下来看一些使用例:
// 单独使用转换说明符
#include <stdio.h>
int main(void)
{
int a = 87;
unsigned int b = 87;
float c = 3.14;
double d = 2.71;
float e = 1919810;
unsigned int f = 87;
unsigned int g = 114514;
int h = 65;
char i[] = "Hello World.";
long *j = &a;
printf("%d\n", a);
printf("%u\n", b);
printf("%f %f\n", c, d);
printf("%a %A %g %G\n", c, c, c * 0.00001, e);
printf("%e\n", e);
printf("%o\n", f);
printf("%x %X\n", g, g);
printf("%c\n", h);
printf("%s\n", i);
printf("%p", (void *)j);
return 0;
}输出为:
87
87
3.140000 2.710000
0x1.91eb860000000p+1 0X1.91EB860000000P+1 3.14e-05 1.91981E+06
1.919810e+06
127
1bf52 1BF52
A
Hello World.
0000008DB1B7F644
// 使用字符宽度和标志
#include <stdio.h>
int main(void)
{
char str[] = "Ciallo~";
int a = 87;
int b = -87;
int c = 114514;
float d = 10;
printf("★%-10s★\n", str);
printf("★%+10d★\n", a);
printf("★%+10d★\n", b);
printf("★% -10d★\n", a);
printf("★% -10d★\n", b);
printf("★%#10o★\n", c);
printf("★%#10x★\n", c);
printf("★%#10X★\n", c);
printf("★%10.0f★\n", d);
printf("★%#10.0f★\n", d);
printf("★%010d★", a);
return 0;
}输出为:
★Ciallo~ ★
★ +87★
★ -87★
★ 87 ★
★-87 ★
★ 0337522★
★ 0x1bf52★
★ 0X1BF52★
★ 10★
★ 10.★
★0000000087★
// 使用数据精度
#include <stdio.h>
int main(void)
{
short a = 10;
unsigned short b = 65535;
signed char c = -128;
double d = 3.1415926;
double e = 12345.678;
double f = 0.0000000123;
double g = 1000000000000000.0;
printf("%.5d\n", a);
printf("%.3d\n", b);
printf("%.5d\n", c);
printf("%.3f\n", d);
printf("%.10f\n", d);
printf("%.3G\n", d);
printf("%.5g\n", e);
printf("%.5G\n", f);
printf("%.6g", g);
return 0;
}输出为
00010
65535
-00128
3.142
3.1415926000
3.14
12346
1.23E-08
1e+15
// 使用长度修饰符
#include <stdio.h>
int main(void)
{
short a = 10;
unsigned short b = 65535;
signed char c = -128;
unsigned char d = 255;
long e = 2147483647;
unsigned long f = 4294967294;
long long g = 9223372036854775806;
unsigned long long h = 18446744073709551615;
long double i = 3.14159265358979;
printf("%hd\n", a);
printf("%hu\n", b);
printf("%hhd\n", c);
printf("%hhu\n", d);
printf("%ld\n", e);
printf("%lu\n", f);
printf("%lld\n", g);
printf("%llu\n", h);
printf("%.15Lf\n", i);
printf("%zd\n", sizeof h);
printf("%td", &b - &a);
return 0;
}输出为:
10
65535
-128
255
2147483647
4294967294
9223372036854775806
18446744073709551615
3.141592653589790
8
16
接下来玩点花的:
// 大杂烩
#include <stdio.h>
int main(void)
{
long double a = 3.1415926535;
unsigned long long b = 219845122340;
printf("★%+*.*llu★\n", 20, 15, b);
printf("★% #020.0Lf★\n", a);
printf("%%"); // 直接打印百分号
return 0;
}输出为:
★ 000219845122340★
★ 000000000000000003.★
%
scanf()函数
scanf()作为处理输入的函数,其转换说明由转换说明符、抑制赋值标志、字符宽度和长度修饰符组成。scanf()函数所用的转换说明与printf()函数几乎相同,但对浮点类型和符号的处理略有差异。
转换说明符
| 转换说明符 | 含义 |
d | 把输入解释为有符号十进制整数,i与其等价。单独使用时地址参数对应的类型应为int。 |
u | 把输入解释为无符号十进制整数。单独使用时地址参数对应的类型应为unsigned int。 |
f,e,a,g | 把输入解释为浮点数。单独使用时地址参数对应的类型应为float。 |
o | 把输入解释为有符号八进制整数。单独使用时地址参数对应的类型应为int。 |
x | 把输入解释为有符号十六进制整数。若改为X则适用于输入数字中的字母为大写的情形。单独使用时地址参数对应的类型应为int。 |
c | 把输入解释为一个字符,不会忽略空白字符。地址参数对应的类型应为char。 |
s | 把输入解释为字符串,遇到空白字符即停止。参数应为指向数组的指针。 |
p | 把输入解释为指针地址。参数应为一个指针的地址。 |
抑制赋值
由*表示,放在%后,若使用此标志,则会在读取输入时跳过对应的内容。
// 使用抑制赋值标志
#include <stdio.h>
int main(void)
{
int a;
scanf("%*d %*d %d", a);
return 0;
}可接受如下输入:
10 12 15
a会被赋值为15。
字符宽度
一个数字,位于长度修饰符前,表示输入的最大字符宽度。对输入的读取会在达到此宽度或遇到空白字符时停止。
长度修饰符
位于字符宽度之后,转换说明符之前。
| 长度修饰符 | 含义 |
h | 表示short或unsigned short类型。适用于所有整数转换说明符。 |
hh | 表示signed char或unsigned char类型。适用于所有整数转换说明符。 |
l | 用于整数转换说明符时表示long或unsigned long,用于浮点转换说明符时表示double。 |
ll | 表示long long或unsigned long long。适用于所有整数转换说明符。 |
L | 表示long double。适用于所有浮点转换说明符。 |
z | 表示size_t(sizeof运算符返回)。 |
t | 表示ptrdiff_t(指针相减返回)。 |