回车与换行的概念
其实在C语言中学的'\n'(即回车换行)其实是两个动作,即回车(回到这行的第一个位置)和换行(从末尾位置向下移动一行)。
键盘上的回车键是先向下,再向左的。
在C语言中,'\n'是回车换行,而'\r'仅仅是回车。
行缓冲区
大家可以自己编译一下下面两个代码,看看现象有什么不一样。
现象是1图先打印三秒后再休眠,2图则是休眠了三秒后,等到结束程序时,再把字符串显示了出来。
对于2图的现象我们要知道,程序并不是先执行sleep函数,再执行printf函数。程序是从上往下执行的,那么在休眠时间里字符串去哪了呢?答案是被放在了缓冲区里。
缓冲区实质上就是一块内存空间,上面的字符串就是保存在这样的一块内存空间里,当程序运行结束时,会自动刷新缓冲区里的内容到显示器上面。
那为什么1图就能直接刷新呢?这要说到刷新缓冲区的几种方法了。
- 在行尾加上'\n',立即刷新
- 等待缓冲区满或者程序结束,自动刷新
- 强制刷新(C语言提供了一个fflush函数,用于强制刷新缓冲区)

我们知道程序在运行的时候默认会打开三种流:
- 标准输入流,stdin
- 标准输出流,stdout
- 标准错误流,stderr
我们的显示器对应的就是标准输出文件,Linux下一切皆文件!
当我们使用fflush函数时,也是先打印再休眠。

有了上面的程序我们可以先来实现一个简易倒计时程序:
简易倒计时
#include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 int i=10;
6 while(i>=0)
7 {
8 printf("倒计时:%-2d\r",i);
9 fflush(stdout);
10 sleep(1);
11 i--;
12 }
13 printf("\n");
14 return 0;
进度条代码
为了方便文件的管理,我们这里采用多文件的形式去实现。
//procs.c
#include"procs.h"
#include<string.h>
#include<unistd.h>
#define style '-'
#define len 101
void procs()
{
char num[len];
memset(num,0,sizeof(num));
int cnt=0;
while(cnt <= 100)
{
printf("[%-100s][%3d%%]\r",num,cnt);
fflush(stdout);
num[cnt]=style;
cnt++;
usleep(50000);
}
printf("\n");
}
//.h
#pragma once
2 #include<stdio.h>
3 void procs();
//test.c
#include"procs.h"
2 #include<stdio.h>
3 int main()
4 {
5 procs();
6 return 0;
7 }
//makefile
1 bin=procs.exe
2 src=procs.c test.c
3 $(bin):$(src)
4 gcc -o $@ $^
5 .PHONY:clean
6 clean:
7 rm -rf $(bin)