C语言基础16(文件IO)

文章目录

    • 构造类型
      • 枚举类型
      • typedef
    • 文件操作(文件IO)
      • 概述
      • 文件的操作
        • 文件的打开与关闭
          • 打开文件
          • 关闭文件
          • 文件打开与关闭案例
        • 文件的顺序读写
          • 单字符读取
          • 多字符读取
          • 单字符写入
          • 多字符写入
      • 综合案例:文件拷贝
          • 判别文件结束
        • 数据块的读写(二进制)
          • 数据块的读取
          • 数据块的写入
        • 文件的随机读写

构造类型

枚举类型

如果定义不相干的常量,使用宏定义;如果需要定义一组相关的常量,使用枚举。以后正式开发,switch的case后访问的就是枚举

  • 定义:

我们一般情况下,定义常量使用宏定义(#define宏名称值),宏定义非常适合没有关联关系的常量;但是有时候我们可能需要对一组拥有关联关系的量进行定义,比如周一——周日,1月~12月、方向(上下左右中)等,那么使用宏定义就不是很清晰,这个时候就需要使用到枚举

枚举的存在就是将多个拥有关系的常量组合在一起,提高代码的可读性

  • 说明:

枚举类型定义了一组常量,我们在开发中直接使用这些常量(常用)

当然枚举类型也可以类似于结构体一样定义变量等操作(不常用)

枚举常量是有默认值,从0开始依次+1;我们可以在定义时指定它的默认值,如果个别没有赋值,可以根据赋值依次+1推导

  • 特点:

定义了一组常量,类似于定义了多个自定义常量(宏定义)

提供了代码的可读性

  • 定义语法:

定义枚举类型名以后就可以定义该枚举类型的变量

enum 枚举类型名 变量列表;

在定义枚举类型的同时定义该枚举类型的变量

enum 枚举类型名{枚举元素列表} 变量列表;

直接定义枚举变量

enum {枚举元素列表} 变量列表;
  • 案例:
#include <stdio.h>void test2()
{//定义枚举enum CaiQuan{SHI_TOU,JIAN_DAO,BU};printf("请输入0~2之间的整数:\n[0-石头,1-剪刀,2-布]\n");int number;scanf("%d",&number);switch(number){case SHI_TOU:printf("石头\n");break;case JIAN_DAO:printf("剪刀\n");break;case BU:printf("布\n");break;}
}int main(int argc,char *argv[])
{test2();return 0;
}

在这里插入图片描述

typedef

  • 说明:给类型重命名,不会影响到类型本身
  • 作用:给已有的类型起别名
  • 格式:
typedef 已有的类型名 新别名;
  • 使用:
//方式1:先定义结构体的类型,再重命名
//定义一个结构体
struct Student
{int id;char *name;char sex;int age;
};//类型重命名
typedef struct Student Stu;//定义结构体变量
struct Stu stu = {1,"张三",'w',21};//方式2:定义结构体的同时重命名
typedef struct PersonInfo
{int a;double b;
} Per;//结构体类型的别名,本质上还是数据类型//定义变量
struct Per per = {2,5};
  • 应用场景:

    • 数据类型复杂(结构体、共用体、枚举、结构体指针、无符号的长整型)时使用

    • 为了跨平台兼容性,例如:

      1.size_t:类型重命名后的数据类型:typedef unsigned long size_t;

      2.unit_16:类型重命名后数据类型

  • 案例:

#include <stdio.h>int main(int argc,char *argv[])
{long p;FILE *fp;if((fp = fopen(argv[1],"a") == NULL))  //此时的mode:a代表追加(a是append的缩写){printf("文件打开失败!");return -1;}//获取当前位置p = ftell(fp);printf("p = %ld\n",p);//向文件添加数据fputs("data",fp);p = ftell(fp);printf("p = %ld\n",p);fclose(fp);return 0;
}

文件操作(文件IO)

概述

  • 什么是文件

文件是保存在外存储器(一般代指磁盘,U盘,移动硬盘等)的数据的集合

  • 文件操作体现在哪几个方面

​ 1.文件内容的读取

​ 2.文件内容的写入

数据的读取和写入可被视为针对文件进行输入(Input)和输出(Output)操作,此时数据像水流一样从外存储器流向内存,或者从内存流向外存储器,所以系统形象的 称文件操作为文件流

C语言程序对文件的操作采用“文件缓冲机制”。就是说在程序对文件的数据读写并不是直接操作文件中的数据,而是系统会为文件在内存中创建“文件缓冲区”,程序对文件的操作,其实是在缓冲区进行的

在这里插入图片描述

  • 文件的分类

根据数据的存储方式划分:

①文本文件(ascii文件)

②二进制文件

  • 文件的标识

    ①文件系统中:路径+文件名,举例:d:/aaa/bbb.txt

​ ②C语言程序中:文件指针(文件类型指针),语法:FILE* 指针变量名;

  • 文件操作的步骤:

①打开文件

②文件处理(读写文件)

③关闭文件

文件的操作

文件的打开与关闭
打开文件

打开文件,让系统为文件创建文件缓冲区

  • 函数名:fopen()
  • 头文件:#include <stdio.h>
  • 函数原型:FIFE* fopen(const char *path,const char *mode);
  • 函数功能:打开文件,并为文件创建缓冲区
  • 函数参数:
    • path:目标文件的路径
    • mode:文件打开的方式(读-r,写-w,读写-r+,二进制读-rb,追加-a)
  • 返回值:
    • 成功:返回文件指针FILE*(缓冲区首地址)
    • 失败:返回NULL
关闭文件

文件关闭,文件使用完毕一定要记得释放内存

  • 函数名:fcolse

  • 头文件:#include <stdio.h>

  • 函数原型:int fclose(FILE* fp);

  • 函数功能

    • fp:已经打开的文件指针
  • 返回值:

    • 成功:返回0
    • 失败:返回EOF(-1)
文件打开与关闭案例
#include <stdio.h>int main(int argc,char *argv[])
{//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc < 2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);// ./a/out ./demo01.creturn -1;}//根据提供的文件路径,打开文件(mode:r,w,rw)FILE* fp = fopen(argv[1],"r");//校验文件是否读取成功if(!fp){perror("文件打开失败!\n");return -1;}puts("文件打开成功!");//关闭打开的文件int ret = fclose(fp);if(ret == -1){perror("文件关闭失败!");return -1;}puts("文件关闭成功!");return 0;
}

在这里插入图片描述

文件的顺序读写
单字符读取
  • 函数名:fgetc

  • 头文件:#include <stdio.h>

  • 函数原型:int fgetc(FILE* fp);

  • 函数功能:从fp代表的文件中获取一个字符

  • 函数参数:

    • fp:我们需要操作的文件的指针
  • 返回值:

    • 成功:返回读取到的字符
    • 失败:或者文件末尾,返回EOF(-1)

方式1:

#include <stdio.h>int main(int argc,char *argv[])
{//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc < 2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);// ./a/out ./demo01.creturn -1;}//根据提供的文件路径,打开文件(mode:r,w,rw)FILE* fp = fopen(argv[1],"r");//校验文件是否读取成功if(!fp){perror("文件打开失败!\n");return -1;}puts("文件打开成功!");//读取文件int ret = 0;while((ret = fgetc(fp)) != -1){printf("%c",ret);}//关闭打开的文件int cet = fclose(fp);if(cet == -1){perror("文件关闭失败!");return -1;}puts("文件关闭成功!");return 0;
}

方式2:

#include <stdio.h>
int main(int argc,char *argv[])
{
// 在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址
if(argc < 2)
{
printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);// ./a.out ./demo01.c
return -1;
}
// 根据提供的文件路径,打开文件(mode:r,w,rw)
FILE* fp = fopen(argv[1],"r");
// 校验文件是否读取成功
if(!fp)
{
perror("文件打开失败!\n");
return -1;
}
puts("文件打开成功!");
// 单字符读取文件
char ch;
// 循环读取文件中所有字符
while((ch = fgetc(fp))!= EOF)printf("%c",ch);
// 关闭打开的文件
int ret = fclose(fp);
if(ret == -1)
{
perror("文件关闭失败!");
return -1;
}
puts("文件关闭成功!");
return 0; 
多字符读取
  • 函数名:fgets();

  • 头文件: #include <stdio.h>

  • 函数原型:char* fgets(char *buf,int size,FILE* fp);

  • 函数功能:从fp代表的文件中获取size个字符(size大小以字节为单位),放置在buf代表的内存中

  • 函数参数:

    • buf:内存空间首地址,用于存放读取的字节
    • size:待读取的字符,实际读取size
    • fp:已经打开文件的指针
  • 返回值:

    • 成功:返回buf(返回得到的字符串)
    • 失败:或者文件末尾,返回NULL
  • 案例:

#include <stdio.h>
#include <string.h>int main(int argc,char *argv[])
{if(argc < 2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);}FILE* fp;char* arr;fp =  fopen(argv[1],"r");if(!fp){perror("文件打开失败!\n");return -1;}puts("文件打开成功");char buf[64] = {0};fgets(buf,64,fp);//多字符串的读取while(fgets(buf,64,fp) != NULL) {printf("%s",buf);memset(buf,0,sizeof(buf));}printf("\n");int ret =  fclose(fp);if(ret == -1){perror("文件关闭失败!\n");return -1;}puts("文件关闭成功!\n");return 0;
}
单字符写入
  • 函数名:fputc()
  • 头文件: #include <stdio.h>
  • 函数原型: int fputc(int c,FILE* fp);
  • 函数功能:向fp代表的文件中写入一个字符c
  • 函数的参数
    • c:待写入的字符
    • fp:已打开的文件指针
  • 返回值:
    • 成功:返回字符c
    • 失败:返回EOF(-1)
  • 案例:
#include <stdio.h>int main(int argc, char *argv[])
{// argc:表示命令行输入的文件个数if (argc < 3){printf("输入有误,请按照<%s 文件路径 文件数据>格式输入\n", argv[0]);return -1;}// argv[1]:表示需要读取内容的文件,argv[2]表示需要写入字符的文件FILE *fp;fp = fopen(argv[1], "w");if (!fp){perror("文件打开失败!\n");return -1;}puts("文件打开成功\n");while (*argv[2] != '\0'){fputc(*argv[2], fp);argv[2]++; // 指针偏移}// 关闭文件int ret = fclose(fp);if (ret == -1){perror("文件关闭失败!\n");return -1;}puts("文件关闭成功\n");return 0;
}
多字符写入
  • 函数名:fputs()

  • 头文件: #include <stdio.h>

  • 函数原型: int fputs(const char* buf,FILE* fp);

  • 函数功能:向fp代表的文件中写入一个字符数组buf

  • 函数的参数

    • buf:待写入的字符数组(写入缓冲区)
    • fp:已打开的文件指针
  • 返回值:

    • 成功:返回非负整数比0大(>0)
    • 失败:返回EOF(-1)
  • 案例:

#include <stdio.h>int main(int argc,char *argv[])
{if(argc < 3){printf("输入有误,请按照<%s 文件路径 文本数据>格式输入\n",argv[0]);return -1;}FILE* fp = fopen(argv[1],"w");if(!fp){perror("文件打开失败!");return -1;}fputs(argv[2],fp);fclose(fp);return 0;
}

综合案例:文件拷贝

实现从a文件读取内容,写入到b文件

#include <stdio.h>
#include <string.h>int main(int argc,char *argv[])
{if(argc < 3){printf("请以正确的方式%s",argv[0]);return -1;}FILE* fp1;FILE* fp2;fp1 = fopen(argv[1],"r");fp2 = fopen(argv[2],"w");if(!fp1 || !fp2){perror("文件打开失败!");return -1;}puts("文件打开成功!\n");//读取第一个文件中的内容,使用fgets//创建一个缓冲区(也就是每次获取字节的大小)char buf[64];fgets(buf,64,fp1);while(fgets(buf,64,fp1) != NULL){fputs(buf,fp2);memset(buf,0,64);}//判断文件是否读取完成int k = feof(fp1);if(!k){printf("文件读取未完成\n");}else{printf("文件读取完成\n");}//关闭文件int r1 =  fclose(fp1);int r2 =  fclose(fp2);if(r1 == -1 || r2 == -1){perror("文件关闭失败!");return -1;}puts("文件关闭成功\n");return 0;
}
判别文件结束
  • 函数名:feof(fp)

  • 头文件:#include <stdio.h>

  • 函数原型:int feof(FILE* fp);

  • 函数功能:在读fp指向的文件时判断是否遇到文件结束

  • 函数参数:

    • fp:已打开文件的指针
  • 返回值:

    • 文件未读取完毕:返回0
    • 文件已读取完毕:返回非0
数据块的读写(二进制)
数据块的读取
  • 函数名:fread
  • 函数原型:size_t fread(void* ptr,size_t size,size_t count,FILE* fp);
  • 函数功能:从fp代表的文件中以字节为单位(一个数据块)读取count个数据块存放在内存中
  • 函数参数:
    • ptr:内存空间首地址,用于存放读取到的数据(任意类型缓冲数据)
    • size:数据块大小,以字节为单位
    • count:待读取的数据块的个数
    • fp:已打开的文件指针
  • 返回值:
    • 成功:返回实际读取的字节数大小
    • 失败:返回<0
#include <stdio.h>#define SIZE 4 // 存放学生个数struct Student
{char name[20];int num;int age;char addr[50];
} stus[SIZE];int main(int argc, char *argv[])
{int i;FILE *fp;stus[1].num  = 6;stus[1].age = 13;fp = fopen("stu-list","rb");if (fopen("stu-list", "rb") == NULL){perror("文件打开失败!");return -1;}// 循环读取二进制读取for (i = 0; i < SIZE; i++){fread(&stus[i], sizeof(struct Student), 1, fp);printf("%-10s%-4d%-4d%-20s\n", stus[i].name, stus[i].num, stus[i].age, stus[i].addr);}// 关闭文件fclose(fp);return 0;
}
数据块的写入
  • 函数名:fwrite

  • 函数原型:size_t fwrite(const void* ptr,size_t size,size_t count,FILE* fp);

  • 函数功能:向fp代表的文件中以size为一个数据块写入count个数据块到fp

  • 函数参数:

    • ptr:内存空间首地址,用于存放写入的数据(任意类型缓冲数据)

    • size:数据块大小,以字节为单位

    • count:待写入的数据块的个数

    • fp:已打开的文件指针

  • 返回值:

    • 成功:返回实际写入的字节数
    • 失败:写入完毕,返回<0
#include <stdio.h>#define SIZE 4 // 存放学生个数struct Student
{char name[20];int num;int age;char addr[50];
} stus[SIZE];int main(int argc, char *argv[])
{int i;FILE *fp;stus[1].num  = 6;stus[1].age = 13;stus[2].num = 3;stus[2].age = 56;stus[3].num = 10;stus[3].age = 23;fp = fopen("stu-list","wb");if (fopen("stu-list", "wb") == NULL){perror("文件打开失败!");return -1;}// 循环读取二进制读取for (i = 0; i < SIZE; i++){fwrite(&stus[i], sizeof(struct Student), 1, fp);//printf("%-10s%-4d%-4d%-20s\n", stus[i].name, stus[i].num, stus[i].age, stus[i].addr);}// 关闭文件fclose(fp);return 0;
}

在这里插入图片描述

文件的随机读写
  • 说明:C语言允许程序员在读写文件内容的时候,可在指定位置上读写数据
  • 文件随机读写的核心操作:文件位置指针的定位
  • 文件位置指针移动方法:
    • rewind
      • 头文件:#include <stdio.h>
      • 函数原型:void rewind(FILE* fp);
      • 函数功能:将文件位置指针定位到文件开头
      • 函数参数:
        • fp:已经打开文件的指针
      • 返回值:空类型
    • fseek
      • 头文件:#include <stdio.h>
      • 函数原型:int fseek(FILE* fp,long offset,int whence);
      • 函数功能:将文件位置指针定位到指定位置
      • 函数参数:
        • fp:已经打开的文件的指针
        • offset:相对于参考位置的偏移量
        • whence:参考位置
          • SEEK_SET或0:表示文件头
          • SEEK_CUR或1:表示当前读写的位置
          • SEEK_END或2:表示文件尾
        • 返回值:
          • 成功:0
          • 失败:-1
    • ftell
      • 头文件:#include <stdio.h>
      • 函数原型:long ftell(FILE* fp);
      • 函数功能:获取文件位置指针当前位置
      • 函数参数:
        • fp:已经打开的文件指针
      • 返回值:
        • 成功:文件位置指针的当前位置
        • 失败:-1

​ 案例:

#include <stdio.h>int main(int argc,char *argv[])
{//创建两个指针,用来接收打开的文件FILE* fp1,*fp2;if(argc < 2){perror("请使用<%s 被读取文件,被写入文件>的方式!\n");return -1;}//打开文件fp1 = fopen(argv[1],"r");fp2 = fopen("argv[2]","w");//第一次,读取文件内容通过控制台打印while(!feof(fp1)){putchar(getc(fp1));//输出到控制台}//将指针指向文件的头,否则下次读取文件,会读取不到内容rewind(fp1);//第二次,读取文件内容将其拷贝至fp2对应的文件中while(!feof(fp1)){putc(getc(fp1),fp2);//输出到文件}//关闭文件fclose(fp1);fclose(fp2);return 0;
}

案例2

#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建两个指针,用来接收打开的文件
FILE *fp1, *fp2;
if(argc < 2)
{
perror("请使用<%s 被读取文件 被写入文件>的方式!\n");
return -1;
}
// 打开文件
fp1 = fopen(argv[1],"r");
fp2 = fopen(argv[2],"w");
// 第一次,读取文件内容通过控制台打印
while(!feof(fp1))
putchar(getc(fp1));// 输出到控制台
// 将指针指向文件的头,否则下次读取文件,会读取不到内容
rewind(fp1);
// 第二次,读取文件内容将其拷贝至fp2对应的文件中
while(!feof(fp1))
putc(getc(fp1),fp2);// 输出到文件
// 关闭文件
fclose(fp1);
fclose(fp2);
return 0;
}

案例3

#include <stdio.h>int main(int argc,char *argv[])
{long p;FILE* fp;fp = fopen(argv[1],"a");if(fopen(argv[1],"a") == NULL)//a表示追加{perror("文件打开失败!");return -1;}//p = ftell(fp);printf("p = %ld\n",p);//向文件添加数据fputs("data",fp);printf("p = %ld\n",p);fclose(fp);return 0;
}

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

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

相关文章

【Unity/HFSM】使用UnityHFSM实现输入缓冲(预输入)和打断机制

文章目录 前言预输入Animancer的InputBuffer&#xff1a;在UnityHFSM中实现InputBuffer&#xff1a; 打断机制 前言 参考Animancer在状态机中的InputBuffer&#xff0c;在UnityHFSM中实现类似的InputBuffer机制&#xff0c;同时扩展一个状态打断机制 插件介绍&#xff1a; A…

运维日记

运维 内容分发网络(CDN):使用CDN将图片分发到离用户更近的服务器,减少传输时间sudo的权限配置是通过/etc/sudoers文件管理的,这个文件定义了哪些用户在哪种条件下执行什么命令。直接编辑这个文件是有风险的,因为错误的语法可能导致系统无法正常使用sudo功能,因此使用vi…

前端需要学什么

作为前端开发者&#xff0c;学习的内容不仅仅局限于 HTML、CSS 和 JavaScript。前端技术栈发展迅速&#xff0c;想要在职业生涯中不断进步&#xff0c;可以从以下几个方面规划学习路径&#xff1a; 1. 核心前端技能 掌握前端开发的基础和进阶知识&#xff1a; HTML/CSS/JavaS…

用python+YOLOV8图片车辆车距

1. 检测车辆&#xff1a; 使用深度学习模型&#xff08;例如 YOLO、Mask R-CNN&#xff09;来检测照片中的车辆&#xff0c;并得到每辆车的边界框&#xff08;Bounding Box&#xff09;。 工具与技术&#xff1a; YOLOv5/YOLOv8&#xff1a;高效的实时目标检测模型。OpenCV&…

【数理统计】参数估计

文章目录 点估计矩估计法最大似然估计法 区间估计单个正态总体参数的区间估计均值 μ \mu μ 的区间估计方差 σ 2 \sigma^2 σ2 的区间估计 两个正态总体参数的区间估计&#xff08;略&#xff09;补充&#xff1a;单侧置信区间 点估计 矩估计法 【定义】设 X X X 是随机…

冯诺依曼架构与哈佛架构的对比与应用

冯诺依曼架构&#xff08;Von Neumann Architecture&#xff09;&#xff0c;也称为 冯诺依曼模型&#xff0c;是由著名数学家和计算机科学家约翰冯诺依曼&#xff08;John von Neumann&#xff09;在1945年提出的。冯诺依曼架构为现代计算机奠定了基础&#xff0c;几乎所有现代…

linux不同发行版中的主要差异

一、初始化系统 Linux不同发行版中的系统初始化系统&#xff08;如 System V init、Upstart 或 systemd&#xff09; System V init&#xff1a; 历史&#xff1a;System V init 是最传统的 Linux 系统初始化系统&#xff0c;起源于 Unix System V 操作系统。运行级别&#xff…

3D造型软件solvespace在windows下的编译

3D造型软件solvespace在windows下的编译 在逛开源社区的时候发现了几款开源CAD建模软件&#xff0c;一直囿于没有合适的建模软件&#xff0c;虽然了解了很多的模拟分析软件&#xff0c;却不能使之成为整体的解决方案&#xff0c;从而无法产生价值。opencascad之流虽然可行&…

机器学习04-为什么Relu函数

机器学习0-为什么Relu函数 文章目录 机器学习0-为什么Relu函数 [toc]1-手搓神经网络步骤总结2-为什么要用Relu函数3-进行L1正则化修改后的代码解释 4-进行L2正则化解释注意事项 5-Relu激活函数多有夸张1-细数Relu函数的5宗罪2-Relu函数5宗罪详述 6-那为什么要用这个Relu函数7-文…

Redis篇-21--运维篇3-集群(分片,水平扩展,高可用,集群配置案例,扩展哨兵案例)

1、概述 Redis集群&#xff08;Cluster&#xff09;通过分片&#xff08;sharding&#xff09;实现了水平扩展&#xff0c;允许数据分布在多个节点上&#xff0c;从而提升性能和存储容量。 在Redis集群中&#xff0c;数据被分割成16384个哈希槽&#xff08;hash slots&#x…

QScreen在Qt5.15与Qt6.8版本下的区别

简述 QScreen主要用于提供与屏幕相关的信息。它可以获取有关显示设备的分辨率、尺寸、DPI&#xff08;每英寸点数&#xff09;等信息。本文主要是介绍Qt5.15与Qt6环境下&#xff0c;QScreen的差异&#xff0c;以及如何判断高DPI设备。 属性说明 logicalDotsPerInch&#xff1…

[HNCTF 2022 Week1]你想学密码吗?

下载附件用记事本打开 把这些代码放在pytho中 # encode utf-8 # python3 # pycryptodemo 3.12.0import Crypto.PublicKey as pk from hashlib import md5 from functools import reducea sum([len(str(i)) for i in pk.__dict__]) funcs list(pk.__dict__.keys()) b reduc…

shell8

until循环(条件为假的时候一直循环和while相反) i0 until [ ! $i -lt 10 ] doecho $i((i)) done分析 初始化变量&#xff1a; i0&#xff1a;将变量i初始化为0。 条件判断 (until 循环)&#xff1a; until [ ! $i -lt 10 ]&#xff1a;这里的逻辑有些复杂。它使用了until循环…

【游戏中orika完成一个Entity的复制及其Entity异步落地的实现】 1.ctrl+shift+a是飞书下的截图 2.落地实现

一、orika工具使用 1)工具类 package com.xinyue.game.utils;import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.DefaultMapperFactory;/*** author 王广帅* since 2022/2/8 22:37*/ public class XyBeanCopyUtil {private static MapperFactory mappe…

frp内网穿透笔记

文章目录 一、环境介绍二、配置过程2.1 下载文件2.3 服务器A的配置2.3 目标机B的配置2.4 电脑C怎么用 三、问题汇总 一、环境介绍 带公网的vps服务器A&#xff0c;需要穿透到的无公网目标电脑B&#xff0c;以及一台需要通过公网访问B的电脑C。frp 0.47.0&#xff1a;frp_0.47.…

PostgreSQL的交互式终端使用一系列命令来获取有关文本搜索配置对象的信息

在 psql&#xff08;PostgreSQL 的交互式终端&#xff09;中&#xff0c;你可以使用一系列命令来获取有关文本搜索配置对象的信息。这些命令主要围绕 \dF 系列&#xff0c;以及使用 SQL 查询 pg_ts_config 系统视图。以下是你可以使用的一些方法&#xff1a; 使用 \dF 系列命令…

写定制程序容易遇见的问题(FLASH不够时)

做了一个关于定制两条串口协议的活&#xff0c;主要是要在源代码基础上进行修改。源代码只剩了200多字节flash。本来最初我的想法很奇特&#xff0c;用结构体来模仿寄存器的写法。当我写完几行代码后&#xff0c;编译链接&#xff0c;立马就报CODE内存超了。 然后最终还是选择…

【Leetcode 热题 100 - 扩展】303. 区域和检索 - 数组不可变

问题背景 给定一个整数数组 n u m s nums nums&#xff0c;处理以下类型的多个查询&#xff1a; 计算索引 l e f t left left 和 r i g h t right right&#xff08;包含 l e f t left left 和 r i g h t right right&#xff09;之间的 n u m s nums nums 元素的 和 &a…

本地缓存和Redis缓存 存储更新时间的更新套路

//先获取redis key和local key //从reids中获取数据 – 为空 先设置redis缓存30天,value为当前时间 然后设置本地缓存,value为当前时间 从数据库里读数据 – 不为空 获取本地缓存时间 if本地缓存时间 < redis缓存时间(认为已更新)或者本地为空 从数据库读数据 else 从本地缓…

处理错误的两种方式:try...catch 与 then...catch

一、try...catch try...catch 是一种用于捕获和处理同步代码中异常的机制。其基本结构如下&#xff1a; try {// 可能会抛出异常的代码 } catch (error) {// 处理异常 }使用场景&#xff1a; 主要用于同步代码&#xff0c;尤其是在需要处理可能抛出的异常时。适用于函数调用…