【C语言深度解剖】(16):C语言的文件读写操作

🤡博客主页:醉竺

🥰本文专栏:《C语言深度解剖》

😻欢迎关注:感谢大家的点赞评论+关注,祝您学有所成!


✨✨💜💛想要学习更多C语言深度解剖点击专栏链接查看💛💜✨✨ 


目录

1. 为什么使用文件 

2. 文件概述

2.1 什么是流 

2.2 什么是文件 

2.3 文件名 

3. 文件的打开和关闭 

3.1 文件指针 

3.2 文件的打开和关闭 

4. 文件的顺序读写 

5.  文件的随机读写

5.1 fssek 

5.2 ftell

5.3 rewind 

6. 文本文件和二进制文件 

7. 文件读取结束的判定 

 7.1 文件的分类 

7.2 被错误使用的feof 

8. 文件缓冲区 


1. 为什么使用文件 

程序执行起来后,称之为进程,进程运行过程中的数据,均在内存中,当我们需要把运算后的数据存储下来时,就需要文件。 做到数据的持久化。

2. 文件概述

2.1 什么是流 

在C语言中,流是一个用于输入输出操作的抽象概念。它代表了一个数据的流动,从源头(比如键盘、文件、网络等)到目的地(比如屏幕、文件、网络等)。流可以看作是一个数据的序列,它按照一定的顺序被读取或写入。

C语言的标准库提供了一套文件输入输出函数,这些函数可以对流进行操作。在C中,所有的输入输出操作都是通过流来完成的。标准输入输出库 <stdio.h> 定义了流的概念,并提供了相关的函数。

以下是C语言中几个重要的流:

  • stdin - 标准输入流,通常指键盘输入。
  • stdout - 标准输出流,通常指屏幕输出。
  • stderr - 标准错误流,用于输出错误信息,通常也是输出到屏幕,但与stdout分离,以便于错误信息不会与普通输出混淆。

流在C语言中是通过文件指针来引用的,文件指针是一个指向FILE结构的指针,FILE结构包含了流的状态信息。例如,当你打开一个文件时,C语言的fopen函数会返回一个FILE指针,通过这个指针,你可以对文件进行读或写操作。

FILE* fp; // 声明一个文件指针
fp = fopen("example.txt", "r"); // 打开一个文件,返回一个指向该文件的流
if (fp == NULL) {
    // 错误处理
}
// ... 使用fp进行文件操作
fclose(fp); // 关闭流

2.2 什么是文件 

文件:文件指存储在外部介质(如磁盘磁带)上数据的集合。操作系统(windows,Linux, Mac 均是)是以文件为单位对数据进行管理的。 

在C语言中,所有的设备都被视为文件,它们的输入输出操作都可以通过文件流来进行。这使得C语言的输入输出模型非常统一和灵活。 

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

  • 程序文件 

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。 

  • 数据文件 

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。 

本章讨论的是数据文件。 

在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理 的就是磁盘上文件。 

2.3 文件名 


3. 文件的打开和关闭 

3.1 文件指针 

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。 

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE

打开文件后我们得到 FILE*类型的文件指针,通过该文件指针对文件进行操作,FILE 是 一个结构体类型,那么首先让我们来看下它里边都有什么呢?

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息, 使用者不必关心细节。 

一般都是通过一个 FILE 的指针来维护 FILE 结构的变量。

下面我们可以创建一个FILE*的指针变量: 

FILE* pf;//文件指针变量

定义 pf 是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。

比如: 

3.2 文件的打开和关闭 

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件

在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。 

ANSIC 规定使用fopen数来打开文件fclose来关闭文件。 

  • 当无法打开文件时,fopen函数会返回空指针。这可能是因为文件不存在,也可能是因为文件的位置不对,还可能是因为我们没有打开文件的权限。 
  • 函数 fclose()关闭给出的文件流, 释放已关联到流的所有缓冲区。fclose()执行成功 时返回 0,否则返回 EOF. 

打开方式如下:

实例代码: 

要区分标准的输入输出,和文件操作中的输入输出


4. 文件的顺序读写 

上述简单了解需要用的时候查看一下即可,下面我会为上述每个函数举一个例子:

  • fgetc 
int fgetc(FILE* stream);

在这个例子中,我们使用 fgetc 读取名为 “example.txt” 的文件,并将文件内容打印到标准输出。我们检查每次 fgetc 的调用是否返回 EOF 来判断是否到达文件末尾。同时,我们使用 ferror 函数来检查文件流是否发生了错误。最后,我们关闭文件流以释放资源。 

#include <stdio.h>

int main() {
    int ch;
    FILE* file = fopen("example.txt", "r"); // 打开文件进行读取

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 读取并打印文件内容,直到文件结束
    while ((ch = fgetc(file)) != EOF) {
        putchar(ch); // 将读取到的字符打印到标准输出
    }

    if (ferror(file)) {
        perror("Error reading file");
    }

    fclose(file); // 关闭文件
    return 0;
}
  • fputc 
int fputc(int ch, FILE* stream);

在这个例子中,我们使用 fputc 将字符 ‘A’、‘B’ 和 ‘C’ 写入名为 “output.txt” 的文件中。然后我们关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入字符到文件
    fputc('A', file); // 写入字符 'A'
    fputc('B', file); // 写入字符 'B'
    fputc('C', file); // 写入字符 'C'

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fputs
int fputs(const char* str, FILE* stream);

fputs 不会自动在字符串的末尾添加换行符(\n),如果需要添加换行符,必须在字符串中包含换行符或者在调用 fputs 后显式地写入换行符。
在这个例子中,我们使用 fputs 将字符串 “Hello, World!” 写入名为 “output.txt” 的文件中。然后我们写入一个换行符,并关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。 

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入字符串到文件
    fputs("Hello, World!", file); // 写入字符串 "Hello, World!"

    // 写入换行符
    fputc('\n', file);

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fscanf
int fscanf(FILE* stream, const char* format, ...);

在这个例子中,我们使用 fscanf 从名为 “data.txt” 的文件中读取一个整数和一个浮点数。我们检查 fscanf 的返回值来确定是否成功读取了两个数据项。如果文件打开或读取过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

#include <stdio.h>

int main() {
    FILE* file = fopen("data.txt", "r"); // 假设文件包含整数和浮点数
    int num;
    float value;

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 从文件中读取整数和浮点数
    if (fscanf(file, "%d %f", &num, &value) == 2) {
        printf("Read: num = %d, value = %f\n", num, value);
    }
    else {
        printf("Failed to read data\n");
    }

    fclose(file); // 关闭文件
    return 0;
}
  • fprintf 
int fprintf(FILE* stream, const char* format, ...);

在这个例子中,我们使用 fprintf 将整数 42 和浮点数 3.14 写入名为 “output.txt” 的文件中,并且使用格式字符串来指定数据的输出格式。然后我们关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。 

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入格式化的数据到文件
    int num = 42;
    float value = 3.14f;
    fprintf(file, "The number is %d and the value is %f\n", num, value);

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fread 
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
  • ptr:指向要读取数据的内存块的指针。
  • size:每个数据项的大小,以字节为单位。
  • nmemb:要读取的数据项的数量。
  • stream:指向 FILE 对象的指针,该对象标识了输入流。这个流可以是标准输入 stdin,也可以是已经打开的文件流。
  • 返回值:fread 返回实际读取的数据项的数量,这个数量可能小于 nmemb 指定的数量,如果到达文件末尾或发生读取错误,则返回值小于 nmemb。

在这个例子中,我们使用 fread 从名为 “data.bin” 的文件中读取5个整数。我们检查 fread 的返回值来确定是否成功读取了5个数据项。如果文件打开或读取过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE* file = fopen("data.bin", "rb"); // 打开文件进行二进制读取
    int data[5]; // 假设文件包含5个整数

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 从文件中读取整数
    size_t num_read = fread(data, sizeof(int), 5, file);
    if (num_read != 5) {
        perror("Error reading data");
    }

    fclose(file); // 关闭文件

    // 打印读取到的整数
    for (size_t i = 0; i < num_read; i++) {
        printf("%d ", data[i]);
    }
    printf("\n");

    return 0;
}
  • fwrite 
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);

在这个例子中,我们使用 fwrite 将5个整数写入名为 “data.bin” 的文件中。我们检查 fwrite 的返回值来确定是否成功写入了5个数据项。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file = fopen("data.bin", "wb"); // 打开文件进行二进制写入
    int data[5] = {1, 2, 3, 4, 5}; // 假设要写入5个整数

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 将整数写入文件
    size_t num_written = fwrite(data, sizeof(int), 5, file);
    if (num_written != 5) {
        perror("Error writing data");
    }

    fclose(file); // 关闭文件

    return 0;
}

对比一组函数: 

这两主要讲解一些 sscanf sprintf

  • sprintf
int sprintf(char *str, const char *format, ...);

在这个例子中,我们使用 sprintf 将整数 42 和浮点数 3.14 格式化为字符串,并写入 buffer 数组中。然后我们打印 buffer 数组中的内容。sprintf 函数返回写入的字符数,这个数可以帮助我们确定字符串的实际长度,并确保 buffer 数组有足够的空间来存储结果。 

#include <stdio.h>

int main() {
    char buffer[100]; // 假设buffer足够大以存储结果
    int num = 42;
    float value = 3.14f;

    // 使用sprintf格式化字符串并写入buffer
    sprintf(buffer, "The number is %d and the value is %f\n", num, value);

    // 打印buffer中的内容
    printf("%s", buffer);

    return 0;
}
  • sscanf
int sscanf(const char *str, const char *format, ...);

在这个例子中,我们使用 sscanf 从字符串 “42 3.14” 中解析一个整数和一个浮点数。我们检查 sscanf 的返回值来确定是否成功解析了两个数据项。如果字符串中没有足够的输入数据,或者格式字符串中的格式规范符与输入数据不匹配,sscanf 可能不会成功匹配所有输入项,或者根本不匹配任何输入项。 

#include <stdio.h>

int main() {
    char input[20];
    int num;
    float value;

    // 假设输入字符串为 "42 3.14"
    strcpy(input, "42 3.14");

    // 从字符串中解析整数和浮点数
    if (sscanf(input, "%d %f", &num, &value) == 2) {
        printf("Parsed: num = %d, value = %f\n", num, value);
    } else {
        printf("Failed to parse data\n");
    }

    return 0;
}

5.  文件的随机读写

5.1 fssek 

根据文件指针的位置和偏移量来定位文件指针。 

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

参数说明:

  • stream:指向 FILE 对象的指针,该对象标识了要设置位置的文件流。
  • offset:要移动的字节数,可以是正数、负数或零。
  • origin:指定移动的起点,可以是以下常量之一:
  • SEEK_SET:从文件流的开始位置开始移动。
  • SEEK_CUR:从文件流的当前位置开始移动。
  • SEEK_END:从文件流的结束位置开始移动。 
#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r+"); // 打开文件进行读写操作

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 将文件指针移动到文件末尾
    if (fseek(file, 0, SEEK_END) == 0) {
        printf("File pointer moved to end of file\n");
    } else {
        perror("Error moving file pointer");
    }

    fclose(file); // 关闭文件
    return 0;
}

在这个例子中,我们使用 fseek 将文件指针移动到文件末尾。我们检查 fseek 的返回值来确定是否成功移动了文件指针。如果文件打开或移动过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。

5.2 ftell

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

long int ftell(FILE* stream);
/* ftell example : getting size of a file */
#include <stdio.h>
int main()
{
    FILE* pFile;
    long size;
    pFile = fopen("myfile.txt", "rb");
    if (pFile == NULL) perror("Error opening file");
    else
    {
        fseek(pFile, 0, SEEK_END);   // non-portable
        size = ftell(pFile);
        fclose(pFile);
        printf("Size of myfile.txt: %ld bytes.\n", size);
    }
    return 0;
}

5.3 rewind 

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

void rewind ( FILE * stream );
/* rewind example */
#include <stdio.h>
int main()
{
    int n;
    FILE* pFile;
    char buffer[27];
    pFile = fopen("myfile.txt", "w+");
    for (n = 'A'; n <= 'Z'; n++)
        fputc(n, pFile);
    rewind(pFile);
    fread(buffer, 1, 26, pFile);
    fclose(pFile);
    buffer[26] = '\0';
    puts(buffer);

    return 0;
}

6. 文本文件和二进制文件 

根据数据的组织形式,数据文件被称为文本文件或者二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件件
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而
二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。 

测试代码:

#include <stdio.h>

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

7. 文件读取结束的判定 

 7.1 文件的分类 

  • 从用户观点: 

特殊文件(标准输入输出文件或标准设备文件)。

普通文件(磁盘文件)。 

  • 从操作系统的角度看,每一个与主机相连的输入、输出设备看作是一个文件。

例:

输入文件:终端键盘

输出文件:显示屏和打印机 

  • 按数据的组织形式: 

 ASCII 文件(文本文件):每一个字节放一个 ASCII 代码。在文本文件(textfile)中,字节表示字符,这使人们可以检查或编辑文件。例如,C程序源代码是存储在文本文件中的。

二进制文件:把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。 在二进制文件(binaryfile)中,字节不一定表示字符;字节组还可以表示其他类型的数据,比如整数和浮点数。如果试图查看可执行C程序的内容,你会立刻意识到它是存储在二进制文件中的。

7.2 被错误使用的feof 

牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。 

而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

正确的使用:

文本文件的例子: 

二进制文件的例子: 

8. 文件缓冲区 

C语言对文件的处理方法:

缓冲文件系统:

非缓冲文件系统:

系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。用非缓冲文件系统进行的输入输出又称为低级输入输出系统。

int fflush(FILE *stream);

void setbuf(FILE *stream, char *buffer);

int setvbuf(FILE *stream, char *buffer, int mode, size_t size);

向磁盘驱动器传入数据或者从磁盘驱动器传出数据都是相对较慢的操作。因此,在每次程序想读或写字符时都直接访问磁盘文件是不可行的。获得较好性能的诀窍就是缓冲(buffering):把写入流的数据存储在内存的缓冲区域内;当缓冲区满了(或者关闭流)时,对缓冲区进行“清洗”(写入实际的输出设备)。输入流可以用类似的方法进行缓冲:缓冲区包含来自输入设备的数据,从缓冲区读数据而不是从设备本身读数据。缓冲在效率上可以取得巨大的收益,因为从缓冲区读字符或者在缓冲区内存储字符几乎不花什么时间。当然,把缓冲区的内容传递给磁盘,或者从磁盘传递给缓冲区是需要花时间的,但是一次大的“块移动”比多次小字节移动要快很多。

当程序向文件中写输出时,数据通常先放入缓冲区中。当缓冲区满了或者关闭文件时,缓冲区会自动清洗。然而,通过调用fflush函数,程序可以按我们所希望的频率来清洗文件的缓冲区。

  • 调用 fflush(fp);为和fp相关联的文件清晰了缓冲区。 
  • 调用 fflush(NULL);  清洗了全部输出流。如果调用成功,fflush函数会返回零;如果发生错误,则返回EOF。
#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语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。 如果不做,可能导致读写文件的问题。 

 本篇文章到此结束,这篇文章学透,对于C语言中的文件操作就会行云流水~麻烦点个赞评论支持一下吧!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务框架Go-kit 01 - 基础示例

一、Go kit简介 Go kit 是一个用于构建可扩展、灵活和可维护微服务的框架和工具集合。它提供了一系列库和组件&#xff0c;涵盖了微服务开发的各个方面&#xff0c;包括服务发现、负载均衡、通信、日志记录、请求跟踪、限流、熔断等。 Go kit 构建微服务时遵循一种类似于传统…

成都爱尔胡建斌院长提醒近视超过600度,记得每年检查眼底!

高度近视是指近视度数在600度及以上的一种屈光不正的状态。 近视的眼睛必定是变形的。在正常情况下&#xff0c;人的眼球类似球体&#xff0c;但随着近视加深&#xff0c;眼轴变长&#xff0c;眼球体积逐渐增大&#xff0c;整个眼球从圆球型向椭圆球形发展&#xff0c;而眼球壁…

HTTPS 协议原理详解

HTTPS 协议原理详解 什么是 HTTPS 协议什么是 SSL/TSL 层HTTPS 使用到的加密算法HTTPS 中 TLS 层的加密过程详解HTTPS 加密过程中用到的数字证书 什么是 HTTPS 协议 HTTPS &#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure &#xff09;&#xff0c;是以安全为…

栈(基于动态顺序表实现的栈)

栈的简单介绍 关于栈的性质咳咳 栈&#xff1a;栈是一种特殊的线性表,其中只让在一端插入和删除元素。 后进先出 进行插入删除的那一端叫栈顶&#xff0c;另一端叫栈底 我们实现的栈是基于一个动态顺序表的的栈&#xff0c;会实现栈的 入栈&#xff0c;出栈&#xff0c;获取…

Python知识点复习

文章目录 Input & OutputVariables & Data typesPython字符串重复&#xff08;字符串乘法&#xff09;字符串和数字连接在一起print时&#xff0c;要强制类型转换int为str用input()得到的用户输入&#xff0c;是str类型&#xff0c;如果要以int形式计算的话&#xff0c…

Dijkstra算法在《庆余年》中的应用:范闲的皇宫之旅

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

C语言 数组——向函数传递数组

目录 把数组传给函数&#xff08;Passing Arrays to Functions&#xff09; 向函数传递一维数组 向函数传递二维数组 数组在学生成绩管理中的应用 例&#xff1a;计算每个学生的平均分 把数组传给函数&#xff08;Passing Arrays to Functions&#xff09; 向函数传递一维…

校园霸凌行为监测AI预警系统

校园霸凌行为监测AI预警系统基于AI视觉智能分析算法&#xff0c;校园霸凌行为监测AI预警系统通过已安装的监控摄像头对校园现场画面进行实时监测。校园霸凌行为监测AI预警系统能够自动识别学生的违规行为&#xff0c;包括打架、跌倒、偷偷翻墙、人员聚众、攀高、抽烟等行为&…

【C++】右值引用 移动语义

目录 前言一、右值引用与移动语义1.1 左值引用和右值引用1.2 右值引用使用场景和意义1.3 右值引用引用左值及其一些更深入的使用场景分析1.3.1 完美转发 二、新的类功能三、可变参数模板 前言 本篇文章我们继续来聊聊C11新增的一些语法——右值引用&#xff0c;我们在之前就已…

马蹄集 oj赛(双周赛第二十七次)

目录 栈的min 外卖递送 奇偶序列 sort 五彩斑斓的世界 括号家族 名次并列 栈间 双端队列 合并货物 逆序对 活动分组 栈的min 难度:黄金巴 占用内存:128 M时间限制:1秒 小码哥又被安排任务了&#xff0c;这次他需要要设计一个堆栈&#xff0c;他除了可以满足正常的栈…

Spring Security整合Gitee第三方登录

文章目录 学习链接环境准备1. 搭建基本web应用引入依赖ThirdApp启动类创建index页面application.yml配置访问测试 2. 引入security引入依赖ProjectConfig访问测试 第三方认证简介注册gitee客户端实现1引入依赖application.yml配置文件创建index.html页面启动类InfoControllerPr…

【openlayers系统学习】3.4波段数学计算(计算NDVI)

四、波段数学计算&#xff08;计算NDVI&#xff09; 我们已经看到了如何使用 ol/source/GeoTIFF​ 源代码来渲染真彩色和假彩色合成。我们通过将缩放的反射率值直接渲染到红色、绿色或蓝色显示通道中的一个来实现这一点。还可以对来自GeoTIFF&#xff08;或其他数据瓦片源&…

javaSwing购物系统项目(文档+视频+源码)

摘要 由Java swing实现的一款简单的购物程序&#xff0c;数据库采用的是mysql&#xff0c;该项目非常简单&#xff0c;实现了管理员对商品类型和商品的管理及用户注册登录后浏览商品、加入购物车、购买商品等功能&#xff0c;旨在学习Java 图形界面开发 系统实现 我们先来管理…

20240516-Flyme AIOS 特种兵发布会

目录 1 Flyme AIOS 2 路演功能 2.1 拖拽流转 2.2 任务剧本自定义 2.3 智能体商店 2.4 实况通知 2.5 AI壁纸 3 MYVU 3.1 翻译功能 3.2 AR导航-骑行 3.3 AI语音转文字-科技向善 3.4 Flyme AR-提词器增强 1 Flyme AIOS 1&#xff09;目标&#xff1a;All in AI&#…

Android:OkHttp网络请求框架的使用

目录 一&#xff0c;OkHttp简介 二&#xff0c;OkHttp请求处理流程 三&#xff0c;OkHttp环境配置 四&#xff0c;OkHttp的使用 1.get网络请求 2.post上传表单数据 3.post上传json格式数据 4.文件上传 5.文件下载 一&#xff0c;OkHttp简介 OkHttp是square公司推出的一…

淘宝api接口是什么意思?api接口申请资格是什么?

淘宝其开放性和灵活性为开发者提供了广阔的创新空间。而淘宝API接口&#xff0c;作为连接淘宝平台与外部应用的桥梁&#xff0c;发挥着至关重要的作用。那么&#xff0c;淘宝api接口是什么意思&#xff1f; 一、淘宝API接口是什么意思&#xff1f; 淘宝API接口&#xff0c;全称…

UNI-APP设置屏幕保持常亮-不熄灭屏幕

前言 最近在实际开发过程中&#xff0c;我们会发现在自己使用的app当中会根据系统无操作熄灭屏幕对于一下需要长时间保持屏幕的业务就很不友好&#xff0c;uni-app也是提供了相应方法加上代码之后-注意app端没报错-不生效就是权限问题-需要设置相对应权限-打自定义包 代码实现…

vue+springboot实现echarts数据图统计

①vue项目修改配置 安装依赖&#xff1a; npm i echarts -S 修改路由index.js&#xff1a; import Vue from vue import VueRouter from vue-router import Manager from ../views/Manager.vue // 解决导航栏或者底部导航tabBar中的vue-router在3.0版本以上频繁点击菜单报错…

【编译原理复习笔记】语法分析-补充(二义性与LR错误处理)

二义性文法的 LR 分析 每个二义性文法都不是 LR 的 但是某些二义性文法更加简短&#xff0c;描述更方便 如 I7 和 I8 具有移进归约冲突 使用优先级和结合性解决冲突 对于 I7&#xff0c;由于乘号优先级高于加号&#xff0c;所以当下一个输入符号为乘号时&#xff0c;我们优…