C语言常用打印格式

一、基本格式说明符

1. 整数类型

格式符 说明 示例代码 输出结果
%d 有符号十进制整数 printf("%d", 123) 123
%i 有符号十进制整数(同%d) printf("%i", 123) 123
%u 无符号十进制整数 printf("%u", 123) 123
%o 无符号八进制整数 printf("%o", 8) 10
%x 无符号十六进制(小写) printf("%x", 255) ff
%X 无符号十六进制(大写) printf("%X", 255) FF

长度修饰符:

short s = 100;
int i = 100;
long l = 100L;
long long ll = 100LL;

printf("%hd\n", s);      // short: 100
printf("%d\n", i);       // int: 100
printf("%ld\n", l);      // long: 100
printf("%lld\n", ll);    // long long: 100

// 无符号版本
unsigned int ui = 100;
unsigned long ul = 100UL;
printf("%u\n", ui);      // unsigned int: 100
printf("%lu\n", ul);     // unsigned long: 100
printf("%llu\n", ull);   // unsigned long long: 100

2. 浮点数类型

格式符 说明 示例代码 输出结果
%f 浮点数(默认6位小数) printf("%f", 3.14159) 3.141590
%lf double类型(同%f) printf("%lf", 3.14) 3.140000
%Lf long double printf("%Lf", 3.14L) 3.140000
%e 科学计数法(小写e) printf("%e", 1234.5) 1.234500e+03
%E 科学计数法(大写E) printf("%E", 1234.5) 1.234500E+03
%g 自动选择%f或%e printf("%g", 1234.5) 1234.5
%G 自动选择%f或%E printf("%G", 1234.5) 1234.5
float f = 3.14159f;
double d = 3.14159;
long double ld = 3.14159L;

printf("%f\n", f);       // 3.141590
printf("%lf\n", d);      // 3.141590
printf("%Lf\n", ld);     // 3.141590

// 控制小数位数
printf("%.2f\n", 3.14159);   // 3.14
printf("%.10f\n", 3.14159);  // 3.1415900000

3. 字符和字符串

格式符 说明 示例代码 输出结果
%c 单个字符 printf("%c", 'A') A
%s 字符串 printf("%s", "Hello") Hello
%% 输出%符号 printf("%%") %
char ch = 'A';
char str[] = "Hello, World!";

printf("%c\n", ch);              // A
printf("%s\n", str);             // Hello, World!
printf("%%d means integer\n");  // %d means integer

4. 指针

格式符 说明 示例代码 输出结果
%p 指针地址(十六进制) printf("%p", ptr) 0x7fff5fbff8a0
int num = 10;
int *ptr = #

printf("地址: %p\n", (void*)ptr);      // 0x7fff5fbff8a0
printf("地址: %p\n", (void*)&num);     // 0x7fff5fbff8a0
printf("值: %d\n", *ptr);              // 10

5. 特殊格式符

格式符 说明 示例代码 输出结果
%n 已输出字符数写入变量 见下方示例 -
int count;
printf("Hello%n World\n", &count);
printf("已输出 %d 个字符\n", count);  // 已输出 5 个字符

二、格式控制标志

完整格式:%[flags][width][.precision][length]specifier

1. 标志(flags)

标志 说明 示例 输出
- 左对齐 printf("%-5d", 10) 10
+ 显示正负号 printf("%+d", 10) +10
(空格) 正数前加空格 printf("% d", 10) 10
0 用0填充 printf("%05d", 10) 00010
# 添加前缀 printf("%#x", 16) 0x10

详细示例:

int num = 42;
int neg = -42;

// 左对齐 vs 右对齐(默认)
printf("[%5d]\n", num);     // [   42]
printf("[%-5d]\n", num);    // [42   ]

// 正负号
printf("%+d\n", num);       // +42
printf("%+d\n", neg);       // -42
printf("% d\n", num);       // 42(前面有空格)
printf("% d\n", neg);       // -42

// 0填充
printf("%05d\n", num);      // 00042
printf("%05d\n", neg);      // -0042

// #前缀
printf("%#x\n", 16);        // 0x10
printf("%#X\n", 16);        // 0X10
printf("%#o\n", 8);         // 010
printf("%#.2f\n", 3.0);     // 3.00(保留小数点)

2. 宽度(width)

指定输出的最小字符数,不够用空格填充。

printf("%5d\n", 42);        // "   42"
printf("%10s\n", "Hello");  // "     Hello"
printf("%*d\n", 5, 42);     // "   42"(宽度由参数指定)

// 组合使用
printf("%05d\n", 42);       // "00042"(0填充)
printf("%-5d\n", 42);       // "42   "(左对齐)

3. 精度(.precision)

类型 精度含义 示例 输出
浮点数 小数位数 printf("%.2f", 3.14159) 3.14
字符串 最大字符数 printf("%.5s", "HelloWorld") Hello
整数 最小位数(0填充) printf("%.5d", 42) 00042
// 浮点数精度
printf("%.2f\n", 3.14159);     // 3.14
printf("%.0f\n", 3.14159);     // 3(四舍五入)
printf("%.*f\n", 3, 3.14159);  // 3.142(精度由参数指定)

// 字符串精度
printf("%.5s\n", "Hello World");  // Hello

// 整数精度
printf("%.5d\n", 42);          // 00042
printf("%5.3d\n", 42);         // "  042"(宽度5,精度3)

4. 组合使用示例

int num = 123;
float pi = 3.14159;
char *str = "Hello";

// 宽度 + 精度
printf("%8.2f\n", pi);         // "    3.14"
printf("%8.3f\n", pi);         // "   3.142"

// 标志 + 宽度 + 精度
printf("%+8.2f\n", pi);        // "   +3.14"
printf("%-8.2f\n", pi);        // "3.14    "
printf("%08.2f\n", pi);        // "00003.14"

// 字符串格式化
printf("%10s\n", str);         // "     Hello"
printf("%-10s\n", str);        // "Hello     "
printf("%.3s\n", str);         // "Hel"
printf("%10.3s\n", str);       // "       Hel"

三、长度修饰符

修饰符 说明 适用类型 示例
hh char d, i, o, u, x, X printf("%hhd", c)
h short d, i, o, u, x, X printf("%hd", s)
l long d, i, o, u, x, X printf("%ld", l)
ll long long d, i, o, u, x, X printf("%lld", ll)
L long double f, e, g printf("%Lf", ld)
z size_t d, i, o, u, x, X printf("%zu", size)
t ptrdiff_t d, i, o, u, x, X printf("%td", diff)

完整示例:

char c = 127;
short s = 32767;
int i = 2147483647;
long l = 2147483647L;
long long ll = 9223372036854775807LL;
size_t sz = sizeof(int);
ptrdiff_t pd = &arr[5] - &arr[0];

printf("char: %hhd\n", c);
printf("short: %hd\n", s);
printf("int: %d\n", i);
printf("long: %ld\n", l);
printf("long long: %lld\n", ll);
printf("size_t: %zu\n", sz);
printf("ptrdiff_t: %td\n", pd);

// 无符号版本
unsigned char uc = 255;
unsigned short us = 65535;
printf("unsigned char: %hhu\n", uc);
printf("unsigned short: %hu\n", us);

四、常见数据类型打印

1. 标准整数类型(stdint.h)

#include <stdint.h>
#include <inttypes.h>

int8_t i8 = 127;
int16_t i16 = 32767;
int32_t i32 = 2147483647;
int64_t i64 = 9223372036854775807LL;

uint8_t u8 = 255;
uint16_t u16 = 65535;
uint32_t u32 = 4294967295U;
uint64_t u64 = 18446744073709551615ULL;

// 使用PRId宏(推荐)
printf("int8_t: %" PRId8 "\n", i8);
printf("int16_t: %" PRId16 "\n", i16);
printf("int32_t: %" PRId32 "\n", i32);
printf("int64_t: %" PRId64 "\n", i64);

printf("uint32_t: %" PRIu32 "\n", u32);
printf("uint64_t: %" PRIu64 "\n", u64);

// 十六进制
printf("hex: 0x%" PRIx32 "\n", u32);
printf("HEX: 0x%" PRIX64 "\n", u64);

2. 指针和地址

int num = 42;
int *ptr = #
void *vptr = #

printf("指针地址: %p\n", (void*)ptr);
printf("指针地址: %p\n", vptr);
printf("变量地址: %p\n", (void*)&num);
printf("指针大小: %zu bytes\n", sizeof(ptr));

// 指针运算
printf("ptr+1 地址: %p\n", (void*)(ptr + 1));
printf("地址差: %td\n", (ptr + 1) - ptr);

3. 数组和字符串

int arr[] = {1, 2, 3, 4, 5};
char str[] = "Hello, World!";

// 打印数组
printf("数组: ");
for (int i = 0; i < 5; i++) {
    printf("%d ", arr[i]);
}
printf("\n");

// 打印字符串
printf("字符串: %s\n", str);
printf("前5个字符: %.5s\n", str);
printf("字符串长度: %zu\n", strlen(str));

// 打印字符串地址
printf("字符串地址: %p\n", (void*)str);
printf("首字符: %c\n", str[0]);

4. 结构体

struct Point {
    int x;
    int y;
};

struct Point p = {10, 20};

printf("Point: (%d, %d)\n", p.x, p.y);
printf("结构体大小: %zu bytes\n", sizeof(struct Point));
printf("结构体地址: %p\n", (void*)&p);
printf("成员x地址: %p\n", (void*)&p.x);
printf("成员y地址: %p\n", (void*)&p.y);

五、特殊场景格式化

1. 二进制输出(自定义实现)

void print_binary(unsigned int n) {
    for (int i = 31; i >= 0; i--) {
        printf("%d", (n >> i) & 1);
        if (i % 8 == 0) printf(" ");
    }
    printf("\n");
}

int main() {
    unsigned int num = 42;
    printf("十进制: %u\n", num);
    printf("十六进制: 0x%x\n", num);
    printf("八进制: 0%o\n", num);
    printf("二进制: ");
    print_binary(num);
  
    return 0;
}
// 输出:
// 十进制: 42
// 十六进制: 0x2a
// 八进制: 052
// 二进制: 00000000 00000000 00000000 00101010

2. 对齐和表格输出

// 表格输出
printf("%-10s %-8s %-6s\n", "Name", "Age", "Score");
printf("%-10s %-8d %-6.1f\n", "Alice", 20, 95.5);
printf("%-10s %-8d %-6.1f\n", "Bob", 22, 87.3);
printf("%-10s %-8d %-6.1f\n", "Charlie", 21, 92.8);

// 输出:
// Name       Age      Score 
// Alice      20       95.5  
// Bob        22       87.3  
// Charlie    21       92.8  

// 右对齐数字
printf("%10s %8s %6s\n", "Name", "Age", "Score");
printf("%-10s %8d %6.1f\n", "Alice", 20, 95.5);
printf("%-10s %8d %6.1f\n", "Bob", 22, 87.3);

3. 货币格式化

double price = 1234.56;

printf("价格: $%.2f\n", price);              // $1234.56
printf("价格: $%,.2f\n", price);             // $1,234.56(需要locale支持)
printf("价格: $%8.2f\n", price);             // $ 1234.56
printf("价格: $%08.2f\n", price);            // $01234.56

// 千位分隔符(需要设置locale)
#include <locale.h>
setlocale(LC_NUMERIC, "");
printf("价格: %'.2f\n", price);              // 1,234.56

4. 时间格式化

#include <time.h>

time_t now = time(NULL);
struct tm *t = localtime(&now);

printf("年: %04d\n", t->tm_year + 1900);
printf("月: %02d\n", t->tm_mon + 1);
printf("日: %02d\n", t->tm_mday);
printf("时: %02d\n", t->tm_hour);
printf("分: %02d\n", t->tm_min);
printf("秒: %02d\n", t->tm_sec);

printf("日期: %04d-%02d-%02d\n", 
       t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
printf("时间: %02d:%02d:%02d\n", 
       t->tm_hour, t->tm_min, t->tm_sec);

// 使用strftime
char buf[100];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", t);
printf("时间戳: %s\n", buf);

5. 进度条

void print_progress(int current, int total) {
    int width = 50;
    int progress = (current * width) / total;
  
    printf("\r[");
    for (int i = 0; i < width; i++) {
        if (i < progress) printf("=");
        else if (i == progress) printf(">");
        else printf(" ");
    }
    printf("] %3d%%", (current * 100) / total);
    fflush(stdout);
}

// 使用示例
for (int i = 0; i <= 100; i++) {
    print_progress(i, 100);
    usleep(50000);  // 模拟工作
}
printf("\n");

六、sprintf和snprintf

1. sprintf - 格式化到字符串

char buffer[100];

// 基本使用
int n = sprintf(buffer, "Number: %d", 42);
printf("输出: %s\n", buffer);        // 输出: Number: 42
printf("写入字符数: %d\n", n);       // 写入字符数: 10

// 组合多个值
sprintf(buffer, "%s: %d, %s: %.2f", "Age", 25, "Score", 95.5);
printf("%s\n", buffer);              // Age: 25, Score: 95.50

// 危险:可能缓冲区溢出!
sprintf(buffer, "%s", very_long_string);  // ⚠️ 不安全

2. snprintf - 安全的格式化

char buffer[20];

// 限制大小,防止溢出
int n = snprintf(buffer, sizeof(buffer), "Number: %d", 12345678);
printf("输出: %s\n", buffer);        // 输出: Number: 12345678
printf("需要字符数: %d\n", n);       // 需要字符数: 17(可能被截断)

// 检查是否截断
if (n >= sizeof(buffer)) {
    printf("警告: 输出被截断!\n");
}

// 安全实践
snprintf(buffer, sizeof(buffer), "%.10s", long_string);

七、常见错误和注意事项

1. 类型不匹配

// ❌ 错误:类型不匹配
int num = 42;
printf("%f", num);           // 未定义行为!

long l = 100L;
printf("%d", l);             // 可能输出错误!

// ✅ 正确
printf("%d", num);
printf("%ld", l);
printf("%f", (double)num);   // 显式转换

2. 指针格式化

int *ptr = NULL;

// ❌ 错误
printf("%d", ptr);           // 未定义行为!

// ✅ 正确
printf("%p", (void*)ptr);    // (nil) 或 0x0

// 打印指针指向的值
if (ptr != NULL) {
    printf("值: %d\n", *ptr);
}

3. 字符串安全

char *str = NULL;

// ❌ 危险
printf("%s", str);           // 段错误!

// ✅ 安全
if (str != NULL) {
    printf("%s", str);
}
printf("%s", str ? str : "(null)");

4. 浮点数精度

float f = 0.1f;
double d = 0.1;

// 注意精度问题
printf("%.20f\n", f);        // 0.10000000149011611938
printf("%.20lf\n", d);       // 0.10000000000000000555

// 比较浮点数
if (fabs(f - 0.1) < 1e-6) {  // 使用epsilon
    printf("接近相等\n");
}

八、快速参考表

printf格式速查

// 整数
%d, %i          // 有符号十进制
%u              // 无符号十进制
%o              // 八进制
%x, %X          // 十六进制
%ld             // long
%lld            // long long
%zu             // size_t

// 浮点数
%f              // 浮点数
%lf             // double
%Lf             // long double
%e, %E          // 科学计数法
%g, %G          // 自动选择

// 字符和字符串
%c              // 字符
%s              // 字符串
%p              // 指针

// 标志
%-              // 左对齐
%+              // 显示符号
%0              // 0填充
%#              // 添加前缀
% (空格)        // 正数前加空格

// 宽度和精度
%5d             // 宽度5
%.2f            // 2位小数
%5.2f           // 宽度5,2位小数
%*.*f           // 动态指定

完整示例程序

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main() {
    // 整数
    printf("整数: %d, %i, %u\n", 42, -42, 42);
    printf("八进制: %o, 十六进制: %x, %X\n", 10, 255, 255);
  
    // 浮点数
    printf("浮点数: %f, %.2f\n", 3.14159, 3.14159);
    printf("科学计数: %e, %E\n", 1234.5, 1234.5);
  
    // 字符串
    printf("字符: %c, 字符串: %s\n", 'A', "Hello");
    printf("截断: %.5s\n", "Hello World");
  
    // 指针
    int num = 42;
    printf("地址: %p, 值: %d\n", (void*)&num, num);
  
    // 格式化
    printf("右对齐: [%5d]\n", 42);
    printf("左对齐: [%-5d]\n", 42);
    printf("0填充: [%05d]\n", 42);
    printf("符号: [%+d] [% d]\n", 42, 42);
  
    // 精度
    printf("精度: [%8.2f] [%8.4f]\n", 3.14159, 3.14159);
  
    return 0;
}

OK,以上就是c语言中的打印格式和使用方法,常规使用没问题。