当前位置: 首页 > news >正文

linux文件——用户缓冲区——概念深度理解、IO模拟实现

        前言:本篇文章主要讲解文件缓冲区。 讲解的方式是通过抛出问题, 然后通过分析问题, 将缓冲区的概念与原理一步一步地讲解。同时, 本节内容在最后一部分还会带友友们模拟实现一下c语言的printf, fprintf接口, 加深友友们对于缓冲区的理解。

        ps: 本节内容适合了解linux进程和linux文件重定向的友友们进行观看。  

目录

缓冲区概念——使用close引出

exit和用户缓冲区

缓冲区刷新方案

为什么要有用户缓冲区

FILE

fork和缓冲区读写

模拟实现c语言标准库

只包含fd的接口——不带缓冲区

c语言的跨平台性

带缓冲区的c语言接口

fflush


缓冲区概念——使用close引出

        讲述缓冲区, 我们需要先看一下下面的接口:

        对于上面的接口, 我们可以预测一下——就是打印4行内容, 分别是hello printfhello fprintfhello fwritehello write

        如图,代码运行结果符合我们的预期。对于上面的代码我们知道, 对于c语言的接口, stdoutFILE文件流里面就封装了1号文件描述符。 他们的底层一定是调用了write函数。

    对于上面的函数,我们重定向到文件是这样, 和直接在显示器上面输出是一样的。

  • 但是, 如果加上close(1), 将显示器文件关闭, 那么情况就有些不同了, 下面是有\n的:

  • 下面是没有\n的:

        如果没有了\n, 对于c语言的打印接口, 就不能输出了。

        如下图, 只输出了系统调用write:

        我们知道对于上面printf、fprintf、fwrite来说, 这三个是c语言接口, 他们的底层一定是封装的write接口。 这就有问题了, 为什么printf、fprintf、fwrite的底层是write, 而write能够打印数据, printf、fprintf、fwrite都不能打印数据呢?

        友友们如果学习过进度条, 那么就会知道一个缓冲区的概念。 这个缓冲区遇到\n或者缓冲区满了之后就会刷新自己。 

        一般情况下, 我们使用printf、fprintf、fwrite不是直接写向显示器, 而是先写向缓冲区。 等到遇到\n或者缓冲区满了之后再刷新缓冲区,将数据刷新到缓冲区。

        也就是说, 对于上面的这个代码来说, 当程序运行到close(1)前一行, 那么数据就已经写到缓冲区了。 只是这个缓冲区一定不在操作系统内部, 这个缓冲区不是系统级别的缓冲区!!!

        具体的底层逻辑关系如下:

        我们使用的c语言接口的时候, 如果是将数据直接拷贝到了系统级别的缓冲区中, 那么等到close(1)的时候, 这个close(1)就能找到对应的文件struct file, 然后找到对应的系统级别的文件缓冲区, 将缓冲区内容刷新到磁盘里面。 也就是说, 如果c语言接口是将数据只拷贝到系统级别的缓冲区, 那么我们应该也能看到c语言接口的结果, 而事实上并没有。 而write是系统调用接口, 是直接写到系统级别的文件缓冲区, 那么当close(1)的时候, 就能直接将数据刷新到磁盘里面。

        我们平时口中的缓冲区, 不是这个系统级别的缓冲区, 而是语言提供的, 这里也就是c语言提供的一个缓冲区, 这个缓冲区是一个用户级别的缓冲区。 也就是说, c语言的printf, fprintf等接口是将数据写到语言级别的缓冲区中, 然后等到某一个时机就调用write接口, 将数据刷新到系统级别的缓冲区中,最后再刷新到磁盘中

        

        所以, 当我们printf、fprintf等等的时候, 这些数据其实是保存在语言级别的缓冲区, 他们还没有进入系统级别的缓冲区, 当close(1)的时候。1号文件struct file, 系统文件缓冲区都被关掉了。 就无法再向磁盘写入数据了, 也就没有显示结果。

        显示器对应的刷新方案是行刷新, 当我们在c语言接口要打印的数据中加上\n的时候, 如下图, 那么即便有close(1), 但是对于用户缓冲区来说, 每一行都会被刷新到系统级别的文件缓冲区。 所以可以打印出来。 用户缓冲区刷新的本质就是将数据通过1 + write写到内核中。

exit和用户缓冲区

        我们之前说过exit和_exit, exit是封装的上层接口, 而_exit是系统调用。 两者的区别是_exit退出前不会刷新缓冲区(我们口中的缓冲区, 都是用户级缓冲区), 而exit会刷新缓冲区(我们口中的缓冲区, 都是用户级缓冲区)。 这是因为_exit身为系统调用, 它在用户层的下层, 它根本看不到用户级缓冲区。 也就没办法刷新它, 而exit处在用户层, 它底层一定是先刷新缓冲区flush, 然后再调用系统调用_exit。

        从上面我的论述中就可以发现, 其实当数据到达内核的时候, 那么这个数据就可以到达硬件了。 ——这也是我们目前认为的, 只要是将数据刷新到了内核, 数据就可以到达硬件了!!!

缓冲区刷新方案

        缓冲区刷新问题:——这里的缓冲区考虑的是语言层, 也就是用户层缓冲区。

  •         无缓冲: 直接刷新, 不管printf, fprintf等接口打印的数据是什么, 直接刷新。
  •         行缓冲: 不刷新,直到遇到\n再刷新。
  •         全缓冲: 缓冲区满了再刷新, 不满的话, 无论如何都不刷新。

 所以整个的刷新流程如下图:

        在向显示器中写入的时候, 采用的是行缓冲。

        在向普通文件中写入的时候, 采用的是全缓冲。

为什么要有用户缓冲区

        进程退出的时候也会刷新缓冲区, 为什么要有这个缓冲区呢? 

        首先就是效率层面——这里可以使用一个例子来说明这件事, 就比如我们给朋友送东西, 如果没有快递公司, 我们就必须亲自去送东西给朋友, 但是现在有了快递公司, 快递公司就可以帮助我们去送快递, 我们节省的这些时间就可以去做自己的事情。——这里面的快递公司就是缓冲区, 我们就是用户。 所以, 缓冲区解决的是谁的效率问题?——其实就是用户的效率问题。 (也就是使用c语言的人的效率问题)

        其次是语言设计层面——拥有缓冲区的目的是为了配合c语言接口:printf,fprintf的输出格式化。——这里我们需要想一个问题, 就是我们在显示器上面打印的789, 这样的数字, 打印的是字符呢? 打印的还是数字呢? ——答案是打印的字符789。 也就是说, 将789转化成字符7, 字符8, 字符9, 然后再打印到显示器上面。 当数据打印的时候, 先将数据打印到用户缓冲区。 当某个时机的时候, 就将用户缓冲区的数据打印到硬件里面。 由于这种数据进入, 数据流出, 很像一条河流, 所以用户缓冲区也被叫做流。
 

FILE

请问, FILE是属于用户呢? 还是属于操作系统呢? 答案是用户, 语言都是属于用户的。

        知道这个之后, 我们就可以知道, 对于fopen来说

        如果使用fopen打开了一个文件, 那么就会获取这个文件的文件描述符fd。 然后再malloc一块内存空间保存在FILE, 这个fd和malloc的内存空间都保存在FILE里面!!也就是下面这张图:

fork和缓冲区读写

现在,我这里有另外一个关于fork函数的问题。 我们看下面这串代码:

        我们生成程序后, 将数据重定向到文件中。 如果按照我们以往的经验的话, 这里我们预测会打印四行内容, 分别是hello printf、hello fprintf、hello fwrite、hello write

        但是, 我们实际运行的结果如下:

        如上图, 我们可以发现c语言接口的打印都被打印了两次, 只有write系统调用被打印了一次。

        这是因为当使用重定向, 重定向到了文件之后, 缓冲区的刷新方案就变成了全缓冲, 遇到\n不再刷新, 而是等缓冲区被写满之后才刷新。

        那么我们下载来证明一下重定向到文件是全缓冲的

        首先我们写下面这个程序;

        这个程序如果按照我们的猜想。 前三秒不会打印任何数据, 这些数据都会被打印到了缓冲区之中。 当三秒过后, write会被打印。然后再五秒所有数据才会全部被打印。

         我们先打开监视窗口进行观察:

然后运行这个程序, 就会得到:

        那么这是为什么呢?——首先我们知道, 当我们三个c语言接口执行完的时候, 数据都被写到了缓冲区中。 而缓冲区也是在进程里面的, 所以当fork创建子进程后, 再刷新缓冲区, 而刷新缓冲区就相当于数据的修改, 需要进行写时拷贝。 所以就有两份缓冲区, 两个缓冲区的数据都被刷新后就产生了上面的现象!!!

模拟实现c语言标准库

        为了模拟实现c语言的标准库, 我们创建三个文件。 这里的_my_func.h就相当于stdio.h这样的标准库, 而_my_func.c就是用来模拟实现c标准库接口。

         我们打开_my_func.h, 首先做好预备工作。 先让该头文件不可重复包含, 也就是下面的ifdef, define, endif。 然后再包含一个头文件string.h。 我们先来简单的实现以下三个函数, _fopen, _fwrite, _fclose

只包含fd的接口——不带缓冲区

下面是代码:

#include<string.h>//定义缓冲区最大长度
#define SIZE 1024//flag用来表示刷新方案
#define FLUSH_NOw 0
#define FLUSH_LINE 1
#define FLUSH_ALL 2typedef struct IO_FILE
{int fileno; //文件fd                                                       int flag;//输入缓冲区//char inbuffer[SIZE];//int in_pos;//输出缓冲区char outbuffer[SIZE];    int out_pos;    
}_FILE;_FILE* _fopen(const char* filename, const char* mode);
int _fwrite(_FILE* fp, const char* s, int len);
void _fclose(_FILE* fp);
void _fflush(_FILE* fp);#endif

然后我们定义FILE类型的结构体。 但是为了区分标准库。 我们这里改成_FILE(以后的函数等等为了区分都会加上"_")。

        对于这个结构体里面的内容, 根据我们前面讲到的只是可以知道, 这里面一定有两个字段一个是文件描述符fd, 一个是文件缓冲区。 这里我们先将fd包含进来。如下图:

 

然后我们就可以先简单的实现一下fopen, fwrite, fclose函数了。

fopen

如下为代码:

_FILE* _fopen(const char* filename, const char* mode){//先打开文件                       //open函数打开文件, 返回文件描述符。第二个参数是打开方式//先判断打开文件的方式。确定第二个参数                                   int f = 0;                int fd = -1; //一开始令fd 为-1if (strcmp(mode, "w") == 0) f = (O_CREAT|O_WRONLY|O_TRUNC); else if (strcmp(mode, "a") == 0) f = (O_CREAT|O_WRONLY|O_APPEND);else if (strcmp(mode, "r") == 0) f = (O_RDONLY);else return NULL;//打开文件, 默认权限是FILEMODEfd = open(filename, f, FILEMODE);//如果fd是-1, 那么直接return。 否则就是正常打开文件。 正常进行操作if (fd == -1) return NULL;//else                          _FILE* fp = (_FILE*)malloc(sizeof(_FILE));if (fp == NULL) return NULL;//如果fp == NULL说明空间不够了。//elsefp->fileno = fd;//让将fd赋值给fp的fd。return fp;}

fwrite

 如下为代码:

 int _fwrite(_FILE* fp, const char* s, int len)                             {//fd, 要写入的字符串, 字节长度return write(fp->fileno, s, len);}

 fclose

如下为代码:

  //关闭文件                     void _fclose(_FILE* fp)        {                              if (fp == NULL) return;      close(fp->fileno);           free(fp);                    }   

 我们自己实现一串代码进行测试, 打开的方式是清空写:

运行结果如下:

         其实从上面的代码我们就能看到封装的好处。 有了fopen, fwrite这些封装之后, 以后再向文件中写内容, 我们想要修改写入的方式, 就不需要再使用O_RONLY、O_WRONLY这些标志了, 直接使用w, a, r, 然后程序就会自动帮助我们判断如何打开文件!!!

c语言的跨平台性

        我们在上面实现的接口是符合linux环境的接口。 如果我们再windows下, 想实现同样的接口, 那么为了能够在windows正常工作,就要实现一份适合在windows下面跑的代码。 同样的macos也是一样的。 这三份代码我们可以使用if else if, endif条件编译。 如果在linux下面就是用linux下面的代码。 如果在windows下面就是用windows下面的代码。 如果在macos下面, 就是用macos下的代码。 这个就叫做c语言的跨平台性!!!

带缓冲区的c语言接口

我们在我们的接口里面加入缓冲区, 下图是引入缓冲区的方法。图中的in_pos和out_pos是为了标记缓冲区的使用情况。 它指向缓冲区已经使用的最后一个位置。 这个位置的左边是已经使用的, 右边是没有使用的。而且由于我们此次模拟实现的接口用不到输入缓冲区, 所以将输入缓冲区注释掉。

接下来我们修改我们的代码:

fopen 

      首先修改fopen, 要初始化缓冲区, 那么就是将标记缓冲区使用情况的out_pos置为0. 就代表缓冲区没有被使用过。 并且我们要初始化缓冲区的刷新方案。也就是_FILE结构体里面的flag。 我们这里默认初始化为行刷新, 下图的黄色代码就是初始化缓冲区。(只需要在原本的fopen下面添加黄色框框的代码就可以实现)

fwrite

        如下图是写方法的含有缓冲区的实现方式。 就是先将数据拷贝到缓冲区中, 然后判断刷新方式, 是直接刷新, 行刷新还是缓冲区满才刷新。刷新后标记位out_pos置为0.

下面是代码:

//写方法int _fwrite(_FILE* fp, const char* s, int len){//使用memcpy将数据拷贝到输出缓冲区中。 memcpy(&fp->outbuffer[fp->out_pos], s, len);fp->out_pos += len;//判断刷新方式//直接刷新if (fp->flag == FLUSH_NOw){write(fp->fileno, fp->outbuffer, fp->out_pos);fp->out_pos = 0;}                                                                        //遇到反斜杠n刷新else if ((fp->flag == FLUSH_LINE) && (fp->outbuffer[fp->out_pos - 1] == '  \n')){//只要遇到反斜杠n就行刷新write(fp->fileno, fp->outbuffer, fp->out_pos);fp->out_pos = 0;}else if (fp->flag == FLUSH_ALL && fp->out_pos == SIZE) {write(fp->fileno, fp->outbuffer, fp->out_pos);fp->out_pos = 0;}else return len;return len;}

fclose

关闭文件和之前没有什么区别

 

测试:

         我们可以使用下面这个监控脚本, 以及我们要测试的代码, 来测试一下我们模拟实现的是否正确:

#include"_my_func.h"    
#include<unistd.h>    int main()    
{    _FILE* fp = _fopen("mytest.txt", "a");    if (fp == NULL) return 1;    int cnt = 10;    const char* mes = "hello linux\n";    while (cnt)    {    _fwrite(fp, mes, strlen(mes));    sleep(1);    cnt--;    }    _fflush(fp);                                                               _fclose(fp);    return 0;    
}    

运行结果如下, 因为我们是以行刷新, 并且每一秒都会追加一行。 所以会出现下图的情况。 验证结果我们的代码是正确的。

 

fflush

        fflush这里我们也要模拟一下, 博主模拟是为了应对全刷新的情况(并不是说fflush只是为了应对全刷新而存在的)。因为我们使用全刷新的时候, 写到缓冲区的内容不容易被刷新出来。就如同下图我们已经运行了程序, 但是仍旧刷新不出东西, 也就是没有向文件写入:

        那么实现fflush, 我们要怎么实现呢?代码如下图:

代码: 

void _fflush(_FILE* fp){if (fp->out_pos > 0) {                                                                        write(fp->fileno, fp->outbuffer, fp->out_pos);fp->out_pos = 0;}}//关闭文件 
E>void _fclose(_FILE* fp){if (fp == NULL) return;_fflush(fp);//因为关闭文件要将缓冲区中的东西都放出来。close(fp->fileno);free(fp);}

         我们在运行就能在10秒胡进程退出的时候打出来了。下图就是测试——前十秒没有打印任何东西, 但是后面打印了一串数据。 这是因为进程退出的时候刷新了缓冲区。

以上就是本节的全部内容。 下面是博主的笔记:

 

相关文章:

linux文件——用户缓冲区——概念深度理解、IO模拟实现

前言&#xff1a;本篇文章主要讲解文件缓冲区。 讲解的方式是通过抛出问题&#xff0c; 然后通过分析问题&#xff0c; 将缓冲区的概念与原理一步一步地讲解。同时&#xff0c; 本节内容在最后一部分还会带友友们模拟实现一下c语言的printf&#xff0c; fprintf接口&#xff0c…...

Selenium模拟鼠标滚动页面:实现自动化测试中的页面交互

Selenium模拟鼠标滚动页面&#xff1a;实现自动化测试中的页面交互 在进行网页自动化测试时&#xff0c;经常需要模拟用户的滚动行为来加载更多内容或触发页面上的某些交互。Selenium WebDriver提供了强大的工具来模拟这些用户行为&#xff0c;包括鼠标滚动。本文将介绍如何使…...

Eureka原理与实践:构建高效的微服务架构

Eureka原理与实践&#xff1a;构建高效的微服务架构 Eureka的核心原理Eureka Server&#xff1a;服务注册中心Eureka Client&#xff1a;服务提供者与服务消费者 Eureka的实践应用集成Eureka到Spring Cloud项目中创建Eureka Server创建Eureka Client&#xff08;服务提供者&…...

OpenJDK 和 OracleJDK 的区别、下载方式

OpenJDK 和 OracleJDK 都是 Java 开发套件 (JDK)&#xff0c;用于开发和运行 Java 应用程序。它们之间的主要区别如下&#xff1a; 许可证和使用限制&#xff1a; OpenJDK&#xff1a;由 OpenJDK 社区开发和维护&#xff0c;基于 GPL v2 with Classpath Exception 许可证&#…...

arthas源码刨析:arthas-core (2)

文章目录 attach JVMagent**ArthasBootstrap** arthas-core的启动可以从上一篇做参考 参考 pom&#xff0c;即启动是调用的 Arthas 的 main 方法 attach JVM JVM提供了 Java Attach 功能&#xff0c;能够让客户端与目标JVM进行通讯从而获取JVM运行时的数据&#xff0c;甚至可以…...

【分享】格力手机色界G0245D 刷REC、root、 救砖、第三方rom教程和资源

开门见山 帮别人弄了一台 格力G0245D&#xff0c;把找到的资源和教程分享一下 教程 这个写的很详细了格力手机色界G0245D-Root-最简指南 不过教程里刷rec这一步漏了加上电源键&#xff0c;加上就行了。 附加参考&#xff1a;格力手机2刷机 格力手机二代刷机 GREE G0215D刷机…...

开学必备清单来啦!大学好物合集推荐!每一个都能帮你提升幸福感

随着开学季的到来&#xff0c;好多学生都在忙着准备各类学习与生活必需品&#xff0c;以迎接新的大学生活到来。以下是一些开学季必备的好物推荐&#xff0c;每一个都很实用&#xff0c;可以帮你提升学习和生活的幸福感&#xff01; 1、西圣电容笔 一句话推荐&#xff1a;公认…...

已解决:javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!!

1. 问题描述 javax.xml.transform.TransformerFactoryConfigurationError 是在使用 Java 的 XML 处理库时&#xff0c;配置 TransformerFactory 出错时抛出的异常。通常&#xff0c;这个异常发生在应用程序试图创建一个 TransformerFactory 实例时&#xff0c;由于无法找到合适…...

商品价格与优惠信息在API返回值中的位置

在API返回值中&#xff0c;商品价格与优惠信息的具体位置可能因不同的电商平台和API设计而有所不同。然而&#xff0c;一般来说&#xff0c;这些信息会以结构化的方式呈现&#xff0c;通常包含在一个包含多个字段的JSON对象或XML文档中。以下是根据多个电商平台&#xff08;如阿…...

Oracle Index Partition索引分区的管理

Oracle索引分区的管理是数据库管理中的重要任务之一&#xff0c;它涉及索引的创建、维护、重建以及优化等多个方面。以下是对Oracle索引分区管理的详细解析&#xff1a; 一、索引分区的概念 索引分区&#xff08;Partitioned Index&#xff09;是针对分区表而言的&#xff0c…...

统信UOS系统访问windows共享目录

问题背景 当我们使用UOS系统的时候&#xff0c;想要访问windows系统的一些资料并将其拷贝下来使用的话&#xff0c;应该怎么操作呢&#xff1f;这个需求是可以实现的&#xff0c;统信UOS系统是基于Linux系统开发的&#xff0c;Linux系统和windows系统之间可以通过SMB协议来共享…...

单一职责原则与REST API设计:如何定义清晰的资源与职责

在软件设计中&#xff0c;单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09;和 REST API 设计是两个重要的概念。单一职责原则是一种设计原则&#xff0c;它强调一个类或模块应当只有一个单一的职责&#xff0c;这有助于提高系统的可维护性和扩展性。…...

JAVA IO模型

我们在平常开发过程中接触最多的就是 磁盘 IO&#xff08;读写文件&#xff09; 和 网络 IO&#xff08;网络请求和响应&#xff09;。从应用程序的视角来看的话&#xff0c;我们的应用程序对操作系统的内核发起 IO 调用&#xff08;系统调用&#xff09;&#xff0c;操作系统负…...

《C/C++实战专栏》介绍

&#x1f680; 前言 本文是《C/C实战专栏》专栏的说明贴&#xff08;点击链接&#xff0c;跳转到专栏主页&#xff0c;欢迎订阅&#xff0c;持续更新…&#xff09;。 专栏介绍&#xff1a;以多年的开发实战为基础&#xff0c;总结并讲解一些的C/C基础与项目实战进阶内容&…...

前端跨域2

前端跨域2 前端跨域解决方案&#xff08;11种方案&#xff09; 1.JSONP跨域解决方案的底层原理 script、img、link、iframe...<script src"https://cdn.bootcss.com/jquery/3.4.1/core.js"></script>// 这个就是因为script标签没有跨域限制&#xff0…...

electron仿微信,新建贴合窗口

说明 在写electron项目时&#xff0c;只有一个主窗口不足以满足需求&#xff0c;我们通常还会打开很多个窗口。 怎么打开一个子窗口像微信的聊天界面一样&#xff0c;全贴合在一起&#xff0c;看起来像一个整体呢&#xff1a; 分析 这个窗口有点像element ui中的抽屉(drawe…...

uniapp微信小程序 分享功能

uniapp https://zh.uniapp.dcloud.io/api/plugins/share.html#onshareappmessage export default {onShareAppMessage(res) {if (res.from button) {// 来自页面内分享按钮console.log(res.target)}return {title: 自定义分享标题,path: /pages/test/test?id123}} }需要再真机…...

Java实现数据库数据到Excel的高效导出

在数据处理和分析工作中&#xff0c;经常需要将数据库中的数据导出到Excel文件中。本文将提供一个Java实现的示例&#xff0c;展示如何边从数据库读取数据&#xff0c;边将其写入Excel文件&#xff0c;同时注重内存效率。 环境配置&#xff1a; Java 1.8 或更高版本MySQL 5.7…...

python之matplotlib (8 极坐标)-圆与心

极坐标 极坐标图像的绘制类似于三维图像的绘制&#xff0c;只需要将projection参数由3d改为polar即可。 import numpy as np import matplotlib.pyplot as plt figplt.figure() axfig.add_subplot(projectionpolar)theta np.linspace(0, 2 * np.pi, 100) r np.sin(the…...

Kubernetes Pod调度基础

在传统架构中&#xff0c;我们总在考虑或者面临一个问题&#xff0c;我们的应用需要部署在哪里&#xff0c;我们的应用下载在哪里运行着?有一个服务不可访问了&#xff0c;去哪里排査?诸如此类的问题总是会出现在工作中。 但是在使用 Kubernetes 部署应用后&#xff…...

80页WORD方案深入了解大数据治理+大数据资产管理+数据运营

文档是一份80页可编辑的企业大数据智能管理与治理平台建设项目技术方案标书文档&#xff0c;涵盖了从项目需求分析、技术方案、建设方案、服务方案到类似案例介绍等多个方面的内容。 1. 项目需求分析 项目建设目标&#xff1a;旨在实现数据的可视化&#xff0c;确保决策者、行…...

OCC安装、VS2019编译运行(新手教程)

OCC安装、VS2019编译运行(新手教程) 简介1、OpenCasCade的下载和安装官网下载安装2、OpenCasCade的运行和编译(VS2019)修改配置文件环境变量配置3、验证代码项目配置运行cpp文件简介 作为一个刚接触OCC的程序员,可能会不知所措,无从下手,甚至在OCC的安装使用都困难重重…...

Mojo 实现排序功能

sort排序 实现排序功能。 您可以从包中导入这些 API。例如&#xff1a;algorithm from algorithm.sort import sortpartition partition[type: AnyRegType, cmp_fn: fn[AnyRegType]($0, $0, /) capturing -> Bool](buff: Pointer[*"type", 0], k: Int, size: …...

信息学奥赛一本通编程启蒙题解(3031~3035)

前言 Hello大家好我是文宇 正文 3031 #include<bits/stdc.h> using namespace std; double n,m,x; int main(){cin>>n>>m;xn-m*0.8;cout<<fixed<<setprecision(2)<<x;return 0; } 3032 #include<bits/stdc.h> using namespace…...

字符函数内存函数———C语言

字符分类函数 头文件&#xff1a; ctype.h 函数功能iscntrl判断字符是否为控制字符isspace判断字符是否为空白字符&#xff08;空格&#xff0c;换页、换行、回车、制表符或垂直制表符&#xff09;isdigit判断字符是否为十进制数字isxdigit判断字符是否为十六进制数字(0-9)(a…...

c语言跨文件传输数据

在 C 语言中&#xff0c;可以通过以下几种方式获取其他 C 文件中定义的变量&#xff1a; 一、使用 extern 关键字 在需要获取变量的文件中&#xff0c;使用extern关键字声明该变量。 例如&#xff0c;如果在other.c文件中有一个全局变量int globalVar;&#xff0c;在当前文件中…...

企业文件防泄密怎么做?10款透明加密软件排行榜

在信息时代&#xff0c;企业的核心竞争力往往体现在其拥有的知识和信息上&#xff0c;而企业文件的安全性直接关系到这些信息的保护。文件防泄密已成为企业管理中的重要议题&#xff0c;透明加密技术因其无缝集成和高效保护的特性&#xff0c;成为企业防泄密的首选方案。2024年…...

AI编程工具的力量:以AWS Toolkit与百度Comate为例,加速程序员开发效率

在当今的数字化转型浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术不仅重塑了众多行业&#xff0c;也为软件开发领域带来了革命性的变化。AI编程工具&#xff0c;凭借其智能化的特性&#xff0c;正在成为程序员提高开发效率、优化代码质量和加速产品迭代的重要助力…...

smallpdf: 免费高效的PDF水印添加工具

引言 在数字文档管理和分享的过程中&#xff0c;保护版权和确保文档的原创性变得尤为重要。PDF文件作为一种广泛使用的格式&#xff0c;经常需要添加水印来表明所有权或提醒查看者注意文档的敏感性。本文将介绍一款名为smallpdf的免费工具&#xff0c;它能够轻松地为PDF文件添…...

java整合modbusRTU与modbusTCP

理解 Modbus TCP 报文格式,Modbus TCP 报文格式如下: | Transaction ID (2 bytes) | Protocol ID (2 bytes) | Length (2 bytes) | Unit ID (1 byte) | Function Code (1 byte) | Data (N bytes) |Transaction ID:标识事务的唯一标识符,确保正确的 Transaction ID:每个请求…...

泰安直聘网官网/seo搜索引擎优化排名

工厂模式之观察者模式...

做公众号链接的网站/百度收录比较好的网站

Dreamweaver CC 2019 for mac是Web设计人员和开发人员设计必备的软件&#xff0c;dw 2019 mac破解版支持HTML、CSS、JavaScript等&#xff0c;功能十分强大&#xff0c;可以轻松帮助用户设计精美的网站网页&#xff0c;这次Dreamweaver cc 2019 mac破解版主要针对安全性增强功能…...

猎趣网站/武汉网站排名提升

今天和大家聊聊泛型在容器中存在的安全问题&#xff0c;我们先来看一个例子。 public class Pet {}public class Dog extends Pet {}public class Cat extends Pet {}public class PelList {public static void main(String[] args) {List dogs new ArrayList<Dog>();d…...

怎么推广自己的微信号/seo是什么意思职业

电商的秒杀功能是现在电商系统的主流功能&#xff1b; 参加过电商秒杀的都知道&#xff0c;有时候会遇到商品明显没有了&#xff0c;用户还可以下单导致秒杀商品的库存时常为负数。 秒杀系统就是典型的、短时间的、大量的、突发访问&#xff1b;这样的短时大并发的系统&#…...

东营做网站优化公司/长沙seo推广外包

F1官方日前宣布F1电竞全球锦标赛将连续第四年盛大举行&#xff0c;今年资格赛参赛人群破纪录超23.7万人&#xff0c;赛事总奖金也飙升至75万英镑。与此同时&#xff0c;F1电竞中国冠军赛个人挑战赛也全面开启报名&#xff0c;中国的模拟赛车爱好者们同样可以在虚拟赛道上&#…...

益阳 网站制作维护/优化的含义

在使用STM32的hal库的时候&#xff0c;我们常常可以看到很多库自带的函数有很多是使用__weak修饰的&#xff0c;比如&#xff1a; 这个修饰符的作用是什么呢&#xff1f; 函数名称前面加上__weak 修饰符&#xff0c;我们一般称这个函数为“弱函数”。 加上了__weak 修饰符的…...