【C语言进阶】文件操作

news2024/11/28 8:41:05

在这里插入图片描述

目录

  • 🥅什么是文件:
    • 🏑程序文件:
    • 🏑数据文件:
    • 🏑文件名:
  • 🥅文件的打开和关闭:
    • 🏑文件指针:
    • 🏑fopen和fclose:
  • 🥅文件的顺序读写:
    • 🏑输出、输入和读取、写入:
    • 🏑输出流、输入流的
    • 🏑fgetc:
    • 🏑fputc:
    • 🏑fgets:
    • 🏑fputs:
    • 🏑fscanf:
    • 🏑fprintf:
    • 🏑fwrite:
    • 🏑fread:
    • 🏑对比scanf、fscanf、sscanf:
    • 🏑对比printf、fprintf、sprintf:
  • 🥅文件的随机读写:
    • 🏑fseek:
    • 🏑ftell:
    • 🏑rewind:
  • 🥅文本文件和二进制文件:
  • 🥅文件读取结束的判定:
    • 🏑如何判断文件读取结束:
    • 🏑被错误使用feof:
    • 🏑ferror:
  • 🥅文件缓冲区:

前言:
 今天分享的内容是和文件有关的操作。使用文件可以让我们的数据直接存存放到电脑的硬盘上,做到数据的 持久化,因此掌握对文件的操作,是一名程序员的必备技能,接下来就让我们进入今天的正题,看看到底如何对文件进行操作吧。

🥅什么是文件:

 在磁盘上的文件是文件。在程序设计中,我们一般谈的文件有两种:程序文件数据文件(从文件功能功能的角度来分类的)。

🏑程序文件:

 主要包括以下几类:

  • 源程序文件(后缀为.c)
  • 目标文件(Windows环境后缀为.obj)
  • 可执行程序文件(Windows环境下后缀为.exe)

🏑数据文件:

 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者需要输出内容的文件.
 今天我们谈的文件操作,都是针对数据文件来说的。在以前我们处理数据的输入输出都是已终端作为对象,即从键盘的终端输入数据,再将结果显示到终端的显示器上。有时后我们也会把信息输出到磁盘上,当需要的时候再把磁盘上的数据读取到内存中使用,这里处理的就是磁盘上的文件

🏑文件名:

 一个文件要有一个唯一的标识符,一遍用户识别和引用。文件名包含以下三部分:文件路径+文件名主干+文件后缀。例如:

  • c:\code\test.txt

 其中c:\\code\\就是文件路径,test就是文件名主干,.txt就是文件名后缀。

🥅文件的打开和关闭:

🏑文件指针:

 缓冲文件系统中,关键的概念是“文件类型指针”简称文件指针。每一个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件相关的信息(如:文件的名字、文件的状态、文件当前的位置等信息)。这些信息保存在一个结构体变量中,该结构体类型是由系统声明的,取名FILE。也就是说,每当我们打开一个文件,内存中都会创建一个FILE类型的结构体变量与我们打开的文件对应。下图是VS2013中对FILE的定义。不同的C编译器的FILE类型包含的内容不完全相同,但是都大同小异。
在这里插入图片描述
 每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构体的变量,并填充里面的信息,我们不必关系里面的细节,只需要会用它就可以。一般我们都是通过一个FILE指针来维护这个FILE结构体变量,这样使用起来更加方便。通过文件指针变量能够找到与他关联的文件

🏑fopen和fclose:

 文件在读取之前要打开文件,在使用结束之后要关闭文件。在编写程序的时候,在打开文件的同时,会返回一个FILE*的指针变量指向该文件,也相当于建立了文件和指针之间的关系。ANSIC规定使用fopen函数来打开文件,fclose函数来关闭文件
⚾:fopen
FILE * fopen ( const char * filename, const char * mode );

  • 第一个参数filename是要被打开的文件的文件名,可以是文件的绝对路径(从根目录开始,例如c:\\code\\test.txt就是一个绝对路径),也可以是文件的相对路径(相对与当前工程目录,例如:test.txt,它表示当前工程目录里的test.txt..\\test.txt表示当前工程目录的上一级目录中的test.txt,其中..\\代表的就是上一级目录)
  • 第二个参数mode是文件的打开方式,主要有以下几种:
文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件,会清空文本文件中的内容建立一个新文件
“a”(追加)向文本文件尾添数据建立一个新文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建立一个新的文件夹建立一个新文件
“a+”(读写)打开一个新文件,在文件尾进行读写建立一个新文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新文件
  • 如果文件打开成功,则返回一个FILE类型的指针与打开的文件关联起来,后面就可以利用这个指针对此文件进行一定的操作,如果打开失败则返回一个空指针

⚾:fclose
int fclose ( FILE * stream );

  • 参数是一个与要关闭的文件有关的FILE类型的指针,此函数的返回值是一个整形,当文件被成功关闭,会返回一个0,如果返回失败则会返回EOF。一般的文件打开和关闭流程,如下面的代码:
int main()
{
	FILE* pf = fopen("D:\\code\\test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	
	//读文件 
	//...
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}
//结果:fopen: No such file or directory

 从打印的结果可以看出文件打开失败了,原因是:首先我们D:\\code\\这个路径下没有创建test.txt这个文件,其次我们是以“r”(只读)的方式打开的,根据上面的表格,此时如果没有对应的文件,打开时就会出错。
 这里补充一个小细节,我们最好在电脑中打开显式文件扩展名,也就是我们常说的文件后缀,这样文件的名称会显示的比较齐全,避免我们在写程序打开文件时出错。
在这里插入图片描述

🥅文件的顺序读写:

 所谓顺序读写就是从文件中的第一个字符开始往后依次读取或写入。文件的顺序读写主要涉及以下几个函数:

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

🏑输出、输入和读取、写入:

 在深入了解文件顺序读写函数之前,先要明确输出、输入读取、写入这两组概念。输出和输入都是针对内存来说的,以内存作为输出和输入的对象,输出准确来说是从内存中输出,输入准确来说是往内存中输入。而读取和写入时针对文件来说的,读取准确来说是从文件中进行读取,写入准确来说是往文件中进行写入。程序是在内存中运行的,因此要把程序运行时产生的数据存储到文件中,其实就是内存输出数据写入到文件中。而程序运行时从文件中获取数据,其实就是从文件中读取数据输入到内存当中。注意,键盘和显示器本质上也是文件。因此我们每次通过scanf从键盘上键入数据,其本质上是从键盘文件中读取数据输入到内存当中供程序运行时使用。而使用printf将程序运行的结果打印到显示器上,其本质是将程序运行时产生的数据从内存中输出写入到显示器文件当中。
 总结一下:输入是和读取绑定的,输出是和写入绑定的

🏑输出流、输入流的

 从上面的表格中我们可以看到,有些函数可以适用于所有的输出流或者输入流,而有的文件只适用于文件的输出流或者输入流,这里的到底是什么意思呢?
可以帮助我们简化输入输出操作,已输出为例,我们可能会将程序运行中产生的数据输出到不同的输出设备中(比如:屏幕、文件、网络等),针对不同的输出设备其写入方式也有所不同,作为程序员我们就需要掌握对不同输出设备的写入方式,这样才能把数据正确的写入到输出设备上,这无疑给程序员增添了许多麻烦。为了简化操作,于是就在内存和输出设备之间抽象出来了一个流的概念,此时程序员只需要知道如何把数据输出到流中去就可以,而从流中把数据写入到不同的输出设备这一过程C语言已经帮我们封装好了。流的类型是FILE*
在这里插入图片描述

 任何一个C语言程序运行的时候会默认打开以下三个流:

  • stdin ---- 标准输入流(键盘)
  • stdout ----标准输出流(屏幕)
  • stderr ---- 标准错误流(屏幕)

 这三个流的类型也都是FILE*,由于这三个流是在C语言程序运行的时候默认打开的,所以在一个C程序中我们可以直接使用scanf和printf。而对于一个文件,C语言程序在运行的时候不会默认打开,因此如果要对文件进行操作我们需要自己写代码来打开文件,例如:FILE* pf = fopen("test.txt", "r"); ,其本质上是获取一个文件流
 所以上表中提到的适用于所有的输入流或输出流,就意味着此函数不仅可以从文件流里面获取或写入数据,以getc和putc为例:

int main()
{
	char ret = fgetc(stdin);//从标准输入流中读取字符,输入到内存当中
	fputc(ret, stdout);//从内存中输出一个字符,写入到标准的输出流里面
	return 0;
}

在这里插入图片描述

🏑fgetc:

int fgetc ( FILE * stream );

  • 参数是一个文件类型的指针
  • FILE结构体中有一个定位指针,指向文件中待读取的字符,最初一定是指向文件中的第一个字符
  • 读取成功会返回定位指针当前所指向的字符,并且定位指针前进一位(这就是顺序读的实现原理),读取结束会返回EOF
  • 因为是从文件中读取字符,因此文件一定是以的方式打开

🏑fputc:

int fputc ( int character, FILE * stream );

  • 第一个参数character是待写入的字符
  • 第二个参数stream是与待写入文件所关联的文件指针(对应的文件流)
  • 此时是向文件中写数据,所以文件必须是以追加的方式进行打开
  • 向定位指针当前指向的位置写入一个字符,写入成功会返回所写入的字符,并且定位指针前进以为。写入失败会返回EOF

🏑fgets:

char * fgets ( char * str, int num, FILE * stream );

  • 第一个参数str表示把读取到的字符串拷贝到str所指向的空间
  • 第二个参数num表示读取num的字符,其中会包含一个’\0’,因此实际上只会读取num-1个字符
  • 第三个参数stream是与待读取文件关联的文件指针(对应的文件流)
  • 读取成功会返回str,读取结束会返回NULL
  • fgets是文本行输入函数,因此当一行没有读取完的时候,下一次读取会从上一次读取结束的位置继续读取当前行的文本。如果待读取的字符个数num大于当前文本行的字符个数,那此次读取只会把当前行的所有字符读取出来,不会去读取下一行的字符。

🏑fputs:

int fputs ( const char * str, FILE * stream );

  • 第一个参数str表示待写入的字符串
  • 第二个参数stream表示与待写入文件关联的文件指针
  • 写入成功会返回一个非负数,写入失败会返回EOF

🏑fscanf:

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

  • 格式化的输入函数,可以通过指定格式从文件中读取任意类型的数据
  • 第一个参数stream是与待读取文件关联的文件指针(对应的文件流)
  • 后面的…表示可变参数列表,与我们平时所使用的scanf中的参数一样,是根据自己的需求来传参的。通过下面的代码来演示fscanf的用法
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	struct Student s1;
	struct Student s2;
	//读文件 
	//...
	fscanf(pf, "%s%d%f", s1.name, &s1.age, &s1.weight);
	fscanf(pf, "%s%d%f", s2.name,&s2.age,&s2.weight);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 首先我们定义了一个Student类型的结构体,然后在主函数中定义了两个Student类型的变量s1s2,接着我们希望从与pf所关联的test.txt文件中去读取信息,分别存放到s1和s2里面,通过下面的执行结果可以看出,成功的从文件中读取了信息。
在这里插入图片描述

🏑fprintf:

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

  • 格式化的输出函数,可以通过指定格式向文件中写入数据
  • 第一个参数stream是与待写入文件关联的文件指针(对应的文件流)
  • 后面的…表示可变参数列表,与我们平时使用的printf函数中的参数列表是一样的,是根据需要进行传参的,下面通过代码演示fprintf函数的用法
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	struct Student s1 = {"wangwu", 35, 56.6};
	struct Student s2 = {"liming", 80, 45.1};
	//读文件 
	//...
	fprintf(pf, "%s, %d, %f\n", s1.name, s1.age, s1.weight);
	fprintf(pf, "%s, %d, %f\n", s2.name, s2.age, s2.weight);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 这次我们在主函数中定义了两个Student类型的变量s1s2,并且进行了初始化,希望把这两个学生的信息写入到与文件指针pf关联的test.txt文件中,通过下面的结果可以看出写入数据成功
在这里插入图片描述

🏑fwrite:

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

  • 首先fwrite是输出二进制文件,因此文件需要以二进制的方式打开,也就是“wb
  • 第一个参数ptr是待输出数据变量的地址,由于可以将任何类型的数据以二进制形式的输出,所以ptr的类型是void*
  • 第二个参数size是待输出数据类型的大小
  • 第三个参数count是待输出数据的个数
  • 第四个参数stream是与被写入文件关联的文件指针(对应的文件流)
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	struct Student s1 = {"wangwu", 35, 56.6};
	struct Student s2 = {"liming", 80, 45.1};
	//读文件 
	//...
	fwrite(&s1, sizeof(struct Student), 1, pf);//把s1以二进制的形式写入到test.txt文件中去
	fwrite(&s2, sizeof(struct Student), 1, pf);//把s2以二进制的形式写入到test.txt文件中去
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

🏑fread:

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

  • 首先fread是以二进制的形式从文件中读取数据输入到内存中,所以文件必须是以二进制读的方式打开的
  • 第一个参数ptr指向输入到内存中的地址
  • 第二个参数size是待输入数据类型的大小
  • 第三个参数count是带输入数据的个数
  • 第四个参数stream是与待读取数据关联的文件指针(对应的文件流)
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	struct Student s[3] = {0};
	//读文件 
	//...
	fread(s, sizeof(struct Student), 2, pf);//从test.txt文件中以二进制形式读取两个struct Student类型的数据
	printf("%s %d %f\n", s[0].name, s[0].age, s[0].weight);
	printf("%s %d %f\n", s[1].name, s[1].age, s[1].weight);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

🏑对比scanf、fscanf、sscanf:

  • scanf----仅适用于标准输入流stdin,也就是从键盘读取数据输入到内存中
  • fscanf----适用于所有的输入流,也就是可以从各种输出设备(文件、键盘等)读取数据输入到内存中
  • sscanf----把一个字符串转换成格式化的数据
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	struct Student s1;
	char* str = "zhangsan 12 35.5";//一个字符串
	sscanf(str, "%s%d%f", s1.name, &s1.age, &s1.weight);//从字符串str中格式化的读取数据存到s1里面去
	printf("%s %d %f", s1.name, s1.age, s1.weight);//打印s1的内容
	return 0;
}

在这里插入图片描述

🏑对比printf、fprintf、sprintf:

  • printf----只适用于标准输出流stdout,也就是把内存中的数据输出到显示器上
  • fprintf----适用于所有的输出流,可以把内存中的数据输出到各种输出设备上(文件、显示器等)
  • sprintf----以格式化的形式把数据存到(转换)到一个字符串中
struct Student
{
	char name[10];
	int age;
	float weight;
};

int main()
{
	struct Student s1 = {"张三", 15, 36.3};//定义一个学生
	char arr[100] = { 0 };//定义一个字符数组
	sprintf(arr, "%s %d %f", s1.name, s1.age, s1.weight);//把学生的信息,以格式化的形式输出到字符数组arr中
	printf(arr);//打印字符数组
	return 0;
}

在这里插入图片描述

🥅文件的随机读写:

🏑fseek:

int fseek ( FILE * stream, long int offset, int origin );

  • 根据文件指针的位置和偏移量来定位文件指针。
  • 第一个参数stream是对应的文件流
  • 第二个参数offset是相对于第三个参数origin的偏移量,向左偏移为负数,向右偏移为正数
  • 第三个参数origin是第二个参数偏移量所参考的位置,有以下三个选项
选项参考位置
SEEK_SET文件的开始位置
SEEK_CUR文件指针当前指向的位置
SEEK_END文件的结尾
int main()
{
	FILE* pf = fopen("test.txt", "r");//已知test.txt文件中存放的数据是---abcdefg
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//用fgetc进行顺序读取
	char ret1 = fgetc(pf);//第一次一定读到的是a
	printf("%c\n", ret1);
	char ret2 = fgetc(pf);//第二次一定读到的的b
	printf("%c\n", ret2);
	char ret3 = fgetc(pf);//第三次一定读到的是c
	printf("%c\n", ret3);
	//第三次读完之后,文件指针已经指向了d
	//如果想继续读b该怎么做?
	fseek(pf, 1, SEEK_SET);//重新对文件指针进行定位,相对于文件的起始位置,向右偏移一个单位
	//fseek(pf, -2, SEEK_CUR);//相对于文件指针当前位置,向左偏移两个单位
	//fseek(pf, -6, SEEK_END);//相对于文件的结尾,向左偏移6个单位
	//此时文件指针指向b
	char ret4 = fgetc(pf);//再一次读取
	printf("%c\n", ret4);
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述
 从结果中可以看出,读取了两个b,具体过程如下动图所示
在这里插入图片描述

🏑ftell:

long int ftell ( FILE * stream );

  • 返回文件指针相对于起始位置的偏移量

🏑rewind:

void rewind ( FILE * stream );

  • 让文件指针的位置回到文件的起始位置

🥅文本文件和二进制文件:

 根据数据的组织形式,数据文件称为文本文件或者二进制文件。数据在内存中是以二进制的形式进行存储的,如果不加转换的输出到外存,就是二进制文件。如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件
 一个数据在内存中是如何存储的呢?
 字符一律是用ASCII码形式存储,数值型数据既可以用ASCII形式存储,也可以用二进制形式存储,例如正数10000,以ASCII形式输出到磁盘,需要占用5个字节(每个字符一个字节),如果以二进制形式输出到磁盘,则在磁盘上需要占用4个字节
在这里插入图片描述

int main()
{
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int a = 10000;
	fwrite(&a, 4, 1, pf);//把10000以二进制形式写入到文件中
	fclose(pf);
	pf = NULL;
	return 0;
}

⚾:如何查看一个二进制文件?

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

在这里插入图片描述

🥅文件读取结束的判定:

🏑如何判断文件读取结束:

 文本文件读取是否结束,判断返回值是否为EOF(fgetc),或者NULL(fgets)

  • fgetc判断返回值是否为EOF
  • fgets判断返回值是否为NULL

 二进制文件是否读取结束,判断返回值是否小于实际要读的个数

  • fread判断返回值是否小于实际要读的个数

🏑被错误使用feof:

int feof ( FILE * stream );

 在文件读取过程中,不能用feof函数的返回值来判断文件读取是否结束。feof用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束,所以feof是用来判断文件是因为什么原因而读取结束的。如果返回一个非零的值说明文件是正常读取遇到了文件结束标志而结束的。

🏑ferror:

int ferror ( FILE * stream );

 检查错误指示器,如果返回一个非零的值说明是在文件读取过程中出错而导致文件读取结束的。

🥅文件缓冲区:

 ANSIC标准采用“文件缓冲区系统”处理数据文件,所谓缓冲文件系统是指系统自动的在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。可以通过setbufsetvbuf等函数去修改缓冲区的大小。
在这里插入图片描述

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10环境测试
int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf);//先将代码放在输出缓冲区
	printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
	Sleep(10000);
	printf("刷新缓冲区\n");
	fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
	//注:fflush 在高版本的VS上不能使用了
	printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
	Sleep(10000);
	fclose(pf);
	//注:fclose在关闭文件的时候,也会刷新缓冲区
	pf = NULL;
	return 0;
}

 通过上面的代码我们可以得出一个结论:因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。如果不做,可能导致读写文件的问题。


 今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,您的支持就是春人前进的动力!
在这里插入图片描述

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

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

相关文章

基于matlab使用先导校准来补偿阵列不确定性(附源码)

一、前言 此示例说明如何使用先导校准来提高天线阵列在存在未知扰动时的性能。 原则上&#xff0c;可以轻松设计理想的均匀线性阵列&#xff08;ULA&#xff09;来执行阵列处理任务&#xff0c;例如波束成形或到达方向估计。在实践中&#xff0c;没有理想的阵列。例如&#xff…

io.netty学习(二)Netty 架构设计

目录 前言 Selector 模型 SelectableChannel Channel 注册到 Selector SelectionKey 遍历 SelectionKey 事件驱动 Channel 回调 Future 事件及处理器 责任链模式 责任链模式的优缺点 ChannelPipeline 将事件传递给下一个处理器 总结 前言 上一篇文章&#xff…

1.react路由的基本使用

第一步 首先打开index.js&#xff0c;在里面引入BrowserRouter或者HashRouter&#xff0c;启用全局路由模式。 BrowserRouter与HashRouter的区别 // index.js import React from react; import ReactDOM from react-dom/client; import ./index.css; import App from ./App;…

P31[10-1]软件模拟IIC通信协议(使用stm32库函数)(内含:实物连接+IIC时序解释+硬件电路+IIC基本时序单元(起始 终止 发送接收 ))

IIC通讯分为硬件读写IIC和软件IIC,以下为软件读写IIC 实物连接如下: 解释: 软件IIC通讯,对MPU6050芯片内部的寄存器进行读写操作,。写入配置寄存器,即可对外挂模块进行配置。。读出数据寄存器,即可获取外挂模块的数据。。。 OLED第一行为设备ID号(固定,有些可能不同)…

基于Springboot+mybatis+mysql+html图书管理系统2

基于Springbootmybatismysqlhtml图书管理系统2 一、系统介绍二、功能展示1.用户登陆2.用户主页3.图书查询4.还书5.个人信息修改6.图书管理&#xff08;管理员&#xff09;7.学生管理&#xff08;管理员&#xff09;8.废除记录&#xff08;管理员&#xff09; 三、数据库四、其它…

8.compute部署neutron服务

compute节点 安装软件包 yum -y install openstack-neutron-linuxbridge ebtables ipset 修改配置文件&#xff1a;/etc/neutron/neutron.conf #查看文件属性 ll /etc/neutron/neutron.conf -rw-r----- 1 root neutron ... /etc/neutron/neutron.conf #备份配置文件 cp /e…

C语言:将一句话的单词进行倒置,标点不倒置。

题目&#xff1a; 将一句话的单词进行倒置&#xff0c;标点不倒置。&#xff08;字符数组长度不超过100&#xff09; 比如&#xff1a;I like beijing. 经过函数后变为&#xff1a;beijing. like I 思路&#xff1a; 总体思路&#xff1a; &#xff08;可以把两步顺序调换&am…

chatgpt赋能python:Python中寻找不重复字符的方法

Python中寻找不重复字符的方法 Python是一种著名界面友好、易学易用且功能强大的编程语言&#xff0c;广泛应用于各种需求中。在本篇文章中&#xff0c;我们将会讨论如何使用Python编程语言来寻找一个字符串中的不重复字符。我们将简单介绍如何实现这个过程以及为什么这个过程…

Python小白如何利用GPT4快速开发一个网站!

这个是一个全栈的项目&#xff0c;麻雀虽小&#xff0c;五脏俱全&#xff01;全程都是利用gpt4进行辅助编程搞定的。第一版其实非常快&#xff0c;大概30分钟就搞定了&#xff0c;后续就是不断的添砖加瓦&#xff0c;增加功能和优化UI。 其实很多小白都在说要学Python&#xff…

chatgpt赋能python:Python扩展库需要导入吗?重要性与结论解析

Python扩展库需要导入吗&#xff1f;重要性与结论解析 作为业内最受欢迎的编程语言之一&#xff0c;Python在数据科学、人工智能、Web开发等领域拥有大量的应用。在Python开发过程中&#xff0c;扩展库的使用是不可避免的。本文将介绍Python扩展库的重要性以及是否需要导入的问…

【Arduino】Portenta H7 板子介绍

文章目录 1. Features2. Pins Name3. Functions3.1 analogReadResolution()3.2 millis() Ref. 1. Features 2. Pins Name 3. Functions 3.1 analogReadResolution() analogReadResolution() is an extension of the Analog API for the Zero, Due, MKR family, Nano 33 (BLE …

vue3-实战-10-管理后台-权限管理之用户管理模块开发

目录 1-用户首页列表开发 1.1-需求原型分析 1.2-封装请求和数据类型 1.3-数据页面渲染和展示 1.4-点击搜索按钮搜索用户 1.5-点击重置按钮 2-新增编辑用户 2.1-原型需求分析 2.2-表单页面数据收集 2.3-页面校验规则的定义 2.4-添加用户按钮编辑按钮逻辑 2.5-保存和取…

C++个人通信录系统

背景&#xff1a; 使用C编写一个通信录程序&#xff0c;来完成作业上的一些需求。 1-提供录入个人信息、修改个人信息&#xff08;姓名和出生日期除外&#xff09;、删除个人信息等编辑功能 2-提供按姓名查询个人信息的功能 3-提供查找在5天之内过生日的人员的信息&#xf…

Gof23设计模式之工厂方法模式和抽象工厂模式

在java中&#xff0c;万物皆对象&#xff0c;这些对象都需要创建&#xff0c;如果创建的时候直接new该对象&#xff0c;就会对该对象耦合严重&#xff0c;假如我们要更换对象&#xff0c;所有new对象的地方都需要修改一遍&#xff0c;这显然违背了软件设计的开闭原则。 如果我们…

机器学习之K-Means(k均值)算法

1 K-Means介绍 K-Means算法又称K均值算法&#xff0c;属于聚类&#xff08;clustering&#xff09;算法的一种&#xff0c;是应用最广泛的聚类算法之一。所谓聚类&#xff0c;即根据相似性原则&#xff0c;将具有较高相似度的数据对象划分至同一类簇&#xff0c;将具有较高相异…

NDK使用LLVM编译Boost库给Android使用

1.下载boost库 ​ wget https://boostorg.jfrog.io/artifactory/main/release/1.71.0/source/boost_1_71_0.tar.gz​ 选择1.71.0版本 NDK版本19 ,ANDROID版本 24 进入然后后的目录 (不指定平台 默认为当前系统平台) ./bootstrap.sh --prefix=./android_build --libdir=.…

Java---阶段项目----五子棋

Java---阶段项目----五子棋 需求说明技术实现棋盘制作完整代码 需求说明 五子棋棋盘为一个1010的方格&#xff0c;五子棋玩家共为两个(A,B)&#xff0c;A在棋盘上落子后&#xff0c;B再落子&#xff0c;依次往复&#xff0c;直到一方胜利或者棋盘空间用完为止&#xff0c;判断…

StarCCM+ 命令行运行(Windows)

添加环境变量 找到启动程序的位置。找到当初安装starccm的文件夹&#xff0c;一般就是 Siemens 文件夹&#xff0c;进入会看到各版本的安装文件夹&#xff08;如果你没有安装多个版本则只有一个&#xff09;&#xff0c;然后参考下面我的路径找到相应的文件夹。在bin文件夹内可…

【openGauss简单使用---快速入门】

【openGauss简单使用---快速入门】 &#x1f53b; 一、openGauss使用&#x1f530; 1.1 连接openGauss&#x1f530; 1.2 创建数据库用户和授权&#x1f530; 1.3 创建数据库&#x1f530; 1.4 创建SCHEMA&#x1f530; 1.5 创建表 &#x1f53b; 二、总结—温故知新 &#x1f…

信息系统之网络安全方案 — “3保1评”

信息系统之网络安全方案 — “3保1评” 序&#xff1a;什么是“3评1保”&#xff1f;一、网络安全等级保护1.1 概念1.2等保发展1.3法律要求1.4分级及工作流程 二、涉密信息系统分级保护2.1概念2.2法律要求2.3分级及工作流程 三、关键信息基础设施保护3.1概念3.2关保的发展3.3法…