C语言提高(2)

news2024/9/20 16:57:58

calloc
void *calloc(size_t namber,size_t size);
功能:在内存动态存储区中分配namber块长度为size字节的连续区域。calloc自动将分配的内存置0
namber:所需内存单元数量
size:每个内存单元的大小(单位:字节)
返回值:
成功:分配空间的起始地址
失败:NULL

/** calloc **/
void test()
{
	int *p = calloc(10,sizeof(int));
	for(int i = 0;i < 10;++i)
	{
		p[i] = i+1;
	}
	//释放内存
	if(p != NULL)
	{
		free(p);
		p = NULL;
	}
}

realloc
void *realloc(void *ptr, size_t size);
功能:重新分配用malloc或者calloc函数在堆中分配的内存空间大小。
realloc不会自动清理增加 的内存,需要手动清理,如果指定的地址后面又连续的空间,那么就会在已有地址基础上增加内存,如果指定的地址后面没有空间,那么realloc会重新分配新的连续内存,把旧内存的值拷贝到新内存,同时释放旧内存
ptr:为之前用malloc或者calloc分配的内存地址,如果此参数等于NULL,那么和realloc与calloc功能一致
size:为重新分配内存的大小,单位:字节
返回值:
成功:新分配的堆内存地址
失败:NULL

/**realloc**/
void test()
{
	int *p = malloc(sizeof(int)*10);
	for(int i = 0;i < 10;++i)
	{
		p[i] = i + 1;
	}
	p = realloc(p,sizeof(int)*20);//扩展20个int类型大小的内存空间
}

sscanf
int sscanf(const char *str,const char *format,...);
功能:从str指定的字符串读取数据,并根据参数format字符串类转换并格式化数据。
str:指定的字符串首地址
format:字符串格式,用法和scanf()一样
返回值:
成功:实际读取的字符个数
失败:-1

格式作用
%*s或%*d跳过数据(%*s跳过字符串、%*d跳过数字)
%[width]s读指定宽度的数据
%[a-z]匹配a到z中任意字符(尽可能多的匹配)
%[aBc]匹配a、B、c中一员,贪婪性
%[^a]匹配非a的任意字符,贪婪性
%[^a-z]表示读取除a-z以外的所有字符
//%*s或%*d  跳过数据
void test()
{
	#if 0
	char *str = "12345abcde";
	char buf[1024] = { 0 };
	sscanf(str,"%*d%s",buf);//忽略数字并且匹配字符串
	printf("buf:%s\n",buf);//buf:abcd
	#end if
	
	char *str = "abcde 12345";//字符串和数字之间需要加空格
	char buf[1024] = { 0 };
	sscanf(str,"%*s%d",buf);//忽略字符串匹配数字
	printf("buf:%s\n",buf);//buf:12345
}

//%[width]s 读取指定宽度的数据
void test01()
{
	char *str = "12345abcde";
	char buf[1024] = { 0 };
	sscanf(str,"%6s",buf);//读取6个数据
	printf("buf:%s\n",buf);//buf:12345a
}

//%[a-z]匹配a到z中任意字符(尽管可能多的匹配)
void test02()
{
	//char *str = "12345abcde";
	char *str = "abcde12345";
	/**
	在使用匹配的时候如果发现第一个数据不匹配那么就会自动退出,
	因此需要将字母放在前面才能匹配到想要的结果
	 **/
	char buf[1024] = { 0 };
	sscanf(str,"%[a-z]",buf);//匹配a到z中任意字符(尽管可能多的匹配)
	printf("buf:%s\n",buf);//buf:abcde
}

// %[aBc] 匹配a、B、c中一员,贪婪性 
void test03()
{
	char *str = "aABbcde";
	char buf[1024] = { 0 };
	sscanf(str,"%[aAb]",buf);//匹配a、B、c中一员,贪婪性
	printf("buf:%s\n",buf);//buf:aA
}

//%[^a] 匹配非a的任意字符,贪婪性
void test04()
{
	char *str = "aABbcde";
	char buf[1024] = { 0 };
	sscanf(str,"%[^c]",buf);//匹配非c的字符
	printf("buf:%s\n",buf);//buf:aABb
}

//%[^a-z] 表示读取除a-z以外的所有字符
void test05()
{
	char *str = "aABbcde12345";
	char buf[1024] = { 0 };
	sscanf(str,"%[^0-9]",buf);//匹配非0-9的字符
	printf("buf:%s\n",buf);//buf:aABbcde
}

void test06()
{
	char *str = "abcde#12uip@0plju";
	char buf[1024] = {0};
	sscanf(str,%*[^#]#%[^@],buf);
	printf("buf:%s\n",buf);//buf:12uip
}
//查找子串第一次出现的位置
void myStrStr( const char *str,const char *substr)
{
	const char *mystr = str;
	const char *mysub = substr;

	while(*mystr != '\0') 
	{
		if(*mystr != *mysub)
		{
			++mystr;
			continue;
		}
		//临时指针变量
		char *temp_mystr = mystr;
		char *temp_mysub = mysub;
		
		while(*temp_mystr != '\0')
		{
			if(*temp_mystr != *temp_mysub)
			{
				++mystr;
				break;
			}
			++temp_mysub;
			++temp_mystr;
		}
		if(*temp_sub == '\0')
		{
			return mystr;
		}	
		++mystr;
	}
	return NULL; 
}

const的使用
const变量放在常量区

/**
	一般函数传递参数的时候都不进行值传递
	大部分使用地址传递
	并且在哪函数中如果传入参数不涉及值修改
	可以在其参数之前加上const关键字
	以防参数值被修改
**/
struct Person
{
	char name[64];
	int age;
	int ID;
	double source;
};
#if 0
void PrintPerson(const struct Person person)
{
	printf("Name:%s Age:%d ID:%d source:%d\n",person.name,person.age,person.ID,person.source);
}
#else if
void PrintPerson(const struct Person *person)
{
	printf("Name:%s Age:%d ID:%d source:%d\n",person->name,person->age,person->ID,person->source);
}
#end if
void test()
{
	struct Person person = {"trump",30,250,59.9};
#if 0
	PrintPerson(person);
#else if
	PrintPerson(&person);
#end if
}

指针的指针(二级指针)
指针的指针:存储的值是另一个指针的地址
在这里插入图片描述

/**
	二级指针做函数参数的输出特性
**/
void allocateSpace(int **temp)
{
	int *arr = malloc(sizeof(int)*10);
	for(int i = 0;i < 10;++i)
	{
		arr[i] = i+1;
	}
	//指针间接赋值
	*temp = arr;
}
void printArray(int *array,int len)
{
	for(int i = 0;i < len;++i)
	{
		printf("%d ",array[i]);
	}
}
void test()
{
	int *pArray = NULL;
	allocateSpace(pArray);
	printArray(&pArray,10);//1 2 3 4 5 6 7 8 9 10
}
/**
	二级指针做形参输入特性:由主调函数分配内存
**/
void printArray(int **arr,int len)
{
	for(int i = 0;i < len;++i)
	{
		printf("%d ",*arr[i]);
	}
}
/**
	在堆上开辟指针数组
	在栈上开辟指针内存
**/
void test()
{
	//堆上分配指针数组
	int **pArraay = malloc(sizeof(int *)*6);
	
	//栈上分配数据空间
	int a1 = 100;
	int a2 = 200;
	int a3 = 300;
	int a4 = 400;
	int a5 = 500;
	int a6 = 600;
#if 0
	pArray[0] = &a1;
	pArray[1] = &a2;
	pArray[2] = &a3;
	pArray[3] = &a4;
	pArray[4] = &a5;
	pArray[5] = &a6;
#end if
	*(pArray + 0) = &a1;
	*(pArray + 1) = &a2;
	*(pArray + 2) = &a3;
	*(pArray + 3) = &a4;
	*(pArray + 4) = &a5;
	*(pArray + 5) = &a6;

	printArray(pArray,6);//100 200 300 400 500 600
}

/**
	在栈上开辟指针数组
	在堆上开辟指针内存
**/
void test01()
{
	int *pArray[5];
	for(int i = 0;i < 5;++i)
	{
		pArray[i] = maloc(4);
		*(pArray[i]) = 100+i;
	}
	printfArray(pArray,5);//100 101 102 103 104
	//释放堆内存
	for(int i = 0;i < 5;++i)
	{
		if(pArray[i] != NULL)
		{
			free(pArray[i]);
			pArray[i] = NULL;
		}
	}
}

二级指针文件读写
读取文件数据,将文件内数据每一行读取出来,然后在按照行为单位存储文件数据

//获得文件行数
void getFileLines(FILE *file)
{
	if(NULL == file) return -1;
	
	char buf[1024] = {0};
	int lines = 0;//文件行数
	while(fgets(file, 1024,file) !=NULL)
	{
		++lines;
	}
	//恢复文件指针,使文件指针从文件末尾指到文件起始位置
	fseek(file,0,SEEK_SET);
	
	return lines;
}
//读取文件数据
void readFileData(FILE *file,int lines,char **contents)
{
	if(NULL == file)
	{
		return ;
	}	
	if(NULL == contents) return ;

	if(lines <= 0) return ;

	//创建缓冲区
	char buf[1024] = {0};
	int index = 0;
	while(fgets(buf,1024,file) != NULL)
	{
		//计算当前行字符串长度
		int curLineLen = strlen(buf) + 1;
		//给当前行分配内存
		char *lineContent = malloc(sizeof(char)* curLineLen);
		//将行数据拷贝到空间中
		strcpy(lineContent, buf);

		contents[index++] = lineContent;
		memset(buf,0,1024);
	}
}

void showFileContents(char **contents,int lines)
{
	for(int i = 0;i < lines;++i)
	{
		printf("%d行:%s",i+1,contents[i]);
	}
}
//释放文件数据内存
void freeFileSpace(char **contents,int lines)
{
	for(int i = 0;i < lines;++i)
	{
		if(contents[i] != NULL)
		{
			free(contents[i]);
			contents[i] = NULL;
		}
	}
	free(contents);
	contents = NULL;
}

void test()
{
	//打开文件
	FILE *file = fopen("./text.txt","r");
	if(NULL == file)
	{
		printf("文件打开失败\n");
		return ;
	}
	//统计文件行数
	int lines = getFileLines(file);
	//堆上开辟空间存储每行数据
	char **pContents = malloc(sizeof(char *)*lines);
	//读取文件内容
	readFileDate(file,line,pContents);
	//关闭文件
	fclose(file);
	file = NULL;
	//打印文件内容
	showFileContents(pContents, lines)
	//释放文件数据内存
	freeFileSpace(pContents,lines)
}

位运算
位运算一般不能对浮点数进行计算,一般对char、short、int、long类型进行使用。

/**
	按位取反 ~
**/
void test()
{
	int number = 2;//010 
	printf("~number : %d\n",~number);// -3
	/**
		~010 -> 101
		负数使用补码存储,101是负数因此要将其转换成补码,得保证符号位不变,其余位置取反,末尾加一
		最终结果111,第一位1是负号,因此结果是-3
		
	**/
}
/**
	按位与 &  将指定位置置成0
	10011&00010 -> 00010
**/
void test()
{
	int number = 335;
	if(number & 1 == 0) printf("%d是偶数",number);
	else printf("%d是奇数",number);
	//number清零操作
	number = number&0;
}
/**
	按位或 |  可以将指定位置置成1
	1101 | 0011 -> 1111
**/
void test()
{
	int number1 = 5,number2 = 3;
	printf("number1 | number2 = %d\n",number1 | number2);//7
}
/**
	位异或 ^
	A:10101110 ^ B:11011100 --> R:01110010
	A ^ B = R;
	R ^ B = A;
	R ^ A = B;
	A ^ B ^ B = A;
**/
void test()
{
	int num1 = 5,num2 = 9;
#if 0
	int temp = num1;
	num1 = num2;
	num2 = temp;
#endif
	num1 = num1 ^ num2;
	num2 = num1 ^ num2;
	num1 = num1 ^ num2; 
	printf("num1:%d num2:%d\n",num1,num2);//num1:9 num2:5 
}

移位运算符
001 << 1 = 2
010 << 1 = 4
100 << 1 = 8

/**
	左移运算符 << 
	左移几位相当于乘以2的几次方
	将其左侧操作数的值的每一位向左移动,移动的位数由其右侧操作数指定,
	空出来的位用0填充,斌且丢弃一处左侧操作数末端的数
**/
void test()
{
	int number = 20;
	printf("number = %d\n",number << 2);//number = 80
}
/**	
	右移几位相当于除以2的几次方
	右移运算符 >> 将其左侧的操作数的值的每位向右移动
	移动的位数由其右侧的操作数指定
	丢弃移除左侧操作数右端的位
	对于unsigned类型,使用0填充左端空出的位
	对于有符号类型,结果依赖于机器
	空出的位可能用0填充,或者使用符号(最左端)位的副本填充
**/
//有符号值
(10001010) >> 2
(00100010) //在某些系统上的结果值

(10001010) >> 2
(11100010) //在另一些系统上的结果

//无符号值
(10001010) >> 2
(00100010) //所有系统上的结果

一维数组

/**
	数组的两种情况下不是指向数组首元素地址的指针,  数组名是数组类型
	1.sizeof
	2.对数组名取地址&arr
	除了以上两点之外,数组名在其他任何情况下都是指向首元素的指针
	数组名是一个常量指针
**/
void test()
{
	int arr[] = {1,2,3,4};
	
	printf("sizeof:%d\n",sizeof arr);//sizeof:16

	printf("&arr addr:%d\n",&arr+1);//&arr addr:7208104
	printf("&arr + 1 addr:%d\n",&arr+1);//&arr + 1 addr:7208120
}
/**
	定义一个指向数组的指针
**/
void test()
{
	//1.先定义数组类型,再定义数组指针类型
	int arr[5] = {1,2,3,4,5};
	
	typedef int (ARRAY_TYPE)[5];
	ARRAY_TYPE myarray;//int myarray[5];
	memset(myaray,5,10);
	//对数组名取地址代表指向整个数组的指针
	ARRAY_TYPE *pArray = &myarray;
	pArray = &arr;
	/**
		1. *pArray 表示拿到pArray指针指向的整个数组
		2. *pArray类型就是数组名,指向首元素类型的指针
	**/


	//2.直接定义数组指针类型
	typedef int(*ARRAY_POINT)[5];
	ARRAY_POINT pArr = &arr;


	//3.直接定义数组指针变量
	int(*pArrParam)[5] = &arr;
}

多维数组
一维数组名是一个指针常量,它的类型是“指向元素类型的指针”,他指向数组的第一个元素,多维数组也是同理,多维数组的数组名也是指向第一个元素,只不过第一个元素是一个数组

/**
	
**/
void test()
{
	int arr[3][3] = 
	{
		{1,2,3},
		{4,5,6},
		{7,8,9}
	}
#if 0
	int arr[3][3] = {1,2,3,4,5,6,7,8,9};
	int arr[][3] = {1,2,3,4,5,6,7,8,9};
#endif

	/**
		对于二维数组同一维数组一样,除了sizeof对数组名求地址之外,数组名就是指向数组首元素的指针
	**/
	printf("%s\n",typeid(arr).name());//int [3][3]
}

指针数组排序—选择排序
使用双重for循环,内循环找到每次最小的值,找到之后和第一位相交换

void selectSort(int *arr,int len){
	for(int i = 0;i < len;++i){
		int min = i;
		for(int j = i;j < len;++j){
			if(arr[min] > arr[j]) min = j;
		}
		if(min != i) 
		{
			int temp = arr[min];
			arr[min] = arr[i];
			arr[i] = temp;
		}
	}
}

结构体赋值

//栈内存
struct Person
{
	char name[64];
	int age;
};
void test()
{
	/**
		等号赋值拷贝是数据复制拷贝
		就是将person1的name、age数据拷贝到person2的name、age
	**/
	struct Person person1 = {"aaa",12};
	struct Person person2 = {"bbb",30}; 
	person2 = person1;
}
//堆内存
struct Teacher
{
	char name[64];
	int age;
};
void test()
{
	struct Teacher teacher1;
	teacher1.name = malloc(sizeof(char)*64);
	memset(teacher1.name,0,64);
	strcpy(teacher1.name,"aaa");
	teacher1.age = 20;
	
	struct Teacher teacher2;
	teacher2.name = malloc(sizeof(char)*128);
	memset(teacher2.name,0,128);
	strcpy(teacher2.name,"bbbbbbb");
	teacher2.age = 30;

	//teacher1和teacher2大小是一样的
#if 0
	teacher1 = teacher2;//报错
	/**
		如果再结构体内部右指针,并且指针指向堆空间
		那么如果发生赋值行为,就会产生两个问题:
		1.同一块空间被释放两次
		2.内存泄漏
		因为再进行复制的时候被赋值的结构体原本指向自己堆内存空间的指针
		就会被覆盖指向赋值结构体的堆内存空间
		此时就会造成没有指针指向原本被赋值结构体的堆内存空间
	**/
#endif
	//如果结构体内部有指针指向堆内存
	//那么就不能使用编译器默认的赋值行为
	//应该手动控制赋值过程
	if(teacher1.name != NULL)
	{
		free(teacher1.name);
		teacher1.name = NULL;
	}
	teacher1.name = malloc(strlen(teacher2.name) + 1);
	strcpy(teacher1.name,teacher2.name);
	teacher1.age = teacher2.age;
}

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

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

相关文章

第二证券:融券余额,较历史高位下降逾九成!

在多种要素归纳影响下&#xff0c;近年融券余额和转融券余额持续下降&#xff0c;其间融券余额已较前史高位下降逾九成&#xff0c;而转融券余额年内降幅也已逾越九成。 有专家在接受证券时报记者采访时认为&#xff0c;融券和转融券余额大幅减少减轻了商场兜销压力&#xff0…

OV SSL证书:让您的网站与众不同

在当今高度竞争的数字世界中&#xff0c;拥有一个安全、可信的网站对于吸引和保留客户至关重要。组织验证&#xff08;OV&#xff09;SSL证书不仅可以为网站提供强大的加密保护&#xff0c;还能通过验证组织的真实身份来增强用户的信任感。本文将探讨OV SSL证书如何帮助您的网站…

背包问题有前提

前言&#xff1a;这个有大前提的背包感觉不能用二进制拆分&#xff0c;不然搞不清楚 注意三维的顺便&#xff0c;第一维度是枚举物品&#xff0c;第二维度是倒序枚举空间&#xff0c;第三维度是枚举数量 题目地址 #include<bits/stdc.h> using namespace std;#define …

XSS-Jquery.html()+DOM破坏

目录 靶场网址&#xff1a;​ https://xss.pwnfunction.com/challenges/ww3/ ​ 分析代码&#xff1a; Jquery.html()解析原理&#xff1a; DOM-clobbering JS作用域&作用域链 ​编辑 靶场网址&#xff1a;​ https://xss.pwnfunction.com/challenges/ww3/ ​ 分析代…

全液冷服务器革命:CPU、内存、PCIe高效散热新方案

在国家十四五规划大力发展数字经济的背景下&#xff0c;数据中心作为算力的核心载体&#xff0c;其基础设施成为支撑数字经济的“数字底座”&#xff0c;但同时也面临巨大的碳排放压力。随着芯片与服务器功耗的上升&#xff0c;单机柜功率密度不断增大&#xff0c;传统风冷散热…

RF自动化环境安装+自动化实例解析

RF定义&#xff1a; 通用型的 自动测试框架&#xff0c; 绝大部分的软件的的自动化系统都可以采用它。 特点&#xff1a; 测试数据文件&#xff08;Test Data&#xff09;对应一个个的测试用例。测试数据文件里面使用的功能小模块叫关键字&#xff0c;由测试库&#xff08;T…

【生日视频制作】教师节中秋节国庆节红色直升飞机AE模板修改文字软件生成器教程特效素材【AE模板】

红色直升飞机生日视频制作教程AE模板改文字广软件告生成器素材 怎么如何做的【生日视频制作】教师节中秋节国庆节红色直升飞机AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频…

字节跳远,AI绘梦:我的自由之旅,从编码到画布的奇幻转变

一、告别字节&#xff0c;开启未知旅程 在字节跳动的那些日子里&#xff0c;我经历了职场的起伏&#xff0c;也见证了公司的飞速发展。然而&#xff0c;高强度的工作节奏和不断攀升的业绩压力&#xff0c;让我开始思考生活的意义。最终&#xff0c;我做出了一个大胆的决定——裸…

Leetcode面试经典150题-300.最长递增子序列

解法都在代码里&#xff0c;不懂就留言或者私信 面试的话普通的动态规划解法就够了&#xff0c;如果要出彩&#xff0c;看看我提交的最终的解 class Solution {/**解题思路分析&#xff1a;这个题的普通解法是标准的动态规划对于每一个位置的值&#xff0c;看看前面所有的比它…

[数据集][目标检测]流水线物件检测数据集VOC+YOLO格式9255张26类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;9255 标注数量(xml文件个数)&#xff1a;9255 标注数量(txt文件个数)&#xff1a;9255 标注…

分析Facebook在区块链技术中的应用与前景

随着数字技术的飞速发展&#xff0c;区块链作为一种具有去中心化、安全性高、透明度强等特点的技术&#xff0c;逐渐引起了各大科技公司的关注。Facebook&#xff08;现Meta&#xff09;也不例外&#xff0c;其在区块链技术上的探索不仅显示了对未来技术趋势的敏锐洞察&#xf…

周易测算系统开发:融合古典智慧与现代技术的创新实践

一、引言 周易&#xff0c;作为中国古代文化的瑰宝&#xff0c;蕴含着深邃的哲学思想与预测智慧&#xff0c;其独特的六十四卦体系及爻变原理&#xff0c;自古以来便被人们用于探索自然规律、人生哲理及未来趋势。随着科技的飞速发展&#xff0c;将周易智慧与现代计算机技术相结…

虚幻5|AI行为树,跟随task(非行为树AI)

这个可以不需要行为树 1.打开ai的角色蓝图后&#xff0c;添加一个函数&#xff0c;命名为跟距离改变速度 并用tick调用 2.编辑函数

python实现自动化生成pdf报告

easypdf使用手册 1. 项目介绍1.1 关于1.2 easypdf 有什么优势1.2 easypdf 可以用来做什么1.3 项目框架1.4 项目教程视频 2. 安装项目环境2.1 安装Python32.2在Windows上安装Python32.3 在Mac上安装Python32.4 在Linux上安装Python32.5 在Windows上安装Pycharm2.6 在Mac上安装Py…

Funsound语音识别技术之 基于paraformer的自定义命令(唤醒)词识别

免费语音识别转写&#xff08;优于讯飞&#xff09;&#xff1a;www.funsound.cn 前言 Paraformer在声学后验上通过greedy search得到语音识别结果&#xff0c;对于自定义命令&#xff08;唤醒&#xff09;词识别&#xff0c;肯定还得走asr模型。对此我们可以在paraformer上为…

基于Java爬取微博数据(五) 补充微博正文列表图片 or 视频 内容

基于Java爬取微博数据五 补充微博正文列表图片 or 视频 内容 数据分析补充图片 or 视频执行结果 在通过对微博正文内容中的图片 or 视频内容进行分析后&#xff0c;图片 or 视频 链接是可以直接通过 Java 代码下载或者转存的&#xff0c;那么这样就可以补充我们在 【基于Java爬…

差旅费太高是什么原因?BI大神带你一起实操财务数据分析!

在数字经济的大潮中&#xff0c;数据已不仅仅是冰冷的数字&#xff0c;而是企业决策的活水源头。对财务来说&#xff0c;每一笔账目&#xff0c;每一次报销&#xff0c;都可能是企业健康的晴雨表。而随着数字化时代的到来&#xff0c;BI分析在财务数据管理中发挥着越来越重要的…

一、Socket介绍(也叫套接字)

一、定义 通过IP地址或者端口 将两个电脑连接起来&#xff1b; Socket是网络通信最常用的&#xff0c;除了这个还有HTTP&#xff1b; Http是一个弱联网&#xff1b;Socket用于长连接&#xff0c;使用的是Tcp&#xff1b; 除了这个还有一个SuperSocket&#xff0c;是对Socket…

初识spring security (一),一文弄懂默认配置

一、简单导入依赖 1、导入pom <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version></parent><modelVersion>4.0.0</modelVersion&g…

伺服电机抖动的解决方案

一、电机运行过程中抖动 1.原因分析 ①增益参数设置不当&#xff1a;增益参数不合适导致系统过于敏感&#xff0c;出现振荡&#xff1b; ②机械共振&#xff1a;机械系统的固有频率与电机运行频率接近&#xff0c;导致共振&#xff1b; ③反馈信号噪声&#xff1a;反馈装置…