格式化输出字符
常用的格式化字符
C 语言中的格式化输出字符如下
| 格式字符 |
类型 |
备注 |
%[-][0][n]d |
int |
-表示左对齐,n表示输出宽度,0表示右对齐时用0补齐,左对齐时用空格补齐 |
%c |
char |
|
%[-][0][n][.n]f |
float |
.n表示小数位位数,其余同int |
%[-][0][n][.n]s |
char[] |
.n表示从左开始取n位,其余同int |
%hd |
short |
|
%[#]o |
八进制整型 |
# 表示显示八进制前面的0 |
%[#]x |
十六进制整型 |
# 表示显示八进制前面的0x |
%hu |
unsigned short |
|
%ld/%Ld |
long |
|
%lld/%LLd |
long long |
|
%u |
unsigned int |
|
%ul/lu/UL/LU |
unsigned long int |
|
%ull/llu/ULL/LLU |
unsigned long long int |
|
%lf |
double |
参数同上 |
%e |
科学计数法 |
如1e2=1*10^2,2e-2=2*10^(-2),0.5E+3=0.5*10^(3) |
%g |
自动判断使用f还是e |
|
%p |
point |
|
%% |
|
输出% |
*修饰符
以格式化输出整数为例,如果想要动态地控制输出的整数的宽度,需要用到* 修饰符
1 2 3 4 5
| int width = 6, precision = 2, n = 1; float f = 3.1415926; printf("######\n"); printf("%0*d\n", width, n); printf("%*.*f", width, precision, f);
|
输出如下
转义字符
常用的转义字符
一般的转义字符
| 转义序列 |
作用 |
\n |
换行 |
\t |
水平制表符 |
\\ |
反斜杠 |
\' |
单引号 |
\" |
双引号 |
\r |
光标回到当前行行首 |
\b |
退格 |
一些案例
1. 用户交互
使用\b实现在横线上输入
1 2 3
| int num; printf("输入一个两位数:__\b\b"); scanf("%d", &num);
|
2.打印进度条
利用\r回到行首不断更新进度条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #include <unistd.h>
int main() { int total = 50; printf("开始下载...\n");
for (int i = 0; i <= total; i++) { printf("\r[");
for (int j = 0; j < i; j++) printf("="); for (int j = 0; j < total - i; j++) printf(" ");
printf("] %d%%", i * 2);
fflush(stdout);
usleep(50000); } printf("\e[0m");
printf("\n下载完成!\n"); return 0; }
|
编码相关
| 转义序列 |
作用 |
例子 |
\xhh |
给定一个十六进制数,输出 ASCII 码表中其对应的字符 |
\x41对应字符 A |
\ooo |
给定一个八进制数,输出 ASCII 码表中其对应的字符 |
\101对应字符 A |
\uNNNN |
输出对应 Unicode 表中对应的字符 参考 Wikipedia |
\u4f60 对应汉字 你 |
ANSI 转义序列
ANSI 转义序列(ANSI Escape Sequences)是一系列以ESC(ASCII 码 27,即 \033 或 \x1B) 开头的控制字符序列
所有的 ANSI 转义序列都始于一个特殊的字符:ESC(Escape,转义字符)。在编程语言中,它通常被表示为 \e (PHP, Bash) 或八进制的 \033 (Python, C/C++),其 ASCII 码为 27
我们常用的 ANSI 转义序列都是 CSI 序列,CSI 序列由ESC[、若干个(包括 0 个)参数字节、中间字节、最终字节组成,各部分字节的范围如下
| 组成部分 |
字符范围 |
ASCII |
| 参数字节 |
0x30-0x3F |
0-9:;< = >? |
| 中间字节 |
0x20-0x2F |
空格、!"#$%&'()*+,-./ |
| 最终字节 |
0x40-0x7E |
@A-Z[\]^\_a-z{|}~ |
控制颜色
用案例引入
1 2
| printf("\e[30;47m这是黑字白底。\e[0m\n"); printf("\e[1;34m这是粗体蓝色的文字。\e[0m\n");
|
在第一条语句中\e[表示启动 CSI 转义,30(参数字节)表示设置字体为黑色,47(参数字节)表示设置白底,m(最终字节)表示处理颜色,\e[0m中0表示重置所有状态第二条语句中,1表示粗体,34表示蓝色
样式参数
-
1:粗体/高亮
-
2:减弱
-
3:斜体
-
4:下划线
-
7:反向显示
常用的颜色参数如下

控制光标
比如可以实现一个加载动画(旋转)的效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <stdio.h> #include <unistd.h>
int main() { const char *spin = "|/-\\"; printf("\033[?25l");
for (int i = 0; i < 20; i++) { printf("\r正在加载 %c ", spin[i % 4]); fflush(stdout); usleep(100000); }
printf("\r加载完成! \n"); printf("\033[?25h"); return 0; }
|
清屏与清行
综合运用
1. 进阶进度条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <stdio.h> #include <unistd.h>
int main() { int total = 50;
printf("\033[?25l"); printf("正在同步数据...\n");
for (int i = 0; i <= total; i++) { float percentage = (float)i / total * 100;
printf("\r\033[K");
if (i < 20) printf("\033[31m"); else if (i < 40) printf("\033[33m"); else printf("\033[32m");
printf("["); for (int j = 0; j < i; j++) printf("█"); for (int j = 0; j < total - i; j++) printf(" "); printf("] %.1f%%", percentage);
fflush(stdout); usleep(50000); }
printf("\n\033[32m✔ 同步完成!\033[0m\n"); printf("\033[?25h"); printf("\033[0m");
return 0; }
|
2. 终端弹球游戏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <stdio.h> #include <unistd.h>
##define TRAIL_SIZE 5
int main() { const int width = 50, height = 15; int x = 1, y = 1, dx = 1, dy = 1;
int history_x[TRAIL_SIZE] = {0}; int history_y[TRAIL_SIZE] = {0};
printf("\033[?25l\033[2J");
for (int frame = 0; frame < 300; frame++) { if (history_x[TRAIL_SIZE - 1] != 0) printf("\033[%d;%dH ", history_y[TRAIL_SIZE - 1], history_x[TRAIL_SIZE - 1]);
for (int i = TRAIL_SIZE - 1; i > 0; i--) { history_x[i] = history_x[i - 1]; history_y[i] = history_y[i - 1]; } history_x[0] = x; history_y[0] = y;
x += dx; y += dy; if (x <= 1 || x >= width) dx = -dx; if (y <= 1 || y >= height) dy = -dy;
int colors[TRAIL_SIZE] = {250, 245, 240, 236, 233}; for (int i = 0; i < TRAIL_SIZE; i++) { if (history_x[i] != 0) { printf("\033[%d;%dH\033[38;5;%dm·", history_y[i], history_x[i], colors[i]); } }
printf("\033[%d;%dH\033[1;37mO\033[0m", y, x);
fflush(stdout); usleep(40000); }
printf("\033[%d;1H\033[?25h游戏结束!\n", height + 1); return 0; }
|
参考链接