前言:本文主要讲解回车与换行的区别,理解完回车与换行的区别后,我们将带大家实现一个简单的倒计时程序,会利用到本文学习的回车与换行,做到学以致用。
文章目录
- 一.理解回车与换行
- (1)\r和\n都存在
- (2)\r和\n都不存在
- (3) 只有\n
- (4) 只有\r
- 二.简单实现倒计时程序
- 三.实现进度条程序
一.理解回车与换行
在C语言中,涉及很多字符,一种是可显字符,另一种是控制字符。可显字符就是类似’a’‘b’等这种,控制字符就是类似’\n’这种字符。
\n(换行)
:使光标从当前行跳到下一行,但是要注意光标只是垂直往下跳,并不是像我们平常按一下Enter键,光标就直接换行并到下一行的开始。
\r(回车)
:让光标回到最开始的位置。
老式键盘图:
测试回车与换行,观察现象:
(1)\r和\n都存在
现象:相当于换行,直接跳到下一行开头
代码:
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hello world!\r\n");
sleep(2);
return 0;
}
运行结果:
(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;
}
运行结果:
(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;
}
运行结果:
补充:
这里在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以后要在第二位刷新数据,所以用%2d
fflush(stdout);//刷新缓冲区
sleep(1);
}
printf("\n");
return 0;
}
三.实现进度条程序
在当前目录下创建4个文件,如下:
//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.c
gcc main.c proc.c -o Processbar
.PHONY:
clean:
rm -f Processbar
进度条运行结果: