> 文章列表 > 【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

前言:本文主要讲解回车与换行的区别,理解完回车与换行的区别后,我们将带大家实现一个简单的倒计时程序,会利用到本文学习的回车与换行,做到学以致用。

文章目录

  • 一.理解回车与换行
    • (1)\\r和\\n都存在
    • (2)\\r和\\n都不存在
    • (3) 只有\\n
    • (4) 只有\\r
  • 二.简单实现倒计时程序
  • 三.实现进度条程序

一.理解回车与换行

在C语言中,涉及很多字符,一种是可显字符,另一种是控制字符。可显字符就是类似’a’‘b’等这种,控制字符就是类似’\\n’这种字符。

\\n(换行)使光标从当前行跳到下一行,但是要注意光标只是垂直往下跳,并不是像我们平常按一下Enter键,光标就直接换行并到下一行的开始。
\\r(回车)让光标回到最开始的位置。
老式键盘图:【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

测试回车与换行,观察现象:

(1)\\r和\\n都存在

现象:相当于换行,直接跳到下一行开头
代码

#include<stdio.h>
#include<unistd.h>
int main()
{printf("hello world!\\r\\n");sleep(2);return 0;
}

运行结果
【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

(2)\\r和\\n都不存在

现象:等待2秒以后,才打印hello world!
但是并不是先执行sleep再执行printf的,一定是从上往下执行。
在sleep期间,hello world!只是没有被刷新出来,被保存在了缓冲区,程序结束再刷新缓冲区打印。
代码

#include<stdio.h>
#include<unistd.h>
int main()
{printf("hello world!");sleep(2);return 0;
}

运行结果
【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

(3) 只有\\n

现象:相当于换行+回车
解释:不管加不加\\n,数据都会先被保存在缓冲区中,此处涉及缓冲区的缓冲策略:行缓冲。行缓冲——只要碰到了换行符,就会把包括换行符在内的之前的所有缓冲区内的内容刷新出来。(刷新策略还有很多,这只是其中一种)所以碰到\\n,先刷新依次缓冲区打印数据,然后等待两秒,程序结束,再打印命令行。

(4) 只有\\r

现象:睡眠2秒,然后看不到打印的信息,只输出linux命令行。
解释:\\r会返回开头,在数据存储进入缓冲区以后,等待两秒,程序要结束,先打印hello world!,打印完成后遇到\\r,光标返回这一行的开头,然后还需要打印命令行,这时命令行会把hello world!给覆盖掉,(程序结束–>缓冲区的数据就被刷新–>缓冲区刷新字符串打印出来)而由于两次打印的速度太快,看起来的结果就和没输出printf一样。
注意:没有看到"hello world",不代表它被丢弃了,只是暂时存储在缓冲区内。
代码

#include<stdio.h>
#include<unistd.h>
int main()
{printf("hello world!\\r");sleep(2);return 0;
}

运行结果
【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)
补充
这里在printf以后,用 fflush(stdout); 来刷新缓冲区先把hello world!打印出来,再sleep等待2秒结束程序,可以清晰的看见这个过程。

二.简单实现倒计时程序

#include<stdio.h>
#include<unistd.h>
int main()
{int i = 10;while(i, i >= 0, i--){printf("%2d\\r",i);//输出两位数,10以后要在第二位刷新数据,所以用%2dfflush(stdout);//刷新缓冲区sleep(1);}printf("\\n");return 0;
}

三.实现进度条程序

在当前目录下创建4个文件,如下:
【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)

//proc.h头文件
#pragma once#include<stdio.h>extern void process();   //proc.c进度条的具体实现函数
#include"proc.h"
#include<unistd.h>
#include<string.h>#define STYLE '='//进度条字符,可定义你们想要的样式
#define SIZE 102 //给'\\0',>箭头留两个位置
#define ARR '>'//进度条前面的箭头,加载完毕箭头消失void process()
{const char* lable="|/-\\\\";//选择光标char bar[SIZE];//存放进度字符的数组memset(bar,'\\0',sizeof(bar));//初始化进度条数组int i=0;while(i<=100){//打印进度条,添加背景颜色为荧光绿,还有%进度,以及旋转光标printf("[\\033[42;32;31m%-100s\\033[0m][%d%%][%c]\\r",bar,i,lable[i%4]);                                                                                                    fflush(stdout);//由于printf是以\\r结尾,所以我们需要将缓冲区的结果刷新到显示屏上bar[i++]=STYLE;//加载完毕,箭头消失if(i!=100)bar[i]=ARR;usleep(100000);}printf("\\n");}//main.c主函数,去调用进度条函数#include"proc.h"int main(){process();return 0;}//Makefile项目自动化构建工具
Processbar:main.c proc.cgcc main.c proc.c -o Processbar .PHONY:clean:rm -f Processbar  

进度条运行结果
【Linux】回车与换行的区别+简单实现倒计时和进度条(学以致用)