1. printf()
基本语法
int printf(const char* format, ...);
- 参数:
format
:格式字符串,包含普通字符(按原样输出)和格式说明符(以%
开头)。...
:可变参数列表,与格式说明符对应。
- 返回值:
- 成功:返回输出的字符数(不含末尾
\0
)。 - 失败:返回负值。
- 成功:返回输出的字符数(不含末尾
2. 格式说明符
格式说明符以 %
开头,用于指定输出数据的类型和格式。以下是常用格式说明符及其描述:
说明符 | 数据类型 | 描述 | 示例 | 输出 |
---|---|---|---|---|
%d | int | 有符号十进制整数 | printf("%d", 42); | 42 |
%i | int | 有符号十进制整数(与 %d 相同) | printf("%i", 42); | 42 |
%u | unsigned int | 无符号十进制整数 | printf("%u", 42); | 42 |
%o | int | 无符号八进制整数 | printf("%o", 8); | 10 |
%x / %X | int | 无符号十六进制整数(小写/大写) | printf("%x", 255); | ff |
%f | float / double | 浮点数(默认 6 位小数) | printf("%f", 3.14159); | 3.141590 |
%e / %E | float / double | 指数形式浮点数(小写/大写) | printf("%e", 3.14159); | 3.141590e+00 |
%g / %G | float / double | 自动选择 %f 或 %e (较短形式,不显示无意义零) | printf("%g", 0.0000123); | 1.23e-05 |
%c | char | 单个字符 | printf("%c", 'A'); | A |
%s | char* | 字符串(以 \0 结尾) | printf("%s", "hello"); | hello |
%p | void* | 指针地址(十六进制) | int x; printf("%p", &x); | 0x7ffee... |
%a / %A | double (C99) | 十六进制浮点数(p/P 记数法) | printf("%a", 3.14159); | 0x1.921f...p+1 |
%% | 无 | 输出百分号 % | printf("%%"); | % |
%n | int* | 将已输出的字符数存储到变量 | int len; printf("hi%n", &len); | hi(len=2 ) |
3. 格式说明符的完整格式
格式说明符的完整结构为:
%[标志][宽度][.精度][长度]类型
3.1 标志(Flags)
标志控制输出对齐、符号显示等行为。
标志 | 描述 | 示例 | 输出 |
---|---|---|---|
- | 左对齐(默认右对齐) | printf("%-10d", 42); | 42 |
+ | 强制显示正负号(正数加 + ) | printf("%+d", 42); | +42 |
正数前加空格,负数显示 - | printf("% d", 42); | 42 | |
0 | 用 0 填充(仅数字) | printf("%05d", 42); | 00042 |
# | 特定格式: | ||
- %o :加前缀 0 | printf("%#o", 8); | 010 | |
- %x / %X :加前缀 0x / 0X | printf("%#x", 255); | 0xff | |
- %e / %f / %g :强制显示小数点 | printf("%#g", 5.0); | 5.00000 |
3.2 宽度(Width)
- 功能:指定字段最小宽度,宽度不足时填充(默认空格)。
- 用法:
- 用十进制正整数表示,如
%10d
。 - 动态宽度:用
*
占位,由参数指定。
- 用十进制正整数表示,如
- 示例:
printf("%10d", 42); // 输出: 42(右对齐) printf("%-10d", 42); // 输出: 42 (左对齐) printf("%*d", 5, 42); // 输出: 42(动态宽度)
3.3 精度(Precision)
- 功能:控制数字或字符串的显示精度。
- 浮点数:小数点后位数。
- 字符串:最大输出字符数。
- 整数:至少输出的数字位数(不足补 0)。
- 用法:以
.
开头,后接十进制正整数,如%.2f
。 - 示例:
printf("%.2f", 3.14159); // 输出: 3.14(保留 2 位小数) printf("%.3s", "hello"); // 输出: hel(只输出前 3 个字符) printf("%5.3d", 42); // 输出: 042(至少 3 位数字) printf("%.*s", 3, "hello"); // 输出: hel(动态精度)
3.4 长度修饰符(Length Modifier)
修饰符 | 数据类型 | 示例 | 输出 |
---|---|---|---|
h | short | printf("%hd", (short)123); | 123 |
l | long | printf("%ld", 123L); | 123 |
ll | long long | printf("%lld", 123LL); | 123 |
L | long double | printf("%Lf", 3.14L); | 3.140000 |
注意:原文中的 F
和 N
(远/近指针)已过时,现代 C 中不常用。
4. 格式说明符的详细用法
4.1 整数类型
- **
%d
/%i
**:有符号十进制整数。%md
:指定宽度m
,不足补空格,超长按实际输出。%ld
:长整型。
printf("%5d", 42); // 输出: 42 printf("%05d", 42); // 输出: 00042
- **
%u
**:无符号十进制整数。%lu
:长无符号整型。
- **
%o
**:无符号八进制整数。%#o
:加前缀0
。
printf("%o", 8); // 输出: 10 printf("%#o", 8); // 输出: 010
- **
%x
/%X
**:无符号十六进制整数。%#x
:加前缀0x
。
int a = -1; printf("%d, %x", a, a); // 输出: -1, ffffffff(补码形式)
4.2 浮点数类型
- **
%f
**:小数形式输出浮点数。- 默认:6 位小数。
%m.nf
:宽度m
,小数位n
。
printf("%f", 3.14159); // 输出: 3.141590 printf("%8.2f", 3.14159); // 输出: 3.14
- **
%e
/%E
**:指数形式输出。%m.ne
:宽度m
,小数位n
。
printf("%e", 1234.567); // 输出: 1.234567e+03
- **
%g
/%G
**:选择%f
或%e
中较短形式,不显示无意义零。printf("%g", 0.0000123); // 输出: 1.23e-05 printf("%#g", 5.0); // 输出: 5.00000(强制小数点)
- **
%a
/%A
**(C99):十六进制浮点数(p/P 记数法)。printf("%a", 3.14159); // 输出: 0x1.921f...p+1
注意:
- 单精度(
float
):%f
输出前 7 位有效数字,默认 6 位小数。 - 双精度(
double
):%lf
输出前 16 位有效数字,默认 6 位小数。
4.3 字符和字符串
- **
%c
**:输出单个字符。printf("%c", 'A'); // 输出: A
- **
%s
**:输出字符串。%ms
:宽度m
,不足补空格,超长按实际输出。%-ms
:左对齐。%m.ns
:宽度m
,取前n
个字符,右对齐。
printf("%7.2s", "CHINA"); // 输出: CH printf("%-7.2s", "CHINA"); // 输出: CH
4.4 指针
- **
%p
**:输出指针地址(十六进制)。int x; printf("%p", &x); // 输出: 0x7ffee...
4.5 特殊说明符
- **
%%
**:输出百分号%
。printf("%%"); // 输出: % printf("%.2f%%", 1.0/3); // 输出: 0.33%
- **
%n
**:将已输出的字符数存储到变量(参数为int*
)。int len; printf("hello%n", &len); printf("\n长度: %d\n", len); // 输出: 5
5.动态格式控制:%*.*s
1.1 定义
-
在 printf() 中,使用 * 占位符结合外部参数动态指定输出的 宽度 和 精度。
-
格式:
-
%*s:* 表示宽度由外部参数指定。
-
%.*s:.* 表示精度(输出的字符个数)由外部参数指定。
-
%*.*s:同时指定宽度和精度。
-
1.2 用法
-
宽度:总输出长度(包括填充的空格)。
-
精度:实际输出的字符个数。
-
参数顺序:printf("%*.*s", 宽度, 精度, 字符串);
1.3 示例
char ch[20] = "hello";
int m = 10, n = 3;
printf("%*.*s\n", m, n, ch);
-
输出: hel
-
解释:
-
m = 10:总宽度为 10。
-
n = 3:输出字符串的前 3 个字符,即 "hel"。
-
总宽度 10,输出 3 个字符,前面填充 7 个空格(右对齐)。
-
1.4 好处
-
灵活性:通过外部变量 m 和 n 动态调整格式,无需修改格式字符串。
-
动态控制:适合根据用户输入或计算结果调整输出格式的场景。
1.5 注意事项
-
确保 m 和 n 是 int 类型。
-
参数值应合理,避免过大或过小导致输出异常。
2. %n 格式说明符
2.1 定义
-
%n 是一个特殊格式说明符,不输出内容,而是将 当前已输出的字符数 存储到指定的整数指针变量中。
2.2 用法
-
在格式字符串中加入 %n,并提供一个 int* 参数。
-
printf() 会将到 %n 为止已输出的字符数记录到该变量中。
2.3 示例
int slen;
printf("hello world%n", &slen);
printf("\n变量 slen 的值: %d\n", slen);
-
输出:
hello world 变量 slen 的值: 11
-
解释:
-
"hello world" 共 11 个字符(包括空格)。
-
%n 将已输出的字符数 11 存储到 slen 中。
-
2.4 好处
-
记录输出长度:无需额外计算即可获取已输出字符数。
-
应用场景:适合调试、跟踪输出进度或在复杂格式化中统计字符数。
2.5 注意事项
-
参数必须是 int* 类型(如 &slen)。
-
%n 本身不输出内容,仅记录字符数。
3. 综合示例
以下示例结合动态格式和 %n:
#include <stdio.h>
int main() {
char str[] = "dynamic format";
int width = 20;
int precision = 5;
int len;
printf("%*.*s%n\n", width, precision, str, &len);
printf("已输出字符数: %d\n", len);
return 0;
}
-
输出:
dynam 已输出字符数: 20
-
解释:
-
width = 20:总宽度为 20。
-
precision = 5:输出前 5 个字符,即 "dynam"。
-
输出结果右对齐,前面填充 15 个空格。
-
%n 记录总输出字符数(包括空格),为 20。
-
6. 宽字符支持
使用 %ls
输出宽字符字符串(wchar_t*
),需设置本地化。
- 示例:
#include <wchar.h> setlocale(LC_ALL, ""); wchar_t wstr[] = L"你好"; printf("宽字符: %ls\n", wstr); // 输出: 你好
7. 注意事项
- 类型匹配:格式说明符必须与参数类型匹配,否则可能导致未定义行为。
- 错误示例:
printf("%s", 123);
(期望字符串但传入整数)。
- 错误示例:
- 浮点数精度:
- 单精度:
%f
默认 6 位小数,前 7 位有效。 - 双精度:
%lf
默认 6 位小数,前 16 位有效。
- 单精度:
- 宽字符:需调用
setlocale(LC_ALL, "")
确保正确显示。 - 安全性:避免格式说明符与参数不匹配,确保宽度和精度合理。
8. 综合示例
以下代码展示多种格式说明符的用法:
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // 设置本地化
// 整数
printf("整数: %d\n", 42); // 输出: 42
printf("宽度: %5d\n", 42); // 输出: 42
printf("左对齐: %-5d\n", 42); // 输出: 42
printf("八进制: %#o\n", 8); // 输出: 010
// 浮点数
printf("浮点数: %.2f\n", 3.14159); // 输出: 3.14
printf("指数: %e\n", 1234.567); // 输出: 1.234567e+03
printf("自动: %g\n", 0.0000123); // 输出: 1.23e-05
// 字符串
printf("字符串: %7.2s\n", "CHINA"); // 输出: CH
printf("左对齐: %-7.2s\n", "CHINA"); // 输出: CH
// 宽字符
wchar_t wstr[] = L"你好";
printf("宽字符: %ls\n", wstr); // 输出: 你好
// 特殊
int len;
printf("hello%n\n", &len);
printf("已输出字符数: %d\n", len); // 输出: 5
return 0;
}
9. 总结
- 功能:
printf()
通过格式说明符控制输出格式,支持多种数据类型。 - 格式:
%[标志][宽度][.精度][长度]类型
,如%-5.2f
。 - 常见说明符:
%d
(整数)、%f
(浮点数)、%s
(字符串)、%p
(指针)。 - 扩展:支持动态宽度/精度(
*
)、宽字符(%ls
)、字符计数(%n
)。 - 注意:确保格式与参数匹配,避免未定义行为;宽字符需设置本地化。
这份笔记全面覆盖了 printf()
的格式化输出用法,便于学习和参考!