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语言中的打印格式和使用方法,常规使用没问题。