首页 > 系统相关 >【Linux学习】(8)第一个Linux编程进度条程序|git三板斧

【Linux学习】(8)第一个Linux编程进度条程序|git三板斧

时间:2024-10-28 22:17:41浏览次数:6  
标签:git 换行 进度条 三板斧 仓库 Linux 缓冲区 processbar

前言

  1. 第一个Linux编程——进度条
  2. git的简单使用

一、第一个Linux编程——进度条

在写进度条之前我们需要两个基础知识:

  1. 回车换行
  2. 缓冲区

1. 回车换行

  • 首先我们需要知道回车换行它是两个概念,回车是回车,换行是换行
  • 换行:光标从上往下,直接到下一行(例如光标现在在当前行的第5个位置,换行之后光标直接挪到下一行的第5个位置,并没有在下一行的最左侧)
    回车:把光标挪到当前行的最开始(最左侧),还在当前行
  • 换行一般不单独使用,一般换行回车一起用,所以在C语言中用\n表示换行(注意:\n是换行+回车)
  • 回车,我们用转义字符\r表示

2. 行缓冲区

(1)引入行缓冲区

在讲解之间我们先来学习一个系统函数——sleep

  • 我们通过man手册,查看sleep的使用在这里插入图片描述
  • 调用sleep,休眠指定的秒数

现在我们来看下面的两个代码:

两段代码唯一的区别就是代码1打印完之后换行,代码2打印完之后不换行,如下图:

在这里插入图片描述
分别编译运行这两段代码,运行结果是怎么样的呢?

  • 代码1:先打印hello linux!和换行,随后休眠2秒,结束运行
  • 代码2:先休眠2秒,随后打印hello linux!,结束运行

问题:我们学过C语言的都知道,C代码一定是按照顺序从上往下执行的,无论是代码1还是代码2都应该是先执行A处再执行B处,但是为什么代码2的运行效果好像是先执行了B处的代码,随后才执行的A处?

从C语言的执行顺序,我们知道一定是先执行printf,随后再执行sleep

在sleep的时候,printf已经执行了,只不过信息没有打印出来

那在我sleep的时候,信息“hello linux!”在哪里?——他一定是被保存起来了!——保存在缓冲区

缓冲区就是由C语言维护的一段内存!

缓冲区的刷新策略:行刷新

  • 行刷新:缓冲区他要看你输出的字符串是不是一个完整行
    • 如果是一个完整行,缓冲区就立刻将存在缓冲区的内容刷新出来
    • 如果不是一个完整行,缓冲区就不刷新,直到程序退出或者遇到换行符才将存在缓冲区的内容刷新出来
    • 完整行的标准:是否有‘\n’换行符

了解了缓冲区和缓冲区的刷新策略,现在我们就知道为什么代码2会先休眠再输出了,因为代码2没有‘\n’换行符,不是一个完整行,所以直到程序退出才从缓冲区刷新出来

(2)怎样强制刷新缓冲区

我们先来认识两个知识点:

  1. C程序默认会帮我们打开三个输入输出流,分别叫做标准输入、标准输出、标准错误。今天我们只考虑标准输出。

    C语言默认会帮我们打开三个输入输出文件,输出文件就是显示器,显示器文件对应C语言的stdout。
#include<stdio.h>

   extern FILE *stdin;
   extern FILE *stdout;
   extern FILE *stderr;
  1. 使用fflush刷新文件流,即使缓冲区不是一个完整行,也可以使用fflush强制将缓冲区中的内容马上刷新出来
    在这里插入图片描述

(3)倒计时

在实现进度条之前,我们可以先来实现一个简易的倒计时程序。

实现倒计时需要注意以下几个问题:

  1. 倒计时需要将之前的数字覆盖掉
    • 光标不能向后移动——》解决方案:回车‘\r’
    • 光标不能换行且要立马将缓冲区数据刷新出来——》fflush
  2. 不想让最后的结果被bash覆盖——》在程序的最后换行
  3. 从大到小倒计时,随着倒计时的运行会导致不能完全覆盖之前的数字,例如9覆盖10,反而变成90——》-numd%:左对齐num个字符
#include<stdio.h>
#include<unistd.h>

int main()
{
    int cnt = 10;
    while(cnt >= 0)
    {
     	printf("%-2d\r", cnt);
        fflush(stdout);
        sleep(1);
        cnt--;
    }
    printf("\n");

   //printf("hello linux!"); //A
   //fflush(stdout);         //强制刷新文件流,将缓冲区中的内容马上刷新出来
  //  sleep(2);                //B
    return 0;
}

3. 进度条

(1)准备工作

  1. 首先mkdir processbar创建processbar目录,用于保存进度条代码
  2. 在processbar目录下,touch processbar.c processbar.h main.c三个文件,分别用于进度条的实现、进度条的声明、进度条的调用
  3. 再touch Makefile,用于项目的自动化构建

(2)实现简单的进度条样式

  • 编写Makefile文件,通过make命令生成可执行程序和清理项目
processbar:processBar.c main.c # 可执行目标文件依赖多个源文件的话,使用空格分隔即可
	gcc $^ -o $@

.PHONY:clean
clean:
	rm -f processbar
  • processbar.h:进度条声明
//防止头文件被重复包含
#pragma once

//声明常用的头文件
#include<stdio.h>
#include<string.h>
#include<unistd.h>
//声明函数
extern void processbar(int speed);
//进度条的长度是一个常量,所以我们将其定义为一个宏
#define NUM 101//进度条长度为100,但因为C字符串以'\0'结尾,所以将其定义为101
//进度条的主体字符格式也是一个常量,所以我们也将其定义为一个宏
#define BODY '='
//进度条推进是右边有一个字符'>'表示在推进
#define RIGHT '>'
  • processbar.c:进度条样式的实现

1、如何实现进度条推进的效果

答:循环——通过每一次多输出一个字符,并将前一次输出的字符覆盖,这样不断循环,从左向右依次增加,实现进度条推进的效果

2、进度条的样式

  • 预留100的长度,并左对齐——%-100s
  • 显示进度条推进的进度,即百分比(注意‘%’是一个特殊字符,一般通过两个‘%%’才能输出)
  • 进度条工作时字符’|'顺时针旋转表示在工作
#include"processBar.h"

//进度条工作时字符'|'顺时针旋转表示在工作
const char* lable = "|/-\\"; //'\'是特殊字符
//实现进度条推进的样式,参数speed—由调用者决定每一次推进的速度
void processbar(int speed)
{
    //定义进度条
    char bar[NUM];
    //初始化进度条
    memset(bar, '\0', sizeof(bar));
    int len = strlen(lable);
    //循环:通过每一次多输出一个字符,并将前一次输出的字符覆盖,这样不断循环实现进度条推进的效果
    //进度条长度为NUM-1,从长度为0开始循环,需要循环NUM次—》[0,NUM-1]
    int cnt = 0;//计数器
    while(cnt <= NUM - 1)
    {
        //这里我们不使用'\n',使用'\r'回车将前一次的进度条覆盖掉
        printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt%len]);
        //没有'\n',缓冲区就没有立即刷新,因为显示器默认行刷新
        //所以这里我们使用fflush函数立马把缓冲区的内容刷新出来
        fflush(stdout);
        //每一次输出休眠0.1秒——usleep
        usleep(speed);
        //迭代:每一次比上一次多一个字符
         bar[cnt++] = BODY;
         //注意:临界情况,即当cnt=NUM-1时就不能再执行了
         if(cnt < NUM - 1)
         {
            bar[cnt] = RIGHT;
         }      
    }
    //进度条打印完之后,为了不让bash命令行把我们的进度条覆盖掉,所以这里换行
    printf("\n");
}

  • main.c:进度条样式的调用(测试)
#include"processBar.h"

int main()
{
    //每一次推进,休眠0.1秒
    processbar(100000);
    return 0;
}

(3)进度条调用的场景

  1. 在实际中进度条的进度不应该有我们循环模拟实现,而是由调用者决定的
  2. 在实际中进度条调用时,调用者进行着某种下载任务,每下载1%就调用进度条打印一次进度,不断重复下载,直到下载任务完成
  • processbar.c:进度条样式的实现
//进度条工作时字符'|'顺时针旋转表示在工作
const char* lable = "|/-\\"; //'\'是特殊字符
//定义进度条
char bar[NUM];
//参数rate为进度条的进度
//processbar每一次调用进度+1
void processbar(int rate)
{
    //当进度条小于0和大于100时,直接退出
    if(rate < 0 || rate > 100) return;
    int len = strlen(lable);
    printf("[%-100s][%d%%][%c]\r", bar, rate, lable[rate%len]);
    fflush(stdout);
    bar[rate++] = BODY;
    //注意:临界情况,即当rate=NUM-1时就不能再执行了
    if(rate < NUM - 1) bar[rate] = RIGHT;
}
//下载完毕之后调用initbar初始化进度条
void initbar()
{
    memset(bar,'\0',sizeof(bar));
}

  • main.c:进度条样式的调用(测试)
#include"processBar.h"

typedef void (*callback_t)(int);//函数指针类型
//模拟一种安装或下载
void downLoad(callback_t cb)
{
    int total = 1000;//需要下载1000MB
    int curr = 0;//一开始还没下载为0MB
    //当curr>total即下载完成
    while(curr <= total)
    {
        //进行某种下载任务
        usleep(10000);//模拟下载的时间
        int rate = curr*100/total;//更新进度
        cb(rate);//通过回调,展示进度
        curr += 10;//迭代:循环一次下载10M
    }
    printf("\n");
}
int main()
{

    downLoad(processbar);
    initbar();
    downLoad(processbar);
    initbar();
    downLoad(processbar);
    initbar();
    downLoad(processbar);
    initbar();
    return 0;
}

二、简单使用git

1. git是什么

  1. git是一个版本控制器
  2. git的核心工作主要是两个:
    • 使用git来进行版本管理
    • 使用git多人协作开发
  3. git是client和Server一体的(例如:本地仓库可以传到远端,远端仓库也可以拉取到本地)
  4. git是一个开源的软件,基于git搞了一些商业版的网站——github&&gitee
  • 理解什么是版本管理?

例如:在写毕业论文的时候,我们需要不断的修改,在修改的时候就会产生不同的版本,这个时候我们需要将其保存在同一个文件夹下,也可将这个文件夹称作仓库。这个仓库就是做毕业论文的版本管理的!

  • 理解git

我们怕电脑中的本地仓库被我们弄丢,所以我们可以将其传到远程仓库git中!

2. git的简单使用

在这里我们只学习git的简单使用,把本地仓库的代码传上远端仓库即可

(1)新建仓库

在菜单栏右侧有一个‘+’,新建仓库:

在这里插入图片描述

现阶段我们创建的仓库,填写好仓库名和仓库介绍即可

在这里插入图片描述

  • tip:.gitignore文件是筛选从本地上传到远端仓库的文件的,只要在.gitignore文件有的文件就不能上传到远端仓库!在这里插入图片描述

(2)将远端仓库拉取到本地

  • 先将仓库的url复制一份:
    在这里插入图片描述
    在这里插入图片描述
  • 将远端仓库拉取到本地:

注意:在拉取之前先检测Linux是否下载了git

git --help#检测git是否安装好,简写为--h也可以
git --version#也可检查是否安装好

出现如下图所示,即安装好了

在这里插入图片描述
如果没有安装,粘贴如下命令安装:

sudo yum install git

将远端仓库拉取到本地,指令如下:

git clone [url]#这里的url就是刚在远端仓库复制的url

在这里插入图片描述

(3)本地仓库

  • 我们需要把本地仓库的代码上传到远端仓库,那本地仓库在哪里呢?

本地仓库 .git 在我们拉取到本地的目录中,注意它隐藏的

在这里插入图片描述

  • 为什么我们的本地仓库是隐藏的——就是因为它不想让我们对其修改

(4)三板斧第一招:git add

  • 先把我们要上传的文件拷贝到刚才拉取的克隆本地当中
    在这里插入图片描述
  • 注意:这个文件虽然拷贝到了本地当中,但是它还没有被仓库管理起来
  • 所以git add第一板斧将新拷贝到本地的文件添加到本地仓库
git add [文件名]

在这里插入图片描述

(5)三板斧第二招:git commit

  • 其实git add只是将其添加到仓库的暂存区里了,还需要git commit第二板斧将其真正提交到本地仓库中!
  • git commit提交的时候还应该注明提交日志,描述改动的详细内容
  • 注意:提交日志不能乱写,它是给我们查看的——即通过日志了解提交的文件具体做了什么事
git commit -m "提交日志信息"
  • 首次使用git commit的时候,可能会报错,因为Git需要知道你的用户名和电子邮件地址,以便在每次提交时记录这些信息,但你还没有设置全局的用户名和邮箱。(其本质是为了对代码进行溯源)
    在这里插入图片描述
  • 完成设置后,你应该能够成功地进行Git提交了。再次尝试运行你的提交命令
    在这里插入图片描述
    tip:如果这里设置的邮箱与你git上的邮箱不一致,可能会导致在Gitee没有提交的小绿点。

(6)三板斧第三招:git push

  • 将本地仓库同步到远端仓库(即远端服务器)上
git push
  • push时需要填写用户名和密码
    在这里插入图片描述
  • 同步成功后,刷新Gitee就可以看到你提交的文件了
    在这里插入图片描述

(7)补充:git log&&git status

  • git log:查看历史提交记录
    在这里插入图片描述
  • git status:查看提交状态
    在这里插入图片描述
    到这里我们就学完了git的基本使用

标签:git,换行,进度条,三板斧,仓库,Linux,缓冲区,processbar
From: https://blog.csdn.net/wangjiushun/article/details/141901109

相关文章

  • 【Linux探索学习】第五弹——Linux用户管理:创建、删除与查看普通用户
    前言:Linux下创建普通用户是我们以后经常要做的一件事,一个超级用户下可以有多个普通用户,这样我们就可以用这些普通用户去做不同的事情,所以学习如何创建并管理这些用户就显得尤为重要提醒:本篇是在Ubuntu系统下进行的操作目录一、创建普通用户二、测试是否创建成功方法一:方法二:三、查......
  • Linux网络连接三种模式的区别(图解超详细)
    (CentOS安装难点——网络连接方式的理解)参考视频链接为什么选择NAT模式?如上图情景设定:图中三个人在同一个教室网络,可以相互通讯,因为他们三人在同一网段(三者都以192.168.0打头)。1.桥接模式虚拟系统可以和外部系统相互通讯,但是容易造成ip冲突(张三ip:192.168.0.20,他......
  • Linux基础命令:轻松掌握终端操作
    引言在现代IT行业中,Linux因其稳定性和灵活性广受欢迎。作为后端开发、系统管理和数据科学等领域的必备技能,熟练掌握Linux基本命令将使你在职场中更加游刃有余。无论你是刚接触Linux的新手,还是希望提升技能的开发者,了解Linux命令行的基本用法都是至关重要的。今天,我们将探讨一......
  • 网络编程 Linux环境 C语言实现
    进程间通信的延续跨电脑进程间通信一、远程通信方式电路交换------老式有线电话通信​报文交换​分组交换支持分时机制的(分片机制)报文交换​现行网络大部分都是采用分组交换形式二、网络&互联网&因特网网络Network:多台计算机通过某种传输介质连接在一起形成......
  • linux shell特殊参数
    $n功能描述:n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要使用大括号包含,如${10}$*功能描述:这个变量代表命令行中的所有参数,此命令把所有参数看成一个整体$@功能描述:这个变量也代表命令行中的所有的参数,但是此命令把每个参数区分对待注意:$*与$@区别在于......
  • git 删除已经添加到git跟踪的文件或文件夹
    这里以.vs文件夹为例:要在Git已存在的项目中忽略>.vs文件夹,你需要创建或修改.gitignore文件,并添加规则来忽略.vs文件夹。如果.gitignore文件已存在,你只需要添加一行.vs/。步骤如下:1.打开终端或命令行界面。2.切换到你的Git项目目录。3.编辑.gitignore文件。如果文件不存......
  • git合并相关操作详解
    在使用Git进行分支管理时,合并(merge)操作是非常常见的。下面是Git合并相关的详细步骤和一些常见的场景及注意事项。一、基本合并操作假设我们有两个分支:main和feature,希望将feature合并到main上。切换到目标分支首先需要切换到你想合并到的分支。例如,切换到main分支......
  • Jenkins实现自动拉取Git代码,构建镜像,并上传到远程镜像仓库
    一.安装JenkinsJenkins官方文档:https://www.jenkins.io下面采用Linux进行安装,其它安装方式请参考官方文档sudowget-O/etc/yum.repos.d/jenkins.repo\https://pkg.jenkins.io/redhat-stable/jenkins.reposudorpm--importhttps://pkg.jenkins.io/redhat-stab......
  • mysql8 gitd 主从复制
    一、master主库1、配置serviceID、开启二进制日志和打开gitd,可以配置中继日志。然后重启mysql。完整配置如下[client]socket=/data/mysql/mysql.sock[mysqld]user=rootdatadir=/data/mysql/databasedir=/data/mysqlsocket=/data/mysql/mysql.sockport=3306#允许最大连......
  • 黑客入门Linux安装准备工作
    ArsenalLinux黑客新手入门推荐:社区采用二个系统进行更新后续文章,分别如下:-Kalilinux:内包含大量工具/一次下载安装可以减少所需要工具安装时间。退求其次:Kali是目前最火爆的黑客工具集成系统。最关键的是网上教程很多,方便更多爱好者实战自己的才能。Linuxmint:目前......