&&
在我们的编译器里面我们只想 进行回车的话,那么我们就是
我们之前在vs2022里面的 是回车且换行
但是今天我们的这里的 和在这个不是一个概念
其实回车换行其实是两个动作的
行缓冲区
我们第一个进行编译的时候我们加上 ,然后sleep两秒
我们编译运行可以发现我们的打印内容先出来然后进行等待两秒
但是我们将这个 去掉的话,我们发现编译的时候是等到了两秒,这个打印的内容才出来的

我们带 的话就是数据立即显示
那么我们如果不带 的话我们先执行printf还是sleep呢?
我们c语言一定是从上到下进行执行的
那么我们这里也是先执行printf也是执行sleep的
那么我们打印的数据怎么没看见呢?
那么我们这时候的数据肯定是存在缓冲区里面的
等休眠时间结束了,我们就将我们打印的显示出来
只要有缓冲区的话
那么一定存在这个刷新策略
显示器的刷新策略:行刷新!
所以如果包含 的话立即打印到显示器上
如果不包含的话改字符串不做刷新,要么程序要么结束自动刷新,要么我们进行强制刷新的操作
如果我们想让不带 的消息进行刷新的话怎么办呢?
我们可以使用命令fflush

这个命令可以直接进行强制刷新的操作
我们在代码中添加这个代码就能立即进行刷新的操作
代码语言:JavaScript代码运行次数:0运行复制
#include <stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 printf("hello kaikai"); 7 fflush(stdout);//利用这个文件流将我们的字符串立即进行刷新的操作 8 sleep(2); 9 return 0; 10 } </unistd.h></stdio.h>

然后我们运行程序我们可以发现字符串立即被打印出来了
我们现在对code.c进行编辑
我们想让结果在一行进行显示的操作
但是我们最后呈现出来的是很多行


那么怎么样让我们的光标在写完之后重新回到那一行呢?
我们可以将原来的 换成我们的 就行了
的作用是在输出完毕之后光标能够回到最开始的位置

但是我们又发现这个什么都不打印

因为我们这里后面不是 了,不会进行刷新操作的,我们打印的结果都是显示在缓冲区里面的
那么我们就进行主动刷新的操作
我们在代码的后面加上fflush(stdout);就行了
输出后我们立即进行刷新,将我们的数字显示出来
但是我们发现我们的数字一打印完就会消失了,光标一直回到开头
最后被命令行覆盖了


我们可以在代码的最后加上这个 进行换行的操作
那么这里我们就完成了一个倒计时的装置了
代码语言:javascript代码运行次数:0运行复制
#include <stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 int cnt=9; 7 while(cnt>=0) 8 { 9 printf("%d ",cnt); 10 fflush(stdout);//利用这个文件流将我们的字符串立即进行刷新的操作 11 cnt--; 12 sleep(1); 13 } 14 printf(" "); 15 // printf("hello kaikai"); 16 // fflush(stdout);//利用这个文件流将我们的字符串立即进行刷新的操作 17 // sleep(2); 18 return 0; 19 }~ </unistd.h></stdio.h>

最终效果就是到了0我们就直接进行了换行的操作了

但是我们又发现我们将这个cnt初始化为10的话我们最后打印的就是这样的
会在后面带上一个0,这是为什么呢?

其实显示器只认字符的
我们在打印的其实是以字符为单位进行打印的操作
我们第一个答应的是1和0两个字符
那么第二次的时候我们的光标回到第一个字符了
然后我们打印9
但是我们之前的字符0没有删除
所以显示的就是90
80
70
60
等等
那么我们怎么进行修改操作呢?
我们可以在我们的格式化那里进行修改的操作的
我们改变成%2d就行了

但是我们发现我们的这个空格打印的时候在左侧的,我们想让不足2位的空格在右边

那么我们怎么办?
我们是可以使用%-2d进行调整
因为我们格式化的时候,,不足位置的时候默认是右对齐的
那么我们加上-号就可以变成左对齐了
那么到这里我们就实现成功了

进度条实现
我们的Linux中的进度条通常是这样的

随着进步不断增加,我们括号中的#就会增加,右边的数字也是显示的进度
然后右边的斜杠就是我们的光标移动
我们这里声明在.h文件中,实现在.c文件中,然后我们在main.c中进行编译操作

我们将我们的Makefile文件拷贝到当前的目录中
使用命令cp ../Makefile .将上级目录中的Makefile文件拷贝到当前的文件中
那么这样我们就成功了

我们只需要将这个Makefile里面的BIN就是生成的可执行文件的名称进行改变下就行了,其他的不需要进行变化

我们然后进行正常的编译操作,输入命令make

我们在这里面引用了usleep的概念
下面的具体的使用方法
usleep 是一个 C 语言中的函数,定义在
函数原型:代码语言:javascript代码运行次数:0运行复制
int usleep(useconds_t usec);
参数: usec:延时的时间,以微秒(microseconds)为单位。1 秒 = 1,000,000 微秒。 返回值: 成功时返回 0。 如果出错(例如传入了非法参数),则返回 -1 并设置 errno。
使用场景:控制程序的执行速度: 在循环中延时一定时间,避免程序执行得过快。 常用于动画、进度条、实时更新等。 等待硬件或外部事件:等待特定硬件响应,比如 GPIO 信号稳定。减少 CPU 占用率:在多线程程序中,为线程设置短暂的休眠以释放 CPU 资源。
示例:
以下是一个简单的例子,展示如何使用 usleep 实现动态进度条:
代码语言:javascript代码运行次数:0运行复制
#include <stdio.h>#include <unistd.h> // 包含 usleep 函数int main() { printf("Loading... "); for (int i = 0; i <p>运行效果: 程序每 50 毫秒更新一次,显示动态的进度条效果。</p> <figure class=""><hr></figure>注意事项:跨平台兼容性: usleep 是 POSIX 标准的一部分,因此在 Windows 平台上可能无法使用。如果需要跨平台的延时功能,可以使用其他方法,比如: Sleep 函数(Windows 特有,单位为毫秒)。 nanosleep(更精确的 POSIX 延时函数)。 std::this_thread::sleep_for(C++11 标准库,适用于跨平台)。 延时的精度:usleep 的精度依赖于操作系统调度器。在某些情况下,实际延时可能比指定时间更长,尤其是在多任务系统中。不推荐使用(现代 POSIX):在 POSIX.1-2008 标准中,usleep 已被标记为不推荐使用(deprecated),建议使用更精确的 nanosleep 或 clock_nanosleep。<figure class=""><hr></figure>替代方法(使用 nanosleep):代码语言:javascript<i class="icon-code"></i>代码运行次数:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>运行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>复制<pre class="prism-token token line-numbers javascript">#include <stdio.h>#include <time.h>int main() { struct timespec ts; ts.tv_sec = 0; // 秒 ts.tv_nsec = 50000000; // 纳秒(50 毫秒) printf("Loading... "); for (int i = 0; i <p>这提供了更高的精度和可靠性。</p> <p>那么到这里我们就能通过下面的代码进行进度的显示了</p>代码语言:javascript<i class="icon-code"></i>代码运行次数:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>运行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>复制<pre class="prism-token token line-numbers javascript"> #include"process.h" 2 #include<string.h> 3 #include<unistd.h> 4 #define SIZE 101 5 #define STYLE '#' 6 void process() 7 { 8 //v1版本展示进度条的基本功能 9 int rate=0; 10 //定义一个缓冲区 11 char buffer[SIZE]; 12 memset(buffer,0,sizeof(buffer));//将我们的buffer初始化为0 13 while(rate<figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487237373236.jpg" alt="深度解析如何在Linux中创建自己的第一个系统程序---进度条"></figure><figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487237486419.jpg" alt="深度解析如何在Linux中创建自己的第一个系统程序---进度条"></figure><p> 但是我们这个进度条的右侧的中扩号不是固定的,而是随着#的增加而往右边进行移动的</p> <p>所以我们必须预留出足够大的空间来进行#的填充操作</p> <p>所以这个右括号不应该随着进度条的移动而移动</p> <p>我们将代码改成这样子,将位置预留出来,然后加上-号向左对齐就行了</p> <figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487237431499.jpg" alt="深度解析如何在Linux中创建自己的第一个系统程序---进度条"></figure><p> 那么最后我们代码就完成了</p> <figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487237486530.jpg" alt="深度解析如何在Linux中创建自己的第一个系统程序---进度条"></figure>代码语言:javascript<i class="icon-code"></i>代码运行次数:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" style="max-width:90%" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>运行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>复制<pre class="prism-token token line-numbers javascript"> 1 #include"process.h" 2 #include<string.h> 3 #include<unistd.h> 4 #define SIZE 101 5 #define STYLE '#' 6 void process() 7 { 8 //v1版本展示进度条的基本功能 9 int rate=0; 10 //定义一个缓冲区 11 char buffer[SIZE]; 12 memset(buffer,0,sizeof(buffer));//将我们的buffer初始化为0 13 const char*lable="|/-"; 14 int len =strlen(lable); 15 16 while(rate<p>但是这个进度条我们没办法直接进行使用的操作</p> <p>我们正常的进度条是随着这个下载的量而使这个进度条进行增加</p> <p>而不是一次性将这个进度条打完</p> <p>我们这个进度条应该是随着我们的下载的数据量进行推进的</p> <p>最后的代码就是这样的</p> <p>main.c</p>代码语言:javascript<i class="icon-code"></i>代码运行次数:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>运行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>复制<pre class="prism-token token line-numbers javascript">#include"process.h" 2 #include<unistd.h> 3 #include<time.h> 4 #include<stdlib.h> 5 //定义一个函数指针类型 6 typedef void (*call_t)(const char*,double,double);//定义了一个函数指针 的类型 7 8 double total=1024.0;//一共要下载的总量 9 //double speed=1.0;//定义一个网速 10 double speed[]={1.0,0.5,1.2,0.01,0.02};//定义一个网速清单 11 12 //下载 13 //回调函数 14 void download(int total,call_t cb) 15 { 16 srand(time(NULL)); 17 double current=0.0; 18 while(current=total) break; 23 //下载代码 24 int random=rand()%5; 25 usleep(50000); 26 27 current+=speed[random]; 28 if(current>=total) 29 { 30 current=total; 31 } 32 }//加上随机数进行动态的调整操作33 } 34 void uploadload(int total,call_t cb) 35 { 36 srand(time(NULL)); 37 double current=0.0; 38 while(current=total) break; 43 //下载代码 44 int random=rand()%5; 45 usleep(50000); 46 47 current+=speed[random]; 48 if(current>=total) 49 { 50 current=total; 51 } 52 }//加上随机数进行动态的调整操作 53 } 54 int main()E> 55 { 56 download(1024.0,FlushProcess); 57 printf("download 1024.0MB done "); 58 download(512.0,FlushProcess); 59 printf("download 512.0MB done "); 60 download(334.0,FlushProcess); 61 printf("download 334.0MB done "); 62 //process(); 63 download(64.0,FlushProcess); 64 printf("download 64.0MB done "); 65 return 0; 66 }</stdlib.h></time.h></unistd.h>
process.c
代码语言:javascript代码运行次数:0运行复制
#include"process.h" 2 #include<string.h> 3 #include<unistd.h> 4 #define SIZE 101 5 #define STYLE '#' 6 //v2:根据进度进行动态刷新一次我们的进度条 7 void FlushProcess(const char*tips,double total,double current) 8 { 9 const char*lable="|/-"; 10 int len=strlen(lable); 11 static int index=0;//只要我们调用这整个函数的话,那么我们这个光标就能> 进行转动的操作了 12 char buffer[SIZE]; 13 memset(buffer,0,sizeof(buffer));//将我们的buffer初始化为0 14 15 //int num =(int)(current*100/total);//只要满足到了1个#的话那么我们就进 行数据的刷新 16 double rate = current*100.0/total; 17 int num=(int)rate;//我们的num直接通过我们的比率进行获得 18 int i=0; 19 for(;i<num buffer printf fflush index if void process int rate="0;" char memset const len="strlen(lable);" while> 我们的当前行开始输出,rate%len就是最后显示的下标只可能是 0 1 2 3这四个数> ,可以使我们的四个字符一直进行变化的操作 48 fflush(stdout);//将我们缓冲区的消息进行刷新操作 49 buffer[rate]=STYLE; 50 rate++; 51 usleep(50000); 52 } 53 printf(" ");//让我们左侧的命令行新起一行 54 }</num></unistd.h></string.h>
process.h
代码语言:javascript代码运行次数:0运行复制
#pragma once 2 #include<stdio.h> 3 //v1版本 4 void process(); 5 6 //v2版本 7 //根据当前的量以及总量进行当前进度条的刷新操作 8 void FlushProcess(const char*tips,double total,double current); </stdio.h>