【Linux】-文件操作(重定向、缓冲区以及Linux下一切皆文件的详解)

news2024/11/24 17:30:24

在这里插入图片描述

💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、以c语言为例,认识一下之前的接口
  • 二、过度到系统,再谈文件系统调用
  • 三、访问文件的本质
  • 四、重定向的原理介绍
  • 五、理解Linux下一切皆文件。
  • 六、缓冲区
  • 七、总结


前言

今天博主来讲一篇大家以前很害怕的但又不得不说的一个的一个知识点–文件管理,再我们c语言的时候,博主就给大家介绍过文件操作,那时候我们使用过很多函数去对文件操作,而我们又不怎么去使用这些函数,所以又熟悉又陌生,今天我们又把文件拿出来讲,远远不至于之前的哪些内容,博主讲深入系统层面来给大家进行讲解,让大家明白我们之前的函数是怎么去操作的,会解决大家很多疑惑,话不多说我们开始进入正文讲解。


共识原理

  1. 文件=内容+属性
  2. 文件分为打开的文件和没打开的文件
  3. 打开的文件,是谁打开的?? 答案是进程,所以我们后面讨论的是进程和文件的关系
  4. 没打开的文件,在哪放着的?答案是磁盘上。没打开的文件最关注的问题是什么? 答案是没打开的文件很多,这样就要我们把文件分类好,管理起来,就必须先描述在组织才能方便我们后面对文件的增删查改操作,所以在系统里面必须又关于文件管理的属性指针,来指向这样文件,方便管理。
  5. 打开的文件是由进程加载到内存的,一个进程可以打开多个文件所以是1:n的关系,此时进程也需要把他打开的文件管理起来,才知道哪些文件是他自己打开的,最后才有办法关闭。

针对4,5点的管理我们一会再正文部分给大家具体介绍,并画出详细的图。上面的我相信大家应该都可以理解,可以理解为人(进程),快递(文件),驿站(磁盘)的关系。


一、以c语言为例,认识一下之前的接口

我们只看写文件,因为读文件没有什么好看的。再进行一个文件操作的时候,需要先打开一个文件,我们来回顾一下c语言的打开文件操作
在这里插入图片描述

在这里插入图片描述
第一个参数是写入的内容字符串,第二个参数是内容多大,第三个参数是写几个这样的,第四个是要传打开的文件

w方式:

#include<stdio.h>
#include<string.h>
int main()
{
    FILE* fp=fopen("login.txt","w");
    if(fp==NULL)
    {
        perror("fopen");
        return -1;
    }

    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,fp);
    fclose(fp);
    return 0;
}

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

我们看到效果和我们文档里面是一样的,如果没有的文件会在当前路径自动创建一个,而每次打开文件都会先清空文件,再进行写入,通过第三个图我们也发现和写不写内容没有关系,只要每次重新打开就会情空。

a方式:

#include<stdio.h>
#include<string.h>
int main()
{
    FILE* fp=fopen("login1.txt","a");
    if(fp==NULL)
    {
        perror("fopen");
        return -1;
    }

    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,fp);
    fclose(fp);
    return 0;
}

在这里插入图片描述

结果和文档的效果是一样的,没有文件就会在当前路径创建新的文件,然后每次打开就会再文件的末尾追加内容。


解决疑惑
(1)在fwrite的时候我们传的strlen(msg),此时需不需要加+1.就是这个\0的长度要不要加上去,我们加一下看看结果:
在这里插入图片描述

我们打开文件发现会出现乱码,说明/0确实被写进去了,因为我们的vim是文本解析器,所以会出现乱码,那我们到底要不要加1呢,答案是不要的,这一看就是不对了,注意:\0是c语言层面的为了给字符串作为结束标志的,而写入文件只需要把有效字符写进去就行了,这个\0和文件是没有关系的,所以不用写进去

(2)fopen的两种方式中博主都提到了当前路径,是怎么做到的,修改当前路径会不会在其他路径下创建,来看演示:
在这里插入图片描述
我们来使用一个系统函数改变当前路径
在这里插入图片描述

博主讲当前路径改成上一级路径,我们发现创建的文件就跑到上一级文件了。可以通过这样的方式来改变当前路径。

---------------------------------------------------------------------------------------------------------------------------------
通过上面介绍的两种方式,我们还能想起来什么??
之前是不是说过重定向,一个输出重定向,一个追加重定向,都是往文件里面写内容,那么可以这样理解,我们的重定向的第一步肯定是要打开文件,输出和追加的区别就是打开方式的不同,但肯定是类似于上面的方式去实现的,再这里大家心里面现有一个印象,这个后面我会再重点谈的。

铺垫:

我们的c语言会默认打开三个FILE类型的文件
在这里插入图片描述
他们在stdio.h里面,这也是我们一开始学习c语言就要包含这个文件的原因

Linux下一切皆文件,所以这三个分别对应的是:键盘文件,显示器文件,显示器文件
我们来使用函数往这些文件里面写点东西

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,stdout);
    return 0;
}

在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char*msg="hello,file";
    fprintf(stderr, "%s: %d\n", msg, 1234);
    return 0;
}

在这里插入图片描述
stdin是键盘文件,不好演示的,可以从键盘读取数据,一会回过头来给大家演示。

这三个默认打开的文件我一会再回头过来讲。

二、过度到系统,再谈文件系统调用

再一开始的共识中,博主就说到文件没被打开时候是在磁盘上的,磁盘是外部设备,也就是硬件,所以访问磁盘文件就是再访问硬件,我们的用户通过库函数去打开文件就比如先经过系统调用接口,去让操作系统去访问硬件资源,操作系统不信任任何用户,而os又是管理着硬件资源,所以必须经过os这一关,几乎所有的库只要访问硬件设备,必定要封装系统调用 我们之前学的printf/fprintf/fscanf/fwrite/fread/fgetc/fopen/fclose都需要封装系统调用接口。

(1)打开文件的系统调用接口open
在这里插入图片描述
在这里插入图片描述

这个函数在二号手册,所以属于系统调用函数,调用失败返回-1
我们的第一个参数是打开的文件,第二个参数类似于位图操作,接下来使用一个例子带大家看看这个是什么:

#define ONE (1<<0) // 1
#define TWO (1<<1) // 2
#define THREE (1<<2) // 4
#define FOUR (1<<3) // 8

void show(int flags)
{
    if(flags&ONE) printf("hello function1\n");
    if(flags&TWO) printf("hello function2\n");
    if(flags&THREE) printf("hello function3\n");
    if(flags&FOUR) printf("hello function4\n");
}



int main()
{
    printf("-----------------------------\n");
    show(ONE);
    printf("-----------------------------\n");
    show(TWO);
    printf("-----------------------------\n");

    show(ONE|TWO);
    printf("-----------------------------\n");
    show(ONE|TWO|THREE);
    printf("-----------------------------\n");
    show(ONE|THREE);
    printf("-----------------------------\n");
    show(THREE|FOUR);
    printf("-----------------------------\n");
}


在这里插入图片描述
博主在文档中圈出来的一些宏定义就是表示功能通过声明也大致可以看出大致含义.


第三个参数是类型,给文件设置什么样的权限,默认是666,但是有掩码,我们看到的就是664,如果我们就像让文件变成默认的666,那么就要修改掩码,但是不要修改其他文件的默认,所以需要在打开这个文件的进程里面修改,使用umask函数就可以了。

(2)再来看看写入的函数:
在这里插入图片描述
这个函数其实和库函数有点像,一会看使用,具体参数博主就不做具体介绍了

来具体看看库函数是怎么使用的:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int  main()
{
    umask(0);//设置掩码为0
    //系统的掩码和这里的掩码程序因该听谁的,答案是谁进听谁的,不会更改系统的掩码。
    int fd=open("login2.txt",O_WRONLY,0666);
    if(fd<0)
    {
        perror("open");
        return 0;
    }
    char*msg="hello,fd\n";
    write(fd,msg,strlen(msg));//这个同样不需要加1
    return 0;
}

在这里插入图片描述


为什么没有打开成功呢,原因是打开文件的使用的功能就是O_WRONLY,必须要在加一个功能

  int fd=open("login2.txt",O_WRONLY|O_CREAT,0666);

在这里插入图片描述


(1)实现w的效果

  int fd=open("login2.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);

在这里插入图片描述
(2)实现a的效果
O_APPEND这是追加功能,所以不能和O_TRUNC同时使用,这两个是冲突的。

 int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);

在这里插入图片描述
我们讲系统调用接口给大家演示了,大家也知道了我们系统调用接口的功能更加的全面,但是此时我不在给大家介绍内容了,我先讲下面一个主题

三、访问文件的本质

我们刚才使用了open这个函数,他的返回值fd,在write里面也需要传fd,那么fd到底是什么,答案是文件描述符(数组的下标)

接下来通过一幅图给大家介绍
在这里插入图片描述
接下来博主在进程里面再多创建几个文件,看看打印出来的fd是什么,和我们预期画图是不是一个效果:

int  main()
{
    umask(0);//设置掩码为0
    int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd1=open("login3.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd2=open("login4.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd3=open("login5.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd4=open("login6.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    if(fd<0)
    {
        perror("open");
        return 0;
    }
    printf("fd:%d\n",fd);
    printf("fd1:%d\n",fd1);
    printf("fd2:%d\n",fd2);
    printf("fd3:%d\n",fd3);
    printf("fd4:%d\n",fd4);
    return 0;
}

在这里插入图片描述

umask(0);//设置掩码为0

    close(0);//这个一会再说
    int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd1=open("login3.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd2=open("login4.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd3=open("login5.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    printf("fd:%d\n",fd);
    printf("fd1:%d\n",fd1);
    printf("fd2:%d\n",fd2);
    printf("fd3:%d\n",fd3);
    return 0;

在这里插入图片描述

确实和我们分析的一样。会再数组里面找没有使用并且下标最小的位置讲打开的文件信息填进去

提出疑问:回顾铺垫
我们的0 1 2这三个下标呢??大家还记不记得上面的铺垫,我们的c语言程序默认打开第三个文件,那这三个下标会不会就对应着三个文件呢,我们来通过实验演示一下,我们猜想他们是按照的文档的方式先后打开的。
stdin(0),stdout(1),stderr(2)

stdin(0)

int main()
{

    char buffer[1024];//0下标,我们默认是stdin
    ssize_t s = read(0, buffer, sizeof(buffer));//从键盘文件上只能读取数据,所以使用系统接口read,
                                                //虽然没有介绍过,但是大家看一下文档应该就会使用
    if(s < 0) return 1;
    buffer[s] = '\0';//因为从键盘读取到的只是有效字符,所以需要手动给字符数组加一个结束标志
    printf("echo : %s\n", buffer);
    return 0;
}

在这里插入图片描述

stdout(1),stderr(2)
这两个都指向显示器文件,就一起展示了

  const char *msg = "hello Linux\n";
  write(1, msg, strlen(msg));
  write(2, msg, strlen(msg));

在这里插入图片描述

结论出来了,那我们的c程序默认打开的三个文件是c语言的特性吗,肯定不是啊,这是os的特性,C语言拿来用了而已,**那为什么要默认打开这三个文件呢??**原因是我们的掉闹再一打开对应的键盘显示器就被加载了,这样程序员才能进行写代码,这是天然决定的

既然我们的c语言要支持这样默认打开的文件,那他必定要对fd进行封装,因为系统调用接口都是通过fd来对文件进行操作的,所以我们看到的FILE他是什么??是不是就是我们C语言里面的结构体,我们通过->来访问一下fd:

 printf("stdin:%d\n",stdin->_fileno);
 printf("stdout:%d\n",stdout->_fileno);
 printf("stderr:%d\n",stderr->_fileno);

在这里插入图片描述

看到这里大家对默认打开的文件是不是有了更深的了解了,大家可以自己下去测试关掉着三个默认的文件,还可不可以从键盘或者显示器进行操作,博主就不演示了,博主接下来带大家回过头来分析那幅图,我么再测试的默认打开的文件的时候,有两个文件都是显示器,那我们再关闭文件的时候,是怎么操作的:
在这里插入图片描述
我们的文件结构体里面有一个引用计数,他每次关闭,对应的文件的引用计数就会减减,到0此会真的关闭。我给大家测试一下:
const char *msg = "hello Linux\n";
write(1, msg, strlen(msg));
close(1);//关闭显示器文件
write(2, msg, strlen(msg));
在这里插入图片描述
结果即使关闭了1指向的显示器文件,但是显示器文件还是可以用的,原因就是close并没有关闭,只是将引用计数减减了。


四、重定向的原理介绍

大家如果从上面一直看下来应该知道我提到过重定向的内容,再铺垫之前就提到过,我们演示过w和a方式之后,往文件里面写东西,和重定向的效果是一样的,但是这节博主将带大家看看原理,再将这个之前,我先给大家讲解一下fd的分配规则,这个再上面也提到过

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{

    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

int main()
{
	close(2);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

int main()
{
	close(1);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

通过前两个案例,我们可以看出,fd的分配规则是找文件描述符表里面下标最小并且为空的位置放我们先打开的文件,我们的fd是1或者2都是指向显示器文件,为什么第三个案例和第二个案例却结果不太,第三个案例没有打印出fd的数值,原因是printf他的功能是往fd=1这个文件上打印文件的,而关闭1了就显示不了。

我们再来写一个例子:

int main()
{
    
    close(1);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    
    const char*msg1="hello normal file\n";
    int cnt=5;
    while(cnt--)
    {
        write(1,msg1,strlen(msg1));
    }

    close(fd);
    return 0;
   }

在这里插入图片描述
我们看到我们打开log文件,万一往显示器上写内容,但是最后结果没有在显示器上显示,而是写道文件里面的,这是为什么??

来看图解:
在这里插入图片描述

这就是输出重定向

int main()
{
    
    close(0);
    int fd=open("log.txt",O_RDONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
   char inbuffer[1024];
    ssize_t s = read(0, inbuffer, sizeof(inbuffer)-1);
    if(s>0)
    {
        inbuffer[s] = '\0';
        printf("echo# %s\n", inbuffer);
    }
	close(fd);
	return 0;
}

在这里插入图片描述

本来是从键盘上读取文件,结果却从log.txt里面读取了,这就是输入重定向。

**特点:**上面两种重定向演示的特点都是,打log.txt文件,想在默认打开的三个文件进行写操作和读操作,但是结果都最后都是操作到log.txt上,原因就是充重定向。上面的办法,先关闭一个文件这样太不好看了,有没有系统函数专门做这样的事情呢??

dup2函数
在这里插入图片描述

int main()
{

    int fd=open("log.txt",O_RDONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    dup2(fd,0);
   char inbuffer[1024];
    ssize_t s = read(0, inbuffer, sizeof(inbuffer)-1);
    if(s>0)
    {
        inbuffer[s] = '\0';
        printf("echo# %s\n", inbuffer);
    }
	close(fd);
	return 0;
}

在这里插入图片描述
也达到了相同的效果,接下来具体介绍一下函数的构成

这个参数的设计有点不和人情。
在这里插入图片描述
将oldfd拷贝到newfd上面,这里的oldfd就是新建的文件log.txt,newfd是你要拷贝的文件,最后再文件描述符表中会有两块位置的值是相同的,都是oldfd,这里面的拷贝不是下标拷贝,下标不可能有两个一样的,是将下标里面的内容拷贝,说这个参数的名字不好的原因是,新建的log.txt按道理比默认的文件后创建,他的fd应该是newold,结果看这个参数就跟搞反了一样。但也没办法,我们适应这个函数之后可以把oldfd给关闭,也可以不关闭,看你个人,这个函数的使用就比之前的方法好很多,一眼就能看出来你要干什么,博主会再下篇给大家写一个简单的shell给大家演示怎么默认实现命令行上面的重定向功能。

---------------------------------------------------------------------------------------------------------------------------------
我想在给大家解决一下心中的小疑惑,我们的os再启动的时候就会默认打开三个文件,但是其中有两个fd指向显示器文件,stdout(1),stderr(2),现在要解决的就是1 & 2的区别是什么??

博主先来写一段代码:

int main()
{

    const char*msg1="hello normal file\n";
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));

    const char*msg2="hell err file\n";
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    return 0;
}

我们看到两个效果是一样的

在这里插入图片描述

我们使用了重定向将1显示器文件和normal.log文件进行重定向,所以本来输出在显示器的内容重定向到normal.log文件里面了,而strerr是2显示器文件,和我没关系,默认的是把1显示器和别的文件进行重定向。下面的和上面的一样。
在这里插入图片描述


在这里插入图片描述

我们可以实现日志的分开写入,其实在本质上两者没有区别,但是为了分流去干一些是,就必须弄两个,方便分流操作。如果不想实现分流,就使用下面的方法:
在这里插入图片描述
先执行./mytest > normal.log 因为已经重定向了1号下标位置的值就是normal.log的内容,在通过&1就是把1号的内容给二号位置,此时如果一个文件都没有关闭,而且先创建normal.log文件的的话,那么1 2 3下标的内容都是3号下标里面normal.log,这样就可以写在同一个文件里面了。

至此我们的重定向就讲解完毕了,大家到时候来支持一下博主的手写shell程序吧。

五、理解Linux下一切皆文件。

在这里插入图片描述

大家好好的理解一下这个图,接下来给大家讲解缓冲区

六、缓冲区

相信这个名词大家在好久之前都听到过,但是只闻其人,未见其人,所以我们对缓冲区的概念还是非常模糊的,接下来我就带大家来看看这个缓冲区是什么。

提出问题:
什么是缓冲区?
为什么要有缓冲区??
缓冲区是怎么去工作的??
缓冲区在哪里?
这些问题我们之前都是不知道的,但是这节会给大家解决的。

首先我们来看一段代码:

#include<stdio.h>
#include<string.h>
int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";
    //c语言的接口
     printf("hello printf\n");
     fprintf(stdout, "hello fprintf\n");
     fwrite(fstr, strlen(fstr), 1, stdout);

	//系统调用的接口
     write(1, str, strlen(str)); 
    return 0;
}

在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";
    //c语言的接口
     printf("hello printf\n");
     fprintf(stdout, "hello fprintf\n");
     fwrite(fstr, strlen(fstr), 1, stdout);

    //系统调用接口
     write(1, str, strlen(str)); 

     fork();
    return 0;
}

在这里插入图片描述

通过着两个测试用例,大家看出来差别了吗??四个写入函数,在第一个代码中打印出来的效果来看,我相信大家没啥疑惑,但是不代表大家懂了为什么会出现这样的结果,但是第二个代码,我们在执行完上面四个代码之后再进行fork的,但是往显示器上打印还是四个,而往文件打印就成了7个,细心的通过会发现,只有c语言调用的函数接口都打印了两次,而系统调用函数接口只打印了一次,而且肯定和fork有关系,但是这个结果很让人理解。,但是这节讲的是缓冲区,所以和缓冲区肯定有关系

再来看一个案例:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

因为再第一次测试的时候,两次代码只有c语言函数的接口函数出现了不同的变化,所以这次的案例,为了测试一下c语言调用函数接口,我们发现,我们的三个函数都是往显示器上打印,而我的close是再三个函数执行完毕后再关闭的,按道理往屏幕上打印是不受影响的,而两次代码的差距就在于打印的字符串有没有带\n,通过结果也可以发现,我们的第三个图没有带close,结果显示出来了,说明再执行close之前,三个函数打印的数据肯定放在其他地方了(缓冲区),而通过第二个图来看,如果1号被关闭打印不出来很正常,但是重定向到文件当中,应该把数据放进去文件,结果却是文件里面没有,原因是我么们先执行程序,显示器的数据先执行完再重定向到文件里面而1号被关闭了,就重定向不了了,所以得出1号文件没有被关闭的时候,再程序退出的时候,就会通过其他位置(缓冲区)把数据通过1号文件打印出来,如果1号被关闭,那么这些数据就被自动清除了。

七、总结

我们上面学完了稳健操作,大家对文件的恐惧感应该减少不少了,而且以前经常出现的概念今天也很好的解释了一遍,理解上面不难,主要的还是大家要贯穿,每个知识点都是连着的,跳着看就会有地方不理解,所以需要一步步,有逻辑性的去学习,那今天的只是就分享到这里了,我们下篇讲解一下文件系统。

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

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

相关文章

使用Nokogiri库的Python程序

python import requests from bs4 import BeautifulSoup import os # 设置 proxies {"http": "", "https": ""} # 设置headers headers { User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (K…

SI24R2E应用于2.4G有源RFID养老院方案

随着人口老龄化的加剧&#xff0c;养老院、颐养小镇、养护院、疗养院等针对养老的机构可以说是层出不穷。而为了方便管理&#xff0c;这些养老机构都有一个共同点&#xff0c;实现无感式的人员定位以及物品管理等功能。 方案介绍 我司推出的2.4G有源RFID养老院方案&#xff0c;…

NOIP2000提高组第二轮T4:方格取数

题目链接 [NOIP2000 提高组] 方格取数 题目描述 设有 N N N \times N NN 的方格图 ( N ≤ 9 ) (N \le 9) (N≤9)&#xff0c;我们将其中的某些方格中填入正整数&#xff0c;而其他的方格中则放入数字 0 0 0。如下图所示&#xff08;见样例&#xff09;: 某人从图的左上…

学习c++的第十四天

目录 动态内存 new 和 delete 运算符 命名空间 定义命名空间 using 指令 不连续的命名空间 嵌套的命名空间 模板 函数模板 类模板 C 中 typename 和 class 的区别 函数模板的重载 动态内存 了解动态内存在 C 中是如何工作的是成为一名合格的 C 程序员必不可少的。…

二.ACW154. 滑动窗口详解

窗口滑动: 几行代表for里的语句 1行看队列,例子.空的不执行 2行q[0]1 3行看队列.1>-1不执行 4行看例子例子.窗口不完整 ht1,只看最后一行的总队列q就行1行.2<6不执行,只存越来越大 2行q[1]2,所以q存的下标 3行.i在增加,1>0不执行,新循环了,对头元素滑出窗口 4行窗口不…

使用Python自动修改电脑的静态IP地址

目录 一、引言 二、实现思路 三、详细步骤 四、Python代码 五、注意事项 六、适用性和局限性 七、总结 一、引言 在网络应用中&#xff0c;有时我们需要频繁更改电脑的静态IP地址。例如&#xff0c;当我们在不同网络环境&#xff08;家庭、办公室&#xff09;中使用电脑…

AMEYA360荣获“国际潜力之星分销商”奖!

由全球电子技术领域知名媒体集团ASPENCORE主办的“全球电子元器件分销商卓越表现奖"颁奖典礼于2023年11月3日晚在深圳大中华喜来登酒店圆满结束! 全球电子元器件分销商卓越表现奖创办于2001 年&#xff0c;迄今已成功举办20年&#xff0c;此奖项旨在表彰支持电子产业发展的…

电脑监控软件丨2023全网最详细解析

电脑监控软件是一个比较敏感的话题&#xff0c;因为很多员工会觉得电脑监控侵犯了自己的隐私&#xff0c;电脑上企业会觉得安装软件只不过是为了保护自己的核心利益。 对于此&#xff0c;我们要辩证的看待。 今天我们从企业的角度出发&#xff0c;谈谈电脑监控软件的话题。 必…

【数据结构】 二叉树理论概念!一文了解二叉树!

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; 数据结构解析 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言&#x1f324;️树的概念☁️树的结构☁️树的小知识☁️树的表示与运用 &#x1f324…

Android View 触摸反馈原理浅析

重写OnTouchEvent() 然后在方法内部写触摸算法 返回true,表示消费事件,所有触摸反馈不再生效,返回事件所有权 if (event.actionMasked MotionEvent.ACTION_UP){performClick()//抬起事件 执行performClick 触发点击 }override fun onTouchEvent(event: MotionEvent): Boolea…

办公套件全家桶 Office2019 mac中文版新功能

office 2019 mac是 Microsoft office 应用程序套件的最新版本。它包括流行的软件&#xff0c;例如 Microsoft Word、Excel、PowerPoint 和 Outlook&#xff0c;office 2019 比其前身有许多新功能和改进&#xff0c;包括增强的协作工具、与 OneDrive 和 SharePoint 等云服务的更…

Figma 怎么切图?新手入门教程详解

Figma 是一个基于浏览器的协作的UI设计工具&#xff0c;其以轻量、便捷、跨平台使用、协同便捷的特点&#xff0c;迅速吸引了广大UI/UX 设计师们的喜欢。但是设计师经常遇到反复切图、交付开发等问题&#xff0c;所以借此机会分享一篇关于 Figma 切图的必要知识点和交付经验。 …

基于 VTable 的多维数据展示的原理与实践

多维表格介绍 多维表格又名透视表、交叉表、Pivot Table&#xff0c;指的是可以在行维度和列维度放入一个或多个维度&#xff0c;显示维度之间相互关系的一种表格。用户可以一目了然地分析出各种场景指标以及对比&#xff0c;旨在帮助业务分析推动决策。 假设需要分析如下表格…

微信支付更换证书最详细方法

6、在【商户平台】&#xff0c;输入操作密码&#xff0c;安全验证后生成证书串 7、在【商户平台】&#xff0c;复制证书串 8、在【证书工具】&#xff0c;粘贴证书串&#xff0c;点击下一步&#xff0c;申请证书成功 &#xff08;若提示"证书与本地公私钥不匹配&qu…

window10 定时任务

window10 定时任务 1、背景2、目标3、思路4、实操4.1、设置定时任务4.2、配置策略4.3、验证 1、背景 项目上由于业务调试需要&#xff0c;开具了一台window10系统&#xff0c;此台window10为项目组公共使用&#xff0c;为防止误操作分配了不通的账号&#xff0c;日常使用各自账…

互联网校园洗衣洗鞋小程序;

互联网校园洗衣洗鞋小程序打造哪足不出户&#xff0c;线上下单上门取货&#xff0c;通过它不仅可以让用户快速便捷的找到小程序下单&#xff0c;在手机上准确的下发洗衣命令&#xff0c;还能洗好后提供取衣服务等&#xff0c;因此受到了广泛用户的喜爱。截止目前&#xff0c;软…

山西电力市场日前价格预测【2023-11-06】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-06&#xff09;山西电力市场全天平均日前电价为126.17元/MWh。其中&#xff0c;最高日前电价为405.20元/MWh&#xff0c;预计出现在18: 15。最低日前电价为0.00元/MWh&#xff0c;预计出…

深入了解Jedis:Java操作Redis的常见类型数据存储

目录 前言 一、Jedis介绍 1.Jedis在各方面的功能 2.特点 二、Java连接Redis 1.导入pom依赖 2.建立连接 三、Java操作Redis的常见类型数据存储 1.字符串 2.哈希表 3.列表 4.集合 5.有序集合 四、Redis的实际应用场景实例 1.会议信息实体 2.自定义注解 3.创建切面…

应用场景 | 中小河流治理监测系统,提升流域智能感知能力

当前&#xff0c;受全球气候变化和人类活动影响&#xff0c;我国中小河流洪涝灾害呈多发、频发趋势&#xff0c;中小河流洪水已成为严重威胁人民群众生命财产安全的重大风险隐患。中小河流治理作为一项重要的民生水利任务&#xff0c;近十年来国家不断加大以防洪为主的治理投入…

初始JVM虚拟机

JVM组成 图解 程序计数器 在JVM线程私有的内存区域中。每个线程都有自己独立的程序计数器。 程序计数器用于存储当前线程正在执行的字节码指令的地址。指示着当前线程执行到了哪一条字节码指令。 堆 是线程共享的区域&#xff0c;用于存储对象的实例和数组对象&#xff1b; …