【Linux】Linux第一个小程序-进度条

news2024/11/15 18:03:56

前言:

  • 在之前的学习中,我们已经基本掌握了关于了 Linux 下的一些工具的使用,接下来我们运用之前学到的知识,我将带领大家写了一个关于 进度条 的小程序来练练手!!!


本文目录

(一)理解 \r && \n

1、可显字符 和 控制字符

2、代码演示

(二)缓冲区的理解

1、什么是缓冲区

2、为什么要引入缓冲区

3、代码演示,引出现象

4、深入理解,解答现象

①缓冲区的类型

②缓冲区的刷新

(三)倒计时功能的实现

1、9以内的倒计时

2、10以内的倒计时实现

a)修改版

(四)进度条小程序( 🔥)

1、进度条样式说明

2、多文件实现

3、主体架构实现

4、进度的实现

5、缓冲功能的实现

(五)总结


(一)理解 \r && \n

在我们正式的写进度条之间,我先给大家理清一下这两个概念,带大家看看到底什么是 \r \n

1、可显字符 和 控制字符

在我们之前学习的 C语言中,有很多的字符。但是在宏观上大概可以分为两类字符,它们分别是:

  • a)可显字符:当我们从键盘上输入这个字符时,显示器上就可以显示这个字符,即输入什么就显示什么。这类字符称为可显示字符,如a、b、c、$、+和空格符等都是可显示字符。
  • b)控制字符:通常表示出现于特定的信息文本中,表示某一控制功能的字符。例如我们今天要讲到的  \n \r 等字符

不知道大家发现没有,不管是在我们日常敲代码又或者像我此时写文章的时候,当我们写完一行后若是没有 自动换行功能 此时就需要敲下键盘中的【Enter】键以此来达到换行的效果。可是对于这个按键,大家可能都认为就是简单的敲一下键盘上的一个键,但是实际上在计算机内部是做了两件事的,即 —— 【换行】+【回车】。具体如下:

  • \n表示新起一行,此时光标位于行末 (换行)
  • \r表示回到当前文本行的最开始处(回车)

此时可能就有点小伙伴会有疑惑,说不对呀!我之前写 C语言的时候就是 printf打印 \n 之后就可以了呀,你这里怎么说是有两部呢?

  • 那是因为各位当前的语言范畴它呢就把 \n 就默认成为了 回车加换行,所以呢你看到的就是这个样子

现在我们知道了进行“换行操作” 其实是经历过两步的。其实很早之前在我们的老式键盘上就已经体现出来了,不知道各位小伙伴有没有仔细观察过呢?

2、代码演示

 当我们知道现象后,接下来我们就需要去验证一下,看我所说的是否是真的。接下来,我写几行代码给大家演示一下

  • 注意:因为在之前的讲解中,我们已经知道了 【vim】【make\Makefile】以及【gcc】的基本使用,接下来我们就不解释这些工具的使用了

a)首先,我们的代码是先写出基础的【Makefile】,我们在创建一个【test.c】文件用来写代码

 b)紧接着我们先写【Makefile】,同时在【test.c】文件中写入两行代码。具体如下:

 c)最后,我们可以执行这个程序,看最后的结果是如何的

 现象解释:

  • 从上我们不难发现一个事情。最后带有 【\r】的一行没有打印出来。
  • 原因就是因为【\r】将光标回到最开始的位置,你可以理解为本来是应该打印 【hello hello】,但是光标此时回到最左侧,最后刷新显示的时候就什么都没有了!

到此,具体的现象我就带大家看到了,原因我也给大家分析了。

  • 但是这就完了吗?其实并没有,我们想要充分理解,我们还要学习一下关于缓冲区的概念

因此,接下来我们将要学习的便是关于缓冲区的基本知识了!!!


(二)缓冲区的理解

1、什么是缓冲区

  • 缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
  • 缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

2、为什么要引入缓冲区

那么当我们有了关于缓冲区的概念之后,此时我们就会想为什么会引入 “缓冲区” 这个概念呢?

举个简单的例子:

  • 当我们从磁盘里读取信息时,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数;
  • 再加上计算机对缓冲区的操作远快于对磁盘的操作,故缓冲区的使用可大大提高计算机的运行速度。


3、代码演示,引出现象

有了上述的基本认识之后,接下来我们通过简单的代码观察其中的现象,让大家有直观的感受,进而我们在深入探讨

  • 在这之前先认识两个Linux下的库函数

sleep() 函数:——>睡眠

  • 头文件包含在<unistd.h>
  • 注意区分一点:Windows中的 sleep() 单位是 毫秒;而Linxu中的sleep()单位是 

fflush()函数 ——> 刷新流

  • 该函数一般用来刷新输出流 ->stdout
  • 格式:int fflush(FILE *stream);

还是以上述验证字符的代码为例,我给几段代码以及输出现象,大家先感受一下

a)代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   printf("hello world");
  6                                                                                                                                          
  7   sleep(2);        
  8                   
  9   return 0 ;       
 10 }   

运行结果

现象描述:

  • 以上代码输出的最后我们没有加上【\n】,从结果我们不难看出,我们要输出的【hello world】并没有在第一时间打印,而是在睡眠2秒后和【命令提示符】一同进行打印,这是为何呢?(注意,问题来了哟!!!)

b)代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   printf("hello world\n");                                                                                                                                              
  7   sleep(2);        
  8                    
  9   return 0 ;       
 10 }   

运行结果

现象描述:

  • 从上述的结果我们可以发现:和我们平时写的代码几乎没有区别的,当加上sleep()函数,相当于在打印输出完之后让程序 “延迟” 2秒,然后才会显示【命令提示符】

c)代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   printf("hello world");
  6   fflush(stdout);                                                                                                                                                  
  7   sleep(2);        
  8                    
  9   return 0 ;       
 10 }   

运行结果

现象描述:

  • 紧接着我们在下行加入了 fflush() 这个函数,将其放在 sleep() 函数之前,也就相当于是优先刷新了一下缓冲流,此时就可以看到【hello world】立马先被打印了出来,等上2秒后才显示的【命令提示符】

d)代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   printf("hello world\r");
  6                                                                                                                                               
  7   sleep(2);        
  8                    
  9   return 0 ;       
 10 }   

运行结果

现象描述:

  • 从上述我们可以观察到:当我们在输出语句后加上了 \r 时,当开始执行后程序便开始睡眠, 然后在2秒睡眠后便直接打印出了【命令提示符】(注意:问题又来了哟!!!)

e)代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   printf("hello world\r");
  6   fflush(stdout);                                                                                                                                                    
  7   sleep(2);
  8             
  9   return 0 ;
 10 }

运行结果

现象描述:

  • 通过上述现象我们不难发现:通过fflush()刷新流,我们提前显示了一下需要打印的数据,此时就可以清晰的观察到,其实我们原本要打印的数据是在的,结果被【命令提示符】覆盖掉了

4、深入理解,解答现象

从上述的代码展示以及最后的结果我们提出了以下几个问题,分别是:

  • 不加换行符 \n 时为何是先睡眠再打印?
  • 加上 \n 后数据会立刻显示出来,完成睡眠后才显示提示符?
  • 加上回车 \r 后观察不到我们输出的数据。然而刷新一下就有了? 

接下来,我会一一为大家解答上述疑惑!!!

  • 在解答之前,我们先来看一些需要大家了解的文字知识!

①缓冲区的类型

缓冲区可以分为三种类型:全缓冲、行缓冲和不带缓冲

  • 注意:在这里我们主要讲的是关于【行缓冲】的基本知识

1、全缓冲

  • 在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2、行缓冲

  • 在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

3、不带缓冲

  • 顾名思义,也就是不进行缓冲,标准出错情况 【stderr】就是典型代表,这使得出错信息可以直接尽快地显示出来。

②缓冲区的刷新

当发生以下情况后,缓冲区将会执行刷新操作:

  • 1、缓冲区满时会自动刷新
  • 2、执行特定的函数时
  • 3、行缓冲遇到换行符时也会刷新
  • 4、关闭文件时,也会自动刷新

可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O操作。

另外,我们可以使用 fflush 函数来刷新缓冲区(执行I/O操作并清空缓冲区)


接下来,我就来回答一下上述我们提出的几个问题吧!

①不加换行符 \n时为何是先睡眠再打印?

  1. 对于上述的代码而言,程序执行时一定是顺序执行的,因此一定是先打印输出语句中的内容;
  2. 那么就有很多小伙伴好奇,我们怎么看不到这个现象呢?因为它被存放到了缓冲区里,由于sleep()函数的缘故,导致这个缓冲区没有被刷新而已,所以它并没有丢失

②加上\n后数据会立刻显示出来,完成睡眠后才显示提示符?

  1. 首先,我们需要知道一点。那就是无论我们加不加\n,数据都会被保存在缓冲区里。
  2. 因为输出的最后一个字符是 \n ,并且是往显示器里面进行打印,此外缓冲区还有很多的刷新策略。今天我们关心的是行缓冲,即->只要碰到了换行符,这就意味着此时就会把换行符之前的所有内容全部显示出来
  3. 所以字符串是以行缓冲的方式保存在了行缓冲区里,最后当我们要退出的时候就会显示出来,所以此时保存在冲区里的数据就会被刷新出来

③加上回车 \r后观察不到我们输出的数据。然而刷新一下就有了? 

  1. 对于 \r 我们可以通过上述的输出可以发现,此时光标会回到行首;
  2. 因为,当我们打印的时候,当遇到 \r 的时候,光标就会回到最开始,但是这些数据并没有在缓冲区中被移除,依旧是存在的;
  3. 当我们 sleep() 的时候,光标打印输出的内容时遇到 \r 就会回到最开始,但是程序执行完之后,shell还会打印提示符,此时就会覆盖掉程序输出的内容


(三)倒计时功能的实现

当我们领悟到上述所讲的知识之后,接下来我们先简单的实现一个——倒计时。

1、9以内的倒计时

  • 我们先来简单的实现一下9以内的倒计时,思路很简单,就是循环输出即可。然后在打印完每个数字之后使用sleep(1)

代码如下:

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 int main()
    4 {
    5   int i=9;
    6   for(;i>=0; i--)
    7   {
    8     printf("%d\n",i);
    9     sleep(1);                                                                                                                                     
   10   }
   11  
   12   return 0 ;
   13 }

运行结果如下:

上述就是最简单的倒计时实现了。但是这跟我们想象的似乎不一样啊是不是:

  • 我们希望看到的是在一行实现相应的功能,并且每次输出的结果把上次输出的结果覆盖掉,那么我们应该怎么做呢?

接下来我就带大家看看怎么实现:

代码如下:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   int i=9;
  6   for(;i>=0; i--)
  7   {
  8     printf("%d\r",i);  //注意这里变为了\r                                                                                                                                           
  9     fflush(stdout);
 10     sleep(1);
 11   }
 12 
 13   return 0 ;
 14 }

此时我们再去查看最终的结果:


2、10以内的倒计时实现

不知道大家觉得【0-9】和【0-10】这二者实现倒计时是否一样呢?其实是不一样的哟!!

  • 眼见为实,我们把【i】的值改为10,看最终的结果是不是我们想要的那样。

结论:

  • 通过上述我们不难发现一件事,当是两位数时只有前面的数字会被覆盖,10后面的这个0会始终被保留下来,最后倒计时结束后便成了00

那么我们要如何修改才会和上述的一样呢?

  • 在计算机打印时,假设我们要打印的是【100】这个数,那么是不是计算机就是按整数【100】的形式打印出来的呢?
  • 其实不是这样的。在计算机打印中,它会把100 当成三个字符进行打印,即在计算机看来 100,就是由 字符 1 0 0 组成;
  • 将整型数字先转换为字符串的形式,然后去遍历这个字符串,用putc()这个函数将字符一一地打印在显示器上

a)修改版

我们可以像如下一样进行修改,即可实现我们上述的效果。

代码如下:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   int i=10;
  6   for(;i>=0; i--)
  7   {
  8     printf("%2d\r",i);    //改为%2d                                                                                                                                          
  9     fflush(stdout);
 10     sleep(1);
 11   }
 12   return 0 ;
 13 }

运行结果:

到此,在这里就简单的实现出来了一个倒计时的“小玩具”。


(四)进度条小程序( 🔥)

有了以上的知识铺垫,接下来就到了实现 ——>进度条小程序的实现过程了!

1、进度条样式说明

首先,就是给大家先说明一下本次进度条我们最终呈现出来的样式是什么样的。

因为,Linux下不是图形化的,因此我们这里实现的进度条就不是大家所熟知的网上看见的那种形状。

首先,我先给出我们的进度条的大概样式,最后呈现出来的就是以下这种现象:

  • 【##################################>】【100%】【/】

说明:

1.主体部分大概就是用个【】来进行概括,中间用 ## 这样的符号来表示我们的进度条的进度样式;

2.后一个【】则表示相应的进度情况;

3.因为我们是在Linux环境下,无法做到这种图形化界面。最后就是用旋转字符的样式来代替我们在 Windows下的缓冲的样式


2、多文件实现

在这里我们给出的是多文件这样的实现方案。因此在正式的上手之前,我们需要创建相应的文件来表示相应的代码。

  • 【proc.h】:存放头文件的文件夹
  • 【proc.c】:代表头文件匹配的源文件,进度条实现的逻辑存放在这里面
  • 【mainc】:来进行程序的调度

先直接给出程序的大概框架,让大家先见见:

  •  接下来,我们要去编译的话,此时我们还需要创建文件列表,即【makefile】来存放,这个在之前我们已经详细的讲过了,这里就不多讲了。直接给出,具体如下:

  •  紧接着,我们边去测试一下程序是否可以正常的编译运行:

 此时,可能好多小伙伴就会有疑惑,在创建的文件列表【Makefile】中只有 main.c和 proc.c  而没有头文件 proc.h 文件

  • 对于以上问题,之前在讲解【gcc】的时候我大概提到过关于这个知识点。
  • 我们在进行多文件编译时候是不需要考虑【头文件】的,因为在预处理阶段头文件就会在它被包含的 .c源文件中进行展开,因此加不加结果都是一样的。
  • 一般我们是不加的


3、主体架构实现

第一步:

#define SIZE 101

解释说明:

  • 因为进度条嘛!进度就是从0到100 的,将整体进度条看作是一个字符串,因此我们设置101来存放

第二步:

memset(bar, '\0', sizeof(bar));

解释说明:

  1. 因为实现这个进度条推演就是一个循环的方式,每次都去修改这个字符数组当前位置上的字符,将其变为 “=” ,紧接着去打印的时候下一个位置就会多出来一个 “=” ,从而实现往后慢慢推进的过程
  2. 初始化时就把数组全部的位置初始化为 \0 ,紧接着随着进度条的推进去修改为 “=” 即可

代码如下:

  1 #include"proc.h"
  2 
  3 #define SIZE 101
  4 
  5 void process()
  6 {
  7   char bar[SIZE];
  8 
  9   memset(bar,'\0',sizeof(bar));
 10 
 11   int i=0;
 12   while(i<+100)
 13   {
 14     printf("[%s]\n",bar);
 15     bar[i++]='#';                                                                                                                                                    
 16     sleep(1);
 17   }
 18 }
  • 此时我们编译一下,看最终的结果是怎么样的:

但是此时我们可以发现,这是不断的换行实现的,但是在我们的认知中进度条就是在 “一行 ”上实现的呀。因此,此时显然不符合我们的预期

  1. 我们的预期是在一行上进行不断推进的过程。因此,我们就不能加上【\n】这个字符;
  2. 我们使用【\r】,当每次打印的时候,都从当前行的起始位置处进行操作。

当我们完成上述要求之后,紧接着来编译代码看最终的结果是不是我们期望的那样,具体如下:

  • 代码如下:
  1 #include"proc.h"
  2 
  3 #define SIZE 101
  4 
  5 void process()
  6 {
  7   char bar[SIZE];
  8 
  9   memset(bar,'\0',sizeof(bar));
 10 
 11   int i=0;
 12   while(i<+100)
 13   {
 14     printf("[%s]\r",bar); //此时变为\r                                                                                                                                           
 15     bar[i++]='#';
 16     sleep(1);
 17   }
 18 }
  • 运行结果:

此时,出现了一个 “小坑” ,我们可以发现并没有显示出任何东西大家知道什么吗?

  • 我相信聪明的小伙伴已经知道了,即 缓冲区没刷新!
fflush(stdout);
  • 再次运行,结果如下:

不过此时有点小伙伴就会有这样一个问题,是什么呢?

  • 我们可以观察到这个进度条推进的速度很慢,那有没有办法让它快一点呢?

答案是有的,此时有需要另外一个库函数了,那就是 【usleep】函数。

  • 大家可以用 【man】手册去查一下到底什么意思,我在这里给出简略的回答:

  •  代码如下:
  1 #include"proc.h"
  2 
  3 #define SIZE 101
  4 #define ARP '>'
  5 
  6 void process()
  7 {
  8   char bar[SIZE];
  9 
 10   memset(bar,'\0',sizeof(bar));
 11 
 12   int i=0;
 13   while(i<+100)
 14   {
 15     printf("[%s]\r",bar);
 16     fflush(stdout);
 17     bar[i++]='#';
 18     usleep(100000);  //变为usleep                                                                                                                                                    
 19   }
 20 }
  • 运行如下:

主体的进度条预留出了一个100的空间,好呈现进度条从0 ~ 100的推进,就可以上面说到过的格式化占位符

printf("[%100s]\r", bar);
  • 运行结果:

我们可以发现怎么是从反方向走的,这也不是符合我们的需求啊!

  • 别急,其实很好解决,只需在 输出的 100前加上 【-】 即可实现从左开始输出。
printf("[%-100s]\r", bar);
  • 运行结果:

当然我们还可以实现更多的样式,例如假设我们要实现【===>】这样的,我们可以怎么操作呢?

  • 代码如下:

  1 #include"proc.h"
  2 
  3 #define SIZE 102    //记住,此时当你加入的符号过多时,空间也应该随之变大
  4 #define ARP '>'
  5 #define STYLE '='   //我们在这里用宏定义样式,便于我们修改                                                                                                                                               
  6 
  7 void process()
  8 {
  9   char bar[SIZE];
 10 
 11   memset(bar,'\0',sizeof(bar));
 12 
 13   int i=0;
 14   while(i<+100)
 15   {
 16     printf("[%-100s]\r",bar);
 17     fflush(stdout);
 18     bar[i++]= STYLE;
 19     bar[i]=ARP;
 20 
 21     usleep(100000);
 22   }
 23 }
  • 运行结果如下:


4、进度的实现

实现完主体的框架之后,紧接着我们需要去实现一下百分比递增

  • 代码如下:
  1 #include"proc.h"  
  2   
  3 #define SIZE 102  
  4 #define ARP '>'  
  5 #define STYLE '='  
  6   
  7 void process()  
  8 {  
  9   char bar[SIZE];  
 10   
 11   memset(bar,'\0',sizeof(bar));  
 12   
 13   int i=0;  
 14   while(i<+100)  
 15   {  
 16     printf("[%-100s][%d]\r",bar,i);   //我们只需在最后加上输出的值即可                                                                                                                           
 17     fflush(stdout);  
 18     bar[i++]= STYLE;  
 19     if(i != 100) bar[i]=ARP;  
 20   
 21     usleep(100000);  
 22   }  
 23 }  
  • 运行如下:

但是此时我们可以发现,输出只是数字,并不是百分数啊! 

  • 我们只需在【%d】的后面在加上 % 即可,即——>【%d%%】

  • 结果如下:

到此,关于进度的实现便完成了。接下来就是关于缓冲功能了!!!


5、缓冲功能的实现

终于到了最后。马上就要揭开我们进度条的了 ”庐山真面目“了。

  • 此时我们只需要定义一个字符数组,并用【const】来修饰。
  • 目的很简单就是防止里面的内容被修改。

const char* label = "|/-\\";
  • 最后在打印的时候,要去实现一个轮回就需要用到一个取余操作,每次打印的都是【0 ~ 3】的倍数,因此模上4 即可

printf("[%-100s][%d%%][%c]\r", bar, i , label[i % 4]);

运行如下:

到此,我们就实现了一个进度条小程序的设计。最终代码如下:

  1 #include"proc.h"
  2 
  3 #define SIZE 102
  4 #define ARP '>'
  5 #define STYLE '='
  6 
  7 void process()
  8 {
  9   const char* label = "|/-\\";
 10   char bar[SIZE];
 11 
 12   memset(bar,'\0',sizeof(bar));
 13 
 14   int i=0;
 15   while(i<+100)
 16   {
 17     printf("[%-100s][%d%%][%c]\r", bar, i , label[i % 4]);                                                                                                           
 18     fflush(stdout);
 19     bar[i++]= STYLE;
 20     if(i != 100 )bar[i]=ARP;
 21 
 22     usleep(100000);
 23   }
 24 }


(五)总结

到此,关于进度条小程序的所有知识便讲解完毕了!接下来,我们一起回顾一下

  • 首先我们学习了C语言中的两个控制字符【\n】与【\r】,知道了这两者的作用及功能;
  • 紧接着我们又引出了缓冲区的概念,并且通过代码的形式给大家具体的呈现了出来。知道了缓冲区是需要被刷新才会被显示出来的;
  • 有了以上知识点的铺垫,我们通过设计的倒计时的功能给大家变相的总结了上文,并且对上述知识进行了运用;
  • 最后,就是总结上文,之前的一切都是在给我们即将设计的 进度条小程序做“背景板”。通过几个方面的讲述带领大家对这个小程序进行了实现。

以上就是本文的所有知识,感谢各位的支持!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/439444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

密码模块非入侵式攻击及其缓解技术GMT0083-2020

密码模块非入侵式攻击&#xff0c;是一种攻击方式&#xff0c;在这种攻击中&#xff0c;攻击者不会直接访问受攻击者的密码模块。相反&#xff0c;攻击者会利用其他途径获得用户的凭证&#xff0c;然后使用这些凭证去访问密码模块。这种攻击通常使用钓鱼邮件、社交工程等技巧&a…

户外软件推荐与介绍——奥维和两步路

文章目录 &#xff08;一&#xff09;记录坐标的网站1、奥维互动地图注册2、记录坐标3、如何导出坐标点到ArcGIS4、导航5、记录轨迹6、下载离线地图 &#xff08;二&#xff09;记录轨迹的软件&#xff08;三&#xff09;离线地图的下载&#xff08;四&#xff09;如何使用3D地…

Chapter5-消息队列的核心机制

Broker 是 RocketMQ 的核心&#xff0c;大部分‘重量级”工作都是由 Broker 完成的&#xff0c;包括接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、&#xff0d;消息的持久化存储、消息的 HA 机制以及服务端过滤功能等。 5.1 消息存储和发送 分布式队列因为有高…

网络协议-TCP、IP协议和互联网协议群

目录 TCP/IP协议群简介&#xff08;互联网协议群&#xff09;&#xff08;Internet Protocol Suite&#xff09; 应用层&#xff08;Application&#xff09;(合并简化了展示层&#xff0c;会话层) 传输层&#xff08;Transport&#xff09; 网络层&#xff08;Internet&am…

射频功率放大器在铝板损伤量化表征中的应用

实验名称&#xff1a;基于异常指数的铝板损伤量化表征 研究方向&#xff1a;损伤量化 测试目的&#xff1a; 结构损伤检测与量化评估对于保障航空、航天、船舶、石油化工及兵器工业等领域的基础设施结构安全性具有重要意义&#xff0c;受到了广泛的关注。在现有的结构监测技术中…

微内核与宏内核

了解Linux发展史的同学都知道&#xff0c;关于linux吵架史的一段佳话&#xff0c;就是关于内核设计思想之争&#xff0c;这段故事在linus Tovalds的自传中也有提到。我们都知道linux操作系统由Linus Tovalds模仿minix操作系统开发的。 虽然Linux是受MINIX启发而发明&#xff0c…

Git——利用SSH密钥本地仓库上传远程GitHub库

文章目录 1、前言2、详细步骤2.1 创建密钥2.2 进入密钥文件并复制2.3 在GitHub上添加密钥2.4 回到本地仓库文件夹&#xff0c;连接GitHub并上传 3. 结语 1、前言 现在想要从本地设备将本地仓库上传到GitHub上需要用到SSH密钥&#xff0c;接下来讲解大致的步骤&#xff0c;本文默…

一本通 3.4.6 拓扑排序

1352&#xff1a;【例4-13】奖金 【题目描述】 由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出&#xff0c;Yali Company总经理Mr.Z心情好&#xff0c;决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。 于是Mr.Z下令召开m方会谈…

openEuler实验-基于openEuler的云景平台文件管理系统

一些常见的Linux命令 目录 前言 实验目的 实验内容 实验知识点 实验环境 实验分析 系统登录和电源管理 1&#xff09;使用login命令登录系统 2&#xff09;退出openEuler 3&#xff09;退出当前的shell 软件管理 1&#xff09;查询目录信息 2&#xff09;切换目录路…

基于Tensorflow搭建卷积神经网络CNN(服装分类)保姆及级教程

项目介绍 TensorFlow2.X 搭建卷积神经网络&#xff08;CNN&#xff09;&#xff0c;实现服装的分类识别。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠&#xff0c;然后经过全连接层&#xff0c;最后用softmax映射为每个类别的概率&#xff0c;概率最大的即为识…

25 - 回文串问题

文章目录 1. 回文子串法一&#xff1a;动态规划法二&#xff1a;双指针法 2. 最长回文子串方法一&#xff1a;动态规划法方法二&#xff1a;双指针法 3. 最长回文子序列 1. 回文子串 法一&#xff1a;动态规划 递推公式 当s[i] ! s[j]&#xff0c;那没啥好说的了&#xff0c;d…

三闯港交所,主打性价比的乡村基如何夺魁“中式快餐第一股”?

曾被中金公司称为“中国大消费最燃赛道”的中式餐饮&#xff0c;正在密集掀起IPO的风潮。去年5月和7月&#xff0c;老乡鸡和老娘舅分别向上交所提交招股书&#xff0c;绿茶餐厅、杨国福麻辣烫、捞王等企业也在推进上市计划。 国内第四大中式快餐集团&#xff0c;占据约0.6%市场…

python版pytorch模型转openvino及调用

一、openvino安装 参看官方文档https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/download.html 安装命令是根据上面的选择生成。这里安装了pytorch和onnx依赖。 二、pytorch模型转opnvino模型推理 import os import time import cv2 import nu…

易基因:MeRIP-seq等揭示m6A甲基化修饰对抗病毒基因表达的转录调控机制|Cell Rep

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 2021年03月02日&#xff0c;杜克大学医学中心的分子遗传学和微生物学系Stacy M. Horner教授团队在《Cell Reports》&#xff08;IF: 9.995&#xff09;杂志发表了题为“Post-transcripti…

LeetCode算法小抄--归并排序详解及应用

LeetCode算法小抄--归并排序详解及应用 归并排序详解及应用[912. 排序数组](https://leetcode.cn/problems/sort-an-array/)[315. 计算右侧小于当前元素的个数](https://leetcode.cn/problems/count-of-smaller-numbers-after-self/)[hard]--华为笔试[493. 翻转对](https://lee…

Java版本工程项目管理系统源码-全面的工程项目管理

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…

供应链优化的好处是什么?

企业可以从优质的供应链优化软件中获得许多好处&#xff1a; 成本降低 通过供应链优化&#xff0c;可以消除许多不必要的成本&#xff0c;从而简化业务运营费用。所有重复或无效的流程也可以根据需要消除或自动化。重点可以转移到通过准确及时交付来满足客户的需求上。通过供…

OpUtils网络端口扫描

网络端口扫描程序使 IT 管理员能够密切监视端口&#xff0c;这些端口是网络通信的端点。网络端口支持不同实体之间的数据传输&#xff0c;并支持运行各种服务或应用程序。在日常工作中&#xff0c;网络管理员的任务是扫描和监控数百个交换机端口。网络端口扫描程序工具通过帮助…

Intellij IDEA-插件开发环境搭建

插件开发有两种方式 1.基于Gradle&#xff08;新版IDEA&#xff0c;按钮名称叫做IDE Plugin&#xff0c;具体多新我也不清楚&#xff0c;反正2023的必须是这种&#xff09; 2.基于Dev kit&#xff08;旧版IDEA&#xff0c;按钮名称叫做IntelliJ Platform Plugin&#xff0c;具体…

【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透

前言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。 Gitlab是被广泛使用的基于git的开源代码管理平台, 基于Ruby on Rails构建, 主要针对软件开发过程中产生的代码和文档进行管理, Gitlab主要针对…