今天我们来简单地讲述一下C中的/r/n字符与缓冲区的概念
/r/n
/r:回车
/n:换行
下面从一段简单地C程序来介绍:
#include <stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
#include <stdio.h>
int main()
{
printf("Hello world\r");
return 0;
}
当带有/n的代码执行结束之后就得到 :
当执行带有/r的代码,得到的结果如下:
当我们什么都不带的时候,我们就会得到如下的代码:
为什么会没有打印出来数据呢,就是因为我们使用了 /r 这个字符,它将光标直接回到了最开始。
为了更好地理解这个问题我们来讲述一下第二个话题缓冲区
缓冲区
我们对代码进行如下的修改,让其在printf函数之后停滞3秒,然后在继续执行:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("Hello world\n");
sleep(3);
return 0;
}
#include <stdio.h>
int main()
{
printf("Hello world\r");
sleep(3);
return 0;
}
首先是带有\n的代码执行结果:
然后是带有\r的代码执行结果:
最后是没有这两种字符的代码执行结果:
从表面上看好像是先执行的sleep,然后在执行的printf,但是我们知道C是以从上至下的顺序结构运行的,一定是先运行的printf。其中根本原因就是在sleep的3秒期间hello的这个字符串没有被刷新,被存放在了缓冲区。当我们添加了\n之后,缓冲区就会被刷新,显示器上就会显示出换行符之前的所有缓冲区存放的数据。
在printf后添加语句 fflush(stdout); 就可以刷新缓冲区。
当我们对缓冲区进行刷新之后就能够得到printf输出的结果:
还可以发现刷新完缓冲区之后,光标的位置是在最开始的。
利用/r完成的倒计时例子
int main()
{
int i = 9;
for (; i >= 0; i--)
{
printf("%d\r", i);
fflush(stdout);
sleep(1);
}
return 0;
}
利用\r的回车和刷新缓存区的功能,就可以仿照倒计时的功能。还需要注意的一点是:回车并不会删除缓冲区中的内容。例如我们的倒计时从10开始:
可以通过将printf中的%d写成%2d的形式来解决这种问题,在C中的格式是右对齐的。
进度条的例子
#define SIZE 101
#define STYLE '='
#define ARR '>'
void process()
{
const char* label = "/|\\-";
char bar[SIZE];
memset(bar, '\0', sizeof(bar));
int i = 0;
while (i <= 100)
{
printf("[%-100s][%d%%][%c]\r", bar, i, label[i%4]);
fflush(stdout);
bar[i++] = STYLE;
if (i != 100) bar[i] = ARR;
usleep(100000);
}
printf("\n");
}
利用前文所述的内容就可以在Linux的环境下编写成一个进度条的例子。
printf彩色输出
此外,讲解一个使用printf输出其他颜色的语句的方法:
控制命令
控制命令以
\033[
开头,以m
结尾,而中间则是属性码,属性代码之间使用;
分隔,如\033[1;34;42m
属性代码
下面给出部分属性代码:
通用格式控制:
属性代码 | 功能 |
---|---|
0 | 重置所有属性 |
1 | 高亮/加粗 |
2 | 暗淡 |
4 | 下划线 |
5 | 闪烁 |
7 | 反转 |
8 | 隐藏 |
前景色:
属性代码 | 颜色 |
---|---|
30 | 黑色 |
31 | 红色 |
32 | 绿色 |
33 | 黄色 |
34 | 蓝色 |
35 | 品红 |
36 | 青色 |
背景色:
属性代码 | 颜色 |
---|---|
40 | 黑色 |
41 | 红色 |
42 | 绿色 |
43 | 黄色 |
44 | 蓝色 |
45 | 品红 |
46 | 青色 |
printf彩色输出转载自:C/C++——printf彩色输出 - LewKI - 博客园 (cnblogs.com)
进过颜色的修改我们可以得到新的进度条样式: