【Linux-基础IO】C语言文件接口回顾 系统文件概念及接口

news2024/11/16 22:44:26

目录

一、C语言文件接口回顾

C语言基础知识

C++中文件操作示例

二、系统文件概念及接口

重定向基本理解的回顾

文件的基本概念

系统调用接口

open

read

write

close

lseek

什么是当前路径


 

一、C语言文件接口回顾

引言:我们并不理解文件!从语言角度(绝对不可能理解)。我们要进行文件操作,前提是我们的程序跑起来了。文件的打开和关闭,是CPU在执行我们的代码

C语言基础知识

几个函数:

FILE *fopen(const char *path, const char *mode);` 

fopen是C语言标准库函数,用于打开一个文件并返回一个文件指针以便进行读写操作。如果文件打开成功,它会返回一个指向 FILE 类型的指针,该指针后续可以用于其他文件操作函数。如果打开失败,则返回 NULL

其中:

  • const char *path:这是一个字符串,表示要打开的文件的路径名。可以是相对路径或绝对路径。

  • const char *mode:这也是一个字符串,表示打开文件的模式,即如何使用文件

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread 函数是 C 标准库中的一个函数,用于从指定的流中读取数据到缓冲区中。该函数同样定义在 stdio.h 头文件中。fread 主要用于二进制输入操作。fread 函数返回成功读取的元素个数,这个数可能小于 nmemb,如果遇到错误或文件末尾。如果文件末尾在读取任何字节之前到达,fread 将返回 0。

其中:

  • ptr:指向内存块的指针,该内存块至少要有 size * nmemb 字节的大小。函数从流中读取数据到这个内存块中。

  • size:要读取的每个元素的大小,以字节为单位。

  • nmemb:要读取的元素个数,每个元素的大小为 size 字节。

  • stream:指向 FILE 对象的指针,该对象指定了输入流。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

fwrite 函数是 C 标准库中的一个函数,用于将数据写入到指定的流中。这个函数也是定义在 stdio.h 头文件中。fwrite 主要用于执行二进制输出操作。fwrite 函数返回成功写入的元素个数,这个数可能小于 nmemb,如果遇到写入错误。如果成功写入 nmemb 个元素,则返回值等于 nmemb

其中:

  • ptr:指向要写入数据的内存块的指针。

  • size:要写入的每个元素的大小,以字节为单位。

  • nmemb:要写入的元素个数,每个元素的大小为 size 字节。

  • stream:指向 FILE 对象的指针,该对象指定了输出流

int fprintf(FILE *stream, const char *format, ...);

fprintf 是 C 标准库中的一个函数,用于将格式化的数据写入到指定的流(通常是文件流)。这个函数与 printf 类似,但是 fprintf 允许你指定写入数据的流,而 printf 默认写入到标准输出(通常是控制台)。如果成功,fprintf 返回写入的字符数。如果发生错误,fprintf 返回一个负数。

其中

  • stream:指向 FILE 对象的指针,该对象标识了要写入数据的流。

  • format:指向一个以空字符结尾的字符串,该字符串包含格式规范,用于指定如何写入后续参数。

  • ...:可变数量的参数,它们将被格式化并写入到流中。

int fclose(FILE *stream);

fclose 是 C 标准库中的一个函数,用于关闭由 fopenfreopen 或其他文件打开函数创建的文件流。关闭文件是非常重要的,因为它会释放与文件流关联的所有内部缓冲区,并且确保所有写入的数据都已经被正确地刷新到磁盘上。

其中:

  • 如果文件成功关闭,fclose 返回 0

  • 如果在关闭文件时发生错误,fclose 返回 EOF(通常定义为 -1)。

文件打开方式:

2accc902d1c9494685aaebbdbb625983.png

几个例子:

【示例1】

int main()
{
  FILE* fp = fopen("log.txt","w");
  if(fp == NULL){
    perror("fopen");
    return 1;
  }

  fprintf(fp, "helloworld, %d, %s, %lf\n", 10, "wuxu", 3.14);

  fclose(fp);
  return 0;
}

执行结果:

[wuxu@Nanyi lesson18]$ ls
makefile  mytest  test1.c
[wuxu@Nanyi lesson18]$ ./mytest
[wuxu@Nanyi lesson18]$ ls
log.txt  makefile  mytest  test1.c
[wuxu@Nanyi lesson18]$ cat log.t

可以发现,我们以写的方式打开log.txt,我们原先并没有log.txt,是“w”的方式,创建了一个log.txt 并向内格式化写入内容

如果我们修改一下 main函数里的格式化输出,再进行执行

将代码修改为

 fprintf(fp, "helloworld, %d, %s, %d\n", 10, "wuxu", 666);   

699b7088fc6f425ab601a1e74e14c543.png

可以发现:原文件内容被内容完全替代,因此我们对于“w”有个结论

  1. 如果文件不存在,就在当前路径下,新建指定的文件

  2. 默认打开文件的时候,就会先把目标文件清空

如果我们想追加对文件进行写入就需要讲模式换为“a”模式

C++中文件操作示例

#include <iostream>
#include <string>
#include <fstream>

#define FILENAME "log.txt"

int main()
{
    std::ofstream out(FILENAME);
    if(!out.is_open()) return 1;

    std::string message = "hello C++\n";
    out.write(message.c_str(), message.size());

    out.close();

    return 0;
}

 dc6994291dda4fe2abf42db4883f5b10.png

二、系统文件概念及接口

重定向基本理解的回顾

我们第一次理解重定向是在 echo命令上理解的,echo 命令本身是向显示器进行输出

[wuxu@Nanyi lesson18]$ echo "hello I am echo"
hello I am echo

我们也可以使用echo命令,向指定文件进行写入 

9ed9aa3fbe114822b9cf5bc2719f0497.png

我们也可以使用echo命令,向文件进行追加写入,也就是追加重定向

ae950d47677c4aabb6704fcfdc93a1c7.png 

那么我们也就发现 > 相当于 "w" , >> 相当于 “a“,如果是的话,我们也可以使用 > 或 >> 进行创建文件

8e0b4161ba5743d89fe9e47c5c3b0fb5.png 

所以我们也就发现:输出重定向一定是文件操作

文件的基本概念

当我们使用ls-l查看文件信息时,会显示文件的类型、权限、引用计数、所有者、所属组、大小、文件最新修改时间等信息,这些都是文件的属性

736487f8e7774044b32f68224d8940cb.png

由此我们可以知道:文件 = 内容+属性

 

文件被打开,需要先被加载到内存。由于内存空间有限,不可能将所有的文件全部打开,所以文件可以分为已被打开文件,和未打开文件。

打开文件:本质是进程打开文件。文件没有打开的时候,文件在磁盘中;

一个进程可以打开很多文件,一个系统中可以存在很多进程;所以很多情况下,在操作系统内部,一定存在大量被打开的文件,那么操作系统是如何对这些文件进行管理呢?--->**先描述,在组织

系统调用接口

文件是存在磁盘中的,由冯诺伊曼体系我们可知,磁盘是一个外设,外设是一个硬件。我们向文件中写入,本质是向硬件中写入;但是用户没有权利直接写入,由于操作系统是硬件的管理着,那我们就可以通过操作系统给我们提供的系统调用(OS不相信任何人)来访问文件

09c7ff59146f416e9bdf84ebdab79968.png

下面是系统调用接口的函数,我们来一一介绍使用,看看与C/C++文件操作有什么共同点与不同点

open

6578540c8382491090efb06444d0923d.png 

 

其中:

  • pathname:指向一个以空字符结尾的字符串,该字符串指定了要打开或创建的文件的路径名。

  • flags:指定文件的打开模式。这个参数是以下选项中的一个或多个通过按位或操作(|)组合起来的值:

    • O_RDONLY: 只读打开。

    • O_WRONLY: 只写打开。

    • O_RDWR: 读写打开。

    • O_CREAT: 如果文件不存在,则创建它。需要与 mode 参数一起使用。

    • O_EXCL: 与 O_CREAT 一起使用,确保调用 open 时创建文件。如果文件已存在,则返回错误。

    • O_TRUNC: 如果文件已存在且为写入或读写打开,则将其长度截断为 0。

    • O_APPEND: 追加模式。在每次写入时,数据会被添加到文件的末尾。

    • 其他标志请参考 open 的手册页。

  • mode:当创建新文件时,这个参数指定了文件的模式(权限)。它是一个八进制数,通常由 umask 的值与要求的权限按位取反后相与得到。常见的权限值包括:

    • S_IRUSR: 用户读权限。

    • S_IWUSR: 用户写权限。

    • S_IXUSR: 用户执行权限。

    • S_IRGRP, S_IWGRP, S_IXGRP: 分别对应组成员的读、写、执行权限。

    • S_IROTH, S_IWOTH, S_IXOTH: 分别对应其他用户的读、写、执行权限。

    • 也可以使用数字来表示权限

返回值:

  • 成功时,open 返回一个最小的非负整数,称为文件描述符,用于后续的读写操作。

  • 出错时,open 返回 -1,并设置 errno 来指示错误。

flag选项描述
O_RDONLY只读
O_WRONLY只写
O_CREAT不存在就创建
O_TRUNC清空文件
O_APPEND追加写入

这些选项都是大写,我们在C/C++中什么情况下用上大写?没错就是宏,这里的flag选项与宏并未区别,我们先自己用宏来创建一个传参示例

测试内容:

#include <stdio.h>
#define ONE   1      // 1 0000 0001
#define TWO   (1<<1) // 2 0000 0010
#define THREE (1<<2) // 4 0000 0100
#define FOUR  (1<<3) // 8 0000 1000

void print(int flag)
{
    if(flag&ONE)
        printf("one\n"); //替换成其他功能
    if(flag&TWO)
        printf("two\n");
    if(flag&THREE)
        printf("three\n");
    if(flag&FOUR)
        printf("four\n");
}

int main()
{
    print(ONE);
    printf("\n");

    print(TWO);
    printf("\n");

    print(ONE|TWO);
    printf("\n");

    print(ONE|TWO|THREE);
    printf("\n");

    print(ONE|FOUR);
    printf("\n");

    print(ONE|TWO|THREE|FOUR);
    printf("\n");

    return 0;
}

输出结果:

2e89f5311332447daccc36ddd96f02ac.png

因此我们发现可以定制宏,通过传入不同的宏,实现定制的不同功能。它的原理底层是位图;一个int类型包含32个比特位,如果我们让低位的 1 表示ONE,次低位的 1 表示 TWO......

30560bf199f04dbbb34df9c09a2eb96e.png 

若此时要实现ONE、TWO、THREE,只需要对这三个数做或位运算ONE|TWO|THREE则会得到一个值为00000000 00000000 00000000 00011010的flags。将它传递给处理函数中,处理函数会将flag与ONE、TWO、THREE这三个数挨个做按位与,如果按位与出来的结果不为0,则表示该选项会被选择

而我们系统调用的flags也是一样的道理

接下来让我们用系统调用接口来操作文件

【示例】

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
  //system call
    int fda = open("loga.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("fda: %d\n", fda);
    int fdb = open("logb.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("fdb: %d\n", fdb);
    int fdc = open("logc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("fdc: %d\n", fdc);
    int fdd = open("logd.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("fdd: %d\n", fdd);

  return 0;
}

 输出结果:

c6ee621585c34c46b075227e41a4c7df.png

 

【问题1】我们定制的权限是666 ,为什么这里是 662?是umask的原因

PS:我们使用系统接口必须要指明权限,否则创建的文件权限是随机的

在 POSIX 兼容的操作系统中,umask 是一个系统调用,用于设置进程的文件模式创建掩码(file mode creation mask)。这个掩码定义了新创建文件的默认权限,通过从权限掩码中“掩蔽”掉一些权限位来限制新文件的权限。我们来查看一下系统的umask

13a7f1cdfa0440fa8f85a032edc63e26.png

接下来我们修改一下umask,看文件权限能不能达到我们想要的结果

在test2.c 加入umask(0)即可

测试结果:

9e83bce22bf845f194788ce4630dcc3c.png

 

【问题2】open系统调用函数返回的数字是什么?这个输出结果有什么含义?

open打开文件后会返回一个数字,这个数字被称为文件描述符,我们一会在下文详细讲解

read

b4287fe0a244451287dd71d9bb594627.png

要从某个文件中读取内容时,第一个参数需要传入该文件的文件描述符,第二个参数需要传入接收文件内容的缓冲区首地址,第三个参数表示要从文件中读取多少字节的内容。

下面程序模拟实现了C语言fopen的r(只读)打开模式

#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_RDONLY);
	char buffer[1024];
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	return 0;
}

 6c4f43937af0488ab1c745c230f04894.png

write

write 是 POSIX 系统调用之一,用于将数据写入文件描述符指向的文件或设备。这个函数在 C 语言中被广泛使用,尤其是在 UNIX、Linux 和其他 POSIX 兼容的操作系统中。

b1abe68ccd9845d5975db7b05f9c08de.png

 

参数:

  • fd:要写入数据的文件描述符。这个文件描述符可以是 open 系统调用返回的,也可以是标准输入输出错误文件描述符(例如 STDOUT_FILENOSTDERR_FILENO)。

  • buf:指向要写入数据的缓冲区的指针。

  • count:要写入的字节数。

返回值:

  • 成功时,write 返回实际写入的字节数。

  • 出错时,write 返回 -1,并设置 errno 来指示错误。

 

下面程序模拟实现C语言fopen的w(只读)模式打开

#include <stdio.h>
#include <string.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 | O_TRUNC, 0666);
	char* msg = "Have a good day!\n";
	write(fd, msg, strlen(msg));
	return 0;
}

2ff3f8983c3747e8b6b38efa1073a742.png

下面程序模拟实现C语言fopen的a(追加)模式打开

#include <stdio.h>
#include <string.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 | O_APPEND, 0666);
	char* msg = "Have a good day!\n";
	write(fd, msg, strlen(msg));
	return 0;
}

 51f6a6d9006343f58c6d44935025701c.png

close

8178bfd939784e3e9afca8eedc193119.png 

传入文件描述符即可关闭对应文件,这里就不掩饰了

lseek

lseek 是 POSIX 系统调用之一,用于设置文件描述符 fd 指向的文件的偏移量。这个函数允许你查询或修改文件流的当前位置,这对于随机访问文件非常有用。

d6197ae77ee341cc98c8db326939f012.png

 

参数:

  • fd:文件描述符,指向已经打开的文件。

  • offset:偏移量,根据 whence 的值,这个偏移量可以是绝对值,也可以是相对值。

  • whence:用于确定如何解释offset的值。它可以是以下三个常量之一:

    • SEEK_SET: 将偏移量设置为从文件开头算起的绝对位置。

    • SEEK_CUR: 将偏移量设置为相对于当前文件位置的相对位置。

    • SEEK_END: 将偏移量设置为相对于文件末尾的相对位置。

返回值:

  • 成功时,lseek 返回新的文件偏移量。

  • 出错时,lseek 返回 -1,并设置 errno 来指示错误。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_RDONLY | O_APPEND, 0666);
	char buffer[1024];
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	//回到文件头再读一遍
	lseek(fd, 0, SEEK_SET);
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	close(fd);
	return 0;
}

d277bc9b7d5f4feb806adfe0f8f20435.png

什么是当前路径

当我们没有指明文件路径,open一个文件时,则open将在当前路径下创建文件那为什么会这个样子呢?

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("log.txt", O_CREAT);
	close(fd);
	sleep(200);
	return 0;
}

当程序运行起来后,我们可以使用ps ajx | head -1 && ps ajx | grep mytest | grep -v grep 查看运行该程序的进程pid,进入/proc/进程pid目录,可以看到两个链接文件cwd和exe。其中,cwd是程序的工作路径,也就是我们常说的当前路径,而exe是可执行程序的保存位置。

42199962d22d4069a25a5790e058e94a.png

 

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

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

相关文章

【JavaEE】——多线程(join阻塞,计算,引用,状态)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 一&#xff1a;join等待线程结束 1&#xff1a;知识回顾 2&#xff1a;join的功能就是“阻塞等待” …

MK-1000门控管理系统

MK-1000门控系统简介 1.1 前言 中大型仓库一般由多个仓库组成&#xff0c;每个仓库具有上百个仓库门&#xff0c;人工控制仓库门的开启、闭合等耗时耗力&#xff0c;随着电子信息自动化发展&#xff0c;集中控制仓库门成为现实。本系统可通过网络灵活控制某个仓库的某个门开启、…

共轭传热和浸没边界耦合相关的论文的阅读笔记

Diffuse-interface immersed-boundary framework for conjugate-heat-transfer problems https://doi.org/10.1103/PhysRevE.99.053304 三区 混合交错离散体积和非交错离散体积 看不懂&#xff0c;不会 FVM 计算固体体积分数的步骤 对于每一个点&#xff1a; 找固体表面上…

【多维动态规划】64. 最小路径和(面试真题+面试官调整后的题目)

64. 最小路径和 难度&#xff1a;中等 力扣地址&#xff1a;https://leetcode.cn/problems/minimum-path-sum/description/ 1. 原题以及解法 1.1 题目 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和…

数据库提权【笔记总结】

文章目录 UDF提权以有webshell只有数据库权限条件复现msf工具sql语句提权 MOF提权前言条件复现msf工具php脚本提权 sqlserver提权前言条件xp_cmdshell提权复现 沙盒提权介绍复现 Oracle提权靶场搭建执行任意命令复现 通过注入存储过程提权&#xff08;低权限提升至DBA&#xff…

HTML-DOM模型

1.DOM模型 window对象下的document对象就是DOM模型。 DOM描绘了一个层次化的节点树&#xff0c;每一个节点就是一个html标签&#xff0c;而且每一个节点也是一个DOM对象。 2.操作DOM 2.1.获取DOM对象常用方法 获取DOM对象的常用方法有如下几种&#xff1a; getElementById(…

Linux入门学习:Git

文章目录 1. 创建仓库2. 仓库克隆3. 上传文件4. 相关问题4.1 git进程阻塞4.2 git log4.3 上传的三个步骤在做什么4.4 配置邮箱/用户名 本文介绍如何在Linux操作系统下简单使用git&#xff0c;对自己的代码进行云端保存。 1. 创建仓库 &#x1f539;这里演示gitee的仓库创建。…

Linux 基础IO 1

文件操作 基础IO 在程序中若需要读取文件数据或者将数据永久存入需要使用文件因为程序的产生的数据都是在内存中的&#xff0c;只要关闭程序就会释放掉不会&#xff0c;所以在一些程序中我们难免需要对文件进程操作。无论我们是存入数据还是提取数据前提是有这个数据并清楚它…

VGG16模型实现新冠肺炎图片多分类

1. 项目简介 本项目的目标是通过深度学习模型VGG16&#xff0c;实现对新冠肺炎图像的多分类任务&#xff0c;以帮助医疗人员对患者的影像进行快速、准确的诊断。新冠肺炎自爆发以来&#xff0c;利用医学影像如X光和CT扫描进行疾病诊断已成为重要手段之一。随着数据量的增加&am…

联想(lenovo) 小新Pro13锐龙版(新机整理、查看硬件配置和系统版本、无线网络问题、windows可选功能)

新机整理 小新pro13win10新机整理 查看硬件配置和系统版本 设置-》系统-》系统信息 无线网络问题 部分热点可以&#xff0c;部分不可以 问题&#xff1a;是因为自己修改了WLAN的IP分配方式为手动分配&#xff0c;导致只能在连接家里无线网的时候可以&#xff0c;连接其他…

51单片机——独立按键

一、独立按键对应单片机P3管脚&#xff0c;如图 二、按键点亮LED灯 #include <STC89C5xRC.H> void main() { while(1) { if(P300) { P200; } else { P201; } } } 当按键为0时&#xff0c;代表按下&#xff0c;所以当P30按下时&#xff0c;让P20&#xff1d;0&#…

Java面试篇基础部分-ReentrantLock详解

ReentrantLock 是继承了Lock接口,并且实现了再接口中定义的方法,属于一个可重入的独占锁。ReentrantLock 通过自定义队列同步器(Abstract Queued Synchroinzed,AQS)来实现锁的获取与释放。   那么什么是独占锁呢?独占锁就是指这个锁在同一时刻只能被一个线程所获取到,…

2024年最新网络协议分析器Wireshark抓包详细教程(更新中)

网络协议分析器 Wireshark 安装 Wireshark 是一个功能强大的网络协议分析器&#xff0c;早期叫作 Ethereal。它主要用于捕获网络数据包&#xff0c;并对这些数据包进行详细的解析和分析&#xff0c;帮助用户深入了解网络通信的细节。它支持多种网络协议&#xff0c;并提供详细…

VM虚拟机下载以及激活

传统的官网已经找不到下载了&#xff0c;这里我将下载好的放在阿里云盘&#xff0c;百度云盘太慢了&#xff0c;懂得都得 阿里云盘分享 下载好了后会是一个exe文件&#xff0c;直接双击运行就可 下载无脑下一步即可&#xff0c;这里不做介绍 下载好了后&#xff0c;需要密钥这里…

如何搭建IP代理池:从零开始的详细指南

在网络应用中&#xff0c;IP代理池是一种非常实用的工具&#xff0c;尤其是在需要大量IP地址进行网络请求时&#xff0c;例如网络爬虫、数据抓取和分布式系统等。通过搭建IP代理池&#xff0c;你可以有效地管理和分配IP地址&#xff0c;避免单一IP地址被封锁&#xff0c;提高网…

高效编程的利器 Jupyter Notebook

目录 前言1. Jupyter Notebook简介1.1 功能特点1.2 使用场景 2. 不同编程工具的对比与效率提升2.1 VS Code&#xff1a;灵活且轻量的代码编辑器2.2 PyCharm&#xff1a;面向专业开发者的集成开发环境2.3 Git&#xff1a;高效协作的版本控制工具2.4 Jupyter Notebook 和 VS Code…

【算法题】63. 不同路径 II-力扣(LeetCode)-”如果起点有障碍物,那么便到不了终点“

【算法题】63. 不同路径 II-力扣(LeetCode)-”如果起点有障碍物&#xff0c;那么便到不了终点“ 1.题目 下方是力扣官方题目的地址 63. 不同路径 II 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下…

【Godot4.x】Mesh相关知识总结

概述 很早之前发布过一篇关于几何体程序生成的文章&#xff0c;当时对于三角面和网格的构造其实还没有特别深入的认识&#xff0c;直到自己脑海里想到用二维数组和点更新的方式构造2D类型的多边形Mesh结构&#xff0c;也意识到在Godot中其实Mesh不仅是3D网格&#xff0c;也可以…

LeetCode 每周算法 6(图论、回溯)

LeetCode 每周算法 6&#xff08;图论、回溯&#xff09; 图论算法&#xff1a; class Solution: def dfs(self, grid: List[List[str]], r: int, c: int) -> None: """ 深度优先搜索函数&#xff0c;用于遍历并标记与当前位置(r, c)相连的所有陆地&…

uni-data-select 使用 localdata 传入数据出现 不回显 | 下拉显示错误的 解决方法

目录 1. 问题所示2. 正确Demo3. 下拉显示错误(Bug复现)4. 下拉不回显(Bug复现)1. 问题所示 uni-app的下拉框uni-data-select 使用 localdata 传入数据 主要总结正确的Demo以及复现一些Bug 数据不回显数据不显示下拉选项2. 正确Demo 详细的基本知识推荐阅读:uni-app中的…