C 语言 printf() 格式化输出详细笔记

1. printf() 基本语法

int printf(const char* format, ...);
  • 参数
    • format:格式字符串,包含普通字符(按原样输出)和格式说明符(以 % 开头)。
    • ...:可变参数列表,与格式说明符对应。
  • 返回值
    • 成功:返回输出的字符数(不含末尾 \0)。
    • 失败:返回负值。

2. 格式说明符

格式说明符以 % 开头,用于指定输出数据的类型和格式。以下是常用格式说明符及其描述:

说明符数据类型描述示例输出
%dint有符号十进制整数printf("%d", 42);42
%iint有符号十进制整数(与 %d 相同)printf("%i", 42);42
%uunsigned int无符号十进制整数printf("%u", 42);42
%oint无符号八进制整数printf("%o", 8);10
%x / %Xint无符号十六进制整数(小写/大写)printf("%x", 255);ff
%ffloat / double浮点数(默认 6 位小数)printf("%f", 3.14159);3.141590
%e / %Efloat / double指数形式浮点数(小写/大写)printf("%e", 3.14159);3.141590e+00
%g / %Gfloat / double自动选择 %f%e(较短形式,不显示无意义零)printf("%g", 0.0000123);1.23e-05
%cchar单个字符printf("%c", 'A');A
%schar*字符串(以 \0 结尾)printf("%s", "hello");hello
%pvoid*指针地址(十六进制)int x; printf("%p", &x);0x7ffee...
%a / %Adouble (C99)十六进制浮点数(p/P 记数法)printf("%a", 3.14159);0x1.921f...p+1
%%输出百分号 %printf("%%");%
%nint*将已输出的字符数存储到变量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:加前缀 0printf("%#o", 8);010
- %x / %X:加前缀 0x / 0Xprintf("%#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)

修饰符数据类型示例输出
hshortprintf("%hd", (short)123);123
llongprintf("%ld", 123L);123
lllong longprintf("%lld", 123LL);123
Llong doubleprintf("%Lf", 3.14L);3.140000

注意:原文中的 FN(远/近指针)已过时,现代 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() 的格式化输出用法,便于学习和参考!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值