【C语言期末项目-通讯录】-升级可动态申请内存版(手把手详细过程,期末评分A+的项目,答辩辅助神博文,建议三连点赞收藏)

news2025/1/21 5:47:18

目录

​编辑

前言:

 1.项目功能需求分析 

2.文件框架说明 

3.程序主框架实现 

4.创建联系人结构体类型和通讯录结构体类型 

4.1创建通讯录 

5.程序功能实现--封装功能函数实现不同功能 

5.1通讯录初始化

 5.2增加联系人 

 5.3显示所有联系人的信息

5.4删除指定联系人的信息 

5.5查找指定联系人 

 5.6修改联系人的信息

 6.释放通讯录

7.测试通讯录动态增长 

6.结语及源码


前言:

对于这个项目,是前面数组基础版本的通讯录的升级版本,大家如果一步理解有困难,一定先点击我的主页了解一下前几篇博客的内容做一个铺垫,我这里罗列一下关联最大的三篇:

①动态内存详解

②通讯录基础数组版本

③C语言结构体详解

 1.项目功能需求分析 

实现一个通讯录:
通讯录保存个人信息

 名字,年龄 性别 电话 住址    用保存人的信息的结构体实现

1.通讯录空间不固定,可以先存放一部分的信息,当用户还要存入信息的时候可以自动增加容量。

(比如默认先存放3个联系人的信息,不够了,就每次增加两个联系人信息的空间给用户)
 2.添加联系人
3.删除指定联系人
4.查找指定联系人
5.显示所有人的信息
6.排序功能

7.可以修改指定联系人的信息

2.文件框架说明 

test.c 主菜单文件,用于功能测试

contact.c 函数具体实现文件

contact.h 存放函数和类型的声明和必要头文件

3.程序主框架实现 

我们希望在程序中实现不同的操作,比如上述的增删查改联系人的信息,而不是执行一次程序就结束,用户可以选择退出。接下来我们就实现一下主体框架,包含主页面菜单显示。

void menu()
{
	printf("----------------------------------\n");
	printf("|***0.Exit       1.ADD***********|\n");
	printf("|***2.DEL       3.SEARCH*********|\n");
	printf("|***4.MODIFY    5.SHOW***********|\n");
	printf("|***6.SORT       ****************|\n");
	printf("----------------------------------\n");
	 
}
void test()
{
	int  input = 0;
	
	
	do
	{
		menu();
		printf("请选择:》");
		scanf("%d", &input);
		switch (input)
		{
			
		case 1:
			
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
			break;
		case 0:
			printf("退出程序成功\n");
			break;
		default:
			printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");
			break;


		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

case后面的选项是1,2,3,4,5,那么我们想可不可以利用枚举,让case后面的选项既能表示我们的功能含义又能表示功能选择数字,这样的代码可读性就会更高一些,我们就可以修改如下 :

首先定义选择枚举类型:

enum OPtion
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,
	MODIFY,
	SHOW,
	SORT

};

这个依然是放在我们的头文件中去定义,这样代码的整体美观些,接下来的结构修改为:

void menu()
{
	printf("----------------------------------\n");
	printf("|***0.Exit       1.ADD***********|\n");
	printf("|***2.DEL       3.SEARCH*********|\n");
	printf("|***4.MODIFY    5.SHOW***********|\n");
	printf("|***6.SORT       ****************|\n");
	printf("----------------------------------\n");
	 
}
void test()
{
	int  input = 0;
	Contact con;
	InitContact(&con);
	
	do
	{
		menu();
		printf("请选择:》");
		scanf("%d", &input);
		switch (input)
		{
			
		case ADD:
			
			break;
		case DEL:
			break;
		case SEARCH:
			break;
		case MODIFY:
			break;
		case SHOW:
			break;
		case SORT:
			break;
		case EXIT:
			printf("退出程序成功\n");
			break;
		default:
			printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");
			break;


		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

4.创建联系人结构体类型和通讯录结构体类型 

由于通讯录存储的是每一个联系人的基本信息,名字、电话、性别、住址等,所以我们可以封装一个联系人结构体类型用于描述每一个联系人。

typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char telepnumber[12];
	char addr[30];

} PeoInfo;

为了后续书写的方便将struct PeoInfo类型重定义为PeoInfo

我们现在需要一块空间来存储我们联系人的信息,这块空间的起始地址交给我们的一个联系人结构体类型的指针。

PeoInfo* data;//指向了存放数据的空间

由于,我们后续会对通讯录进行增删操作,就会改变数组的大小,为了方便查看或者显示或者为了方便操作我们可以定义一个SZ来记录数组的大小,增加一个联系人,sz+1.......

int sz;//记录的是当前有效元素的个数

这,当我们起始有三个联系人类型那么大的空间的时候,还没有存入联系人的信息,此时我们的sz=0,那么我们什么时候开始扩大我们的空间呢,所以我们专门设计一个变量来记录我们通讯录的数据空间容量,起始容量为3,当sz 等于我们的容量的时候,就可以扩容了。

int  capacity;//记录当前存放数据空间的容量

数据区,容量和联系人数目都是通讯录的属性,我们可以设计一下通讯录类型结构体:

typedef struct Contact
{
	PeoInfo* data;//指向了存放数据的空间
	int sz;//记录的是当前有效元素的个数
	int  capacity;//记录当前存放数据空间的容量

	
}Contact;

为了以后书写方便,用typedef重定义通讯录结构体类型为:Contact类型。

4.1创建通讯录 

当我们的通讯录类型有了过后,我们就可以创建一个通讯录:

5.程序功能实现--封装功能函数实现不同功能 

5.1通讯录初始化

初始化函数,首先要为我们的data数据区申请3个PeoINfo类型的空间,将sz也初始化为0.将容量初始化3,起始的容量不一定设置为3,方便不同的伙伴来设置,我们将容量的大小也设置为宏.我们传参使用了结构体地址传参,接收参数使用了结构体指针,内存占用少。

void Initcontact(Contact* pc)
{
	assert(pc);
		pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));
		if (pc->data == NULL)
		{
			perror("Initcontact");
		}
	pc->sz = 0;
	pc->capacity = CAPICITY;
}

 5.2增加联系人 

在动态版本中,我们不用考虑通讯录满没满。而是应该考虑通讯录申请的空间是否够了,不够就要扩容,每录入一个联系的信息,sz就+1,当我们的sz与我们的容量相等的时候,就要考虑扩容,所以我们进入增加函数第一步就应该先判断是否要增容。

为了代码方便,我们将检查是否要增容这一步封装为一个函数:

int ChekCapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
	PeoInfo* ptr =(PeoInfo * )realloc(pc->data, (pc->capacity + 2 * sizeof(PeoInfo)));
	if (ptr == NULL)
	{
		perror("ChekCapaticy");
		return  0;

	}
	else
	{
		pc->data = ptr;
		pc->capacity += 2;
	}
	
	}
	return 1;
}

函数返回1,说明增容成功,函数返回0说明增容失败。当然,也不一定每次只增加两个空间,我们还是将增加的空间数目定义为宏,方便伙伴们修改:

#define ADDC 2
void Initcontact(Contact* pc)
{
	assert(pc);
		pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));
		if (pc->data == NULL)
		{
			perror("Initcontact");
		}
	pc->sz = 0;
	pc->capacity = CAPICITY;
}
int ChekCapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
	PeoInfo* ptr =(PeoInfo * )realloc(pc->data, (pc->capacity + ADDC * sizeof(PeoInfo)));
	if (ptr == NULL)
	{
		perror("ChekCapaticy");
		return  0;

	}
	else
	{
		pc->data = ptr;
		pc->capacity += ADDC;
         printf("增容成功\n");
return1;
	}
	
	}
	return 1;
}

我们的增加联系人的函数为:

void AddContact(Contact* pc)
{
	assert(pc);//断言防止传入空指针
	//首先判断通讯录满每满
	if (0 == ChekCapacity(pc))
	{
		return;
	}
	printf("请输入联系人的名字>\n");
	scanf("%s", pc->data[pc->sz].name);//由于name是数组名这里就不要&符号了
	printf("请输入联系人的年龄>\n");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入联系人的性别>\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入联系人的电话>\n");
	scanf("%s", pc->data[pc->sz].telepnumber);
	printf("请输入联系人的地址>\n");
	scanf("%s", pc->data[pc->sz].addr); 

		//添加联系人成功,我们sz++
		pc->sz++;
	printf("添加联系人成功\n");

}

 

 5.3显示所有联系人的信息

为了看一下我们添加联系人或者删除联系人的效果,我们这里就先写显示函数

用于我们只是显示通讯录信息,并不将参数内容进行修改所以参数最好使用const进行修饰,防止出错,这一步不理解的伙伴可以点击我的主页看一下我讲解const的博文。

这个函数我们只用循环打印我们data数组内容就行

void ShowContact(const Contact* pc)
{
	assert(pc);//断言一下防止传入空指针
	int i = 0;
	printf("————————————————————————————————————————————————————————————————————————————————————————\n");
	printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < pc->sz; i++)
		{
			printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n", 
				pc->data[i].name,
				pc->data[i].age,
				pc->data[i].sex,
				pc->data[i].telepnumber,
				pc->data[i].addr);
			printf("————————————————————————————————————————————————————————————————————————————————————————\n");
		}
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");

我们来看一下前两个函数执行的效果:

5.4删除指定联系人的信息 

首先,如果通讯录为空,我们就没有删除的东西

第二,要删除对应联系人的信息,实现思想是先找到对应联系人的名字匹配相同将后面的内容前移覆盖完成删除。

void DelCotact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[DATAMAX] = { 0 };
	assert(pc);//断言,防止传入空指针
	printf("请输入要删除的人的名字:》\n");
	scanf("%s", name);
	//遍历找到要删除的人
	int i = 0;
	int del = 0;
	int flag = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			del = i;
			flag = 1;
			break;
		}
		
	}
	if (flag == 0)
	{
		printf("找不到要删除的人,请检查名字是否输入正确\n");
		return;
	}
	//找到了,删除联系人
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("成功删除联系人\n");
}

由于我们后面修改呀等等都会用到查找这个函数,所以我们将其封装为一个查找函数,那我们就可以改造代码如下:

int Findbyname(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}

	}
	return -1;//找不到
}
void DelCotact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[DATAMAX] = { 0 };
	assert(pc);//断言,防止传入空指针
	printf("请输入要删除的人的名字:》\n");
	scanf("%s", name);
	//遍历找到要删除的人
	int i = 0;
	int del = 0;
	del = Findbyname(pc, name);
	if (del == -1)
	{
		printf("找不到要删除的人,请检查名字是否输入正确\n");
		return;
	}
	//找到了,删除联系人
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("成功删除联系人\n");
}

我们来看一下效果:

5.5查找指定联系人 

这里我们就实现一下通过名字查找,之所以单独写一个查找函数是因为在功能中,查找到过后还要显示出来。

看实现:

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[DATAMAX] = { 0 };
	printf("请输入要查找的人的名字:》\n");
	scanf("%s", name);
	int pos = Findbyname(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在,请检查名字是否输入正确\n");

	}
	else
	{
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");
		printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");
		printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].telepnumber,
			pc->data[pos].addr);
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");

	}
}

这里查找也可以根据其他的比如号码等,可以利用Switch来实现。看一下效果:

 5.6修改联系人的信息

通过名字来找到要修改信息的联系人,然后重新录入信息

void 	ModifyContact(Contact* pc)
{
	assert(pc);
	char name[DATAMAX] = { 0 };
	printf("请输入要修改人的名字:>\n");
	scanf("%s", name);
	int pos = Findbyname(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在,请检查名字是否输入正确\n");

	}
	else
	{
		printf("请输入要修改人的名字>\n");
		scanf("%s", pc->data[pos].name);//由于name是数组名这里就不要&符号了
		printf("请输入要修改人的年龄>\n");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入要修改人的性别>\n");
		scanf("%s", pc->data[pos].sex);
		printf("请输入要修改人的电话>\n");
		scanf("%s", pc->data[pos].telepnumber);
		printf("请输入要修改人的地址>\n");
		scanf("%s", pc->data[pos].addr); \

			
		printf("修改成功\n");

	}
}

我们看一下效果:

 6.释放通讯录

由于我们的通讯录空间是malloc来的,所以在最后程序结束应该将空间释放,防止造成内存泄漏。

那我们就在退出选项后面增加一个销毁函数:

void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

7.测试通讯录动态增长 

先往通讯录里面放入三个联系人信息:

下一步增容:

增容成功,我们展现一下通讯录然后我们查找一下2号联系人:

功能正常。到这里我们的动态版本就修改完成了。

6.结语及源码

以上就是本期的所有内容,大家可以配合解释和原码运行理解。创作不易,大家如果觉得还可以的话,欢迎大家三连,有问题的地方欢迎大家指正,一起交流学习,一起成长,我是Nicn,正在c++方向前行的奋斗者,感谢大家的关注与喜欢。下面附上整个项目源码。后续会陆续更新升级版,大家敬请期待。

test.c

#include"contact.h"

//通讯录空间不固定,大小1可以调整
// 默认放3个人的信息,不够,每次增加两个


void menu()
{
	printf("----------------------------------\n");
	printf("|***0.Exit       1.ADD***********|\n");
	printf("|***2.DEL       3.SEARCH*********|\n");
	printf("|***4.MODIFY    5.SHOW***********|\n");
	printf("|***6.SORT       ****************|\n");
	printf("----------------------------------\n");

}
void test()
{
	int  input = 0;
	Contact con;
	Initcontact(&con);

	do
	{
		menu();
		printf("请选择:》");
		scanf("%d", &input);
		switch (input)
		{

		case ADD:
			AddContact(&con);

			break;
		case DEL:
			DelCotact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
		
			break;
		case EXIT:
			DestoryContact(&con);
			printf("退出程序成功\n");
			break;
		default:
			printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");
			break;


		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

contact.h

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


#define DATAMAX 100
#define CAPICITY 3
#define ADDC 2


enum OPtion
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,
	MODIFY,
	SHOW,
	SORT

};

//类型的声明
typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char telepnumber[12];
	char addr[30];

} PeoInfo;


//typedef struct Contact
//{
//	PeoInfo data[DATAMAX];
//	int sz;
//}Contact;
typedef struct Contact
{
	PeoInfo* data;//指向了存放数据的空间
	int sz;//记录的是当前有效元素的个数
	int  capacity;//记录当前存放数据空间的容量


}Contact;

//初始化函数
void Initcontact(Contact* pc);//函数声明
void AddContact(Contact* pc);//增加联系人函数
void ShowContact(const Contact* pc);//显示通讯录信息
void DelCotact(Contact* pc);//删除联系人信息
void SearchContact(Contact* pc);//查找联系人的信息
void 	ModifyContact(Contact* pc);//修改联系人的信息
void DestoryContact(Contact* pc);//销毁通讯录

contact.c

#include"contact.h"
int Findbyname(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}

	}
	return -1;//找不到
}
void Initcontact(Contact* pc)
{
	assert(pc);
		pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));
		if (pc->data == NULL)
		{
			perror("Initcontact");
		}
	pc->sz = 0;
	pc->capacity = CAPICITY;
}
int ChekCapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
	   PeoInfo* ptr =(PeoInfo * )realloc(pc->data, (pc->capacity + ADDC * sizeof(PeoInfo)));
	   if (ptr == NULL)
	   {
		perror("ChekCapaticy");
		return  0;

	    }
	   else
	   {
	   	pc->data = ptr;
		pc->capacity += ADDC;
		printf("增容成功\n");
		return 1;
	    }
	
	}
	return 1;
}

void AddContact(Contact* pc)
{
	assert(pc);//断言防止传入空指针
	//首先判断通讯录满每满
	if (0 == ChekCapacity(pc))
	{
		return;
	}
	printf("请输入联系人的名字>\n");
	scanf("%s", pc->data[pc->sz].name);//由于name是数组名这里就不要&符号了
	printf("请输入联系人的年龄>\n");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入联系人的性别>\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入联系人的电话>\n");
	scanf("%s", pc->data[pc->sz].telepnumber);
	printf("请输入联系人的地址>\n");
	scanf("%s", pc->data[pc->sz].addr); 

		//添加联系人成功,我们sz++
		pc->sz++;
	printf("添加联系人成功\n");

}
void ShowContact(const Contact* pc)
{
	assert(pc);//断言一下防止传入空指针
	int i = 0;
	printf("————————————————————————————————————————————————————————————————————————————————————————\n");
	printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");
	printf("————————————————————————————————————————————————————————————————————————————————————————\n");
	for (i = 0; i < pc->sz; i++)
	{
		printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].telepnumber,
			pc->data[i].addr);
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");
	}
	printf("————————————————————————————————————————————————————————————————————————————————————————\n");

}

void DelCotact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[DATAMAX] = { 0 };
	assert(pc);//断言,防止传入空指针
	printf("请输入要删除的人的名字:》\n");
	scanf("%s", name);
	//遍历找到要删除的人
	int i = 0;
	int del = 0;
	del = Findbyname(pc, name);
	if (del == -1)
	{
		printf("找不到要删除的人,请检查名字是否输入正确\n");
		return;
	}
	//找到了,删除联系人
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("成功删除联系人\n");
}

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[DATAMAX] = { 0 };
	printf("请输入要查找的人的名字:》\n");
	scanf("%s", name);
	int pos = Findbyname(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在,请检查名字是否输入正确\n");

	}
	else
	{
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");
		printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");
		printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].telepnumber,
			pc->data[pos].addr);
		printf("————————————————————————————————————————————————————————————————————————————————————————\n");

	}
}


void 	ModifyContact(Contact* pc)
{
	assert(pc);
	char name[DATAMAX] = { 0 };
	printf("请输入要修改人的名字:>\n");
	scanf("%s", name);
	int pos = Findbyname(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在,请检查名字是否输入正确\n");

	}
	else
	{
		printf("请输入要修改人的名字>\n");
		scanf("%s", pc->data[pos].name);//由于name是数组名这里就不要&符号了
		printf("请输入要修改人的年龄>\n");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入要修改人的性别>\n");
		scanf("%s", pc->data[pos].sex);
		printf("请输入要修改人的电话>\n");
		scanf("%s", pc->data[pos].telepnumber);
		printf("请输入要修改人的地址>\n");
		scanf("%s", pc->data[pos].addr); \


			printf("修改成功\n");

	}
}

void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

 

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

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

相关文章

COMSOL方法编辑器中产生随机数(可控制随机种子)

简介 COMSOL二次开发主要在方法编辑器中进行&#xff0c;编程语言为Java。有时需要产生随机数&#xff08;比如随机生成一些球体&#xff09;&#xff0c;方法编辑器中已经存在Math.random()可直接使用。 但是&#xff0c;对于某些特殊情况&#xff0c;我希望每次运行代码产生…

最新Burp Suite入门讲解

Burp Suite的安装 Burp Suite是一款集成化的渗透测试工具&#xff0c;包含了很多功能&#xff0c;可以帮助我们高效地完成对Web应用程序的渗透测试和安全检测。 Burp Suite由Java语言编写&#xff0c;Java自身的跨平台性使我们能更方便地学习和使用这款软件。不像其他自动化测…

使用python绘制可视化的欧拉公式三维曲线图

欧拉公式应用非常广泛&#xff0c;它在研究交流电、信号分析、量子力学、极坐标切换、求反常积分以及研究任何圆周运动等方面都有着重要的应用&#xff0c;它建立了复数、自然对数、圆周率等重要数学常量之间的关系&#xff0c;描述了复数在极坐标和笛卡尔坐标之间的转换。公式…

本地Tomcat网页搭建结合Cpolar内网穿透实现公网访问

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1.前言2.本地Tomcat网页搭建2.1 Tomcat安装2.2 配置环境…

闲来无事,写几个好看的产品宣传界面,希望您喜欢

闲来无事&#xff0c;再写几个产品宣传页 宣传页面一&#xff1a; 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&…

QT:实现图片选择器

一、效果图 二、用到的类 qApp&#xff1a;可以快速获取到项目目录位置。 QSettings &#xff1a;编写config文件&#xff0c;记录上次打开图片的位置&#xff0c;下次打开图片会从上次的位置查找图片。 QPixmap&#xff1a;用于图片的缩放&#xff0c;防止图片过小&#xff0…

学习Python需要准备什么?BoBo仔为您指点明经~~~

前言 大家好&#xff01;我是bobo仔&#xff0c;欢迎来阅读我的文章。我的这篇文章是专门为Python新手筹备的&#xff0c;大家一定要好好阅读&#xff0c;做好每一步&#xff0c;完成每一节。 【注&#xff1a;部分内容为作者见解、发现&#xff0c;如有版权侵袭或是信息错误…

kali系统概述、nmap扫描应用、john破解密码、抓包概述、以太网帧结构、抓包应用、wireshark应用、nginx安全加固、Linux系统加固

目录 kali nmap扫描 使用john破解密码 抓包 封装与解封装 网络层数据包结构 TCP头部结构​编辑 UDP头部结构 实施抓包 安全加固 nginx安全 防止缓冲区溢出 Linux加固 kali 实际上它就是一个预安装了很多安全工具的Debian Linux [rootmyhost ~]# kali resetkali …

BUUCTF-Real-[Jupyter]notebook-rce

1、简介 Jupyter Notebook&#xff08;此前被称为 IPython notebook&#xff09;是一个交互式笔记本&#xff0c;支持运行 40 多种编程语言。 如果管理员未为Jupyter Notebook配置密码&#xff0c;将导致未授权访问漏洞&#xff0c;游客可在其中创建一个console并执行任意Pytho…

Java中“==”和equals方法的区别

目录 一、“”举例 二、equals举例 区别如下&#xff1a; &#xff08;1&#xff09;“”既可以用在基本数据类型&#xff0c;也可以用在引用数据类型&#xff1b;如果用在基本数据类型上&#xff0c;那么比较时比较的是具体的值&#xff0c;如果用在引用数据类型&#xff0c…

Stable Diffusion 模型下载:majicMIX reverie 麦橘梦幻

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十

线性代数的本质 1 向量

向量是线性代数中最为基础的概念。 何为向量&#xff1f; 从物理上看&#xff0c; 向量就是既有大小又有方向的量&#xff0c;只要这两者一定&#xff0c;就可以在空间中随便移动。 从计算机应用的角度看&#xff0c;向量和列表很接近&#xff0c;可以用来描述某对象的几个不同…

2024-2-6-复习作业

1> 要求&#xff1a; 源代码&#xff1a; #include <stdio.h> #include <stdlib.h> void output(int arr[],int len) {for(int i0;i<len;i){printf("%d ",arr[i]);}puts(""); } void bubble_sort(int arr[],int len) {for(int i1;i<…

upload-labs文件上传漏洞靶场

第一关 <?php eval ($_POST[123]);?>发现他这个是通过客户端前端写了一个限制 我们禁用srcipt即可 蚁剑成功打开 第二关 我们上传文件2.php它提示我们文件类型不正确 我们可以联想到做了后缀检测 我们通过burp抓包修改后缀 第三关 我们上传一个.php文件不可上…

Netty应用(一) 之 NIO概念 基本编程

目录 第一章 概念引入 1.分布式概念引入 第二章 Netty基础 - NIO 1.引言 1.1 什么是Netty&#xff1f; 1.2 为什么要学习Netty&#xff1f; 2.NIO编程 2.1 传统网络通信中开发方式及问题&#xff08;BIO&#xff09; 2.1.1 多线程版网络编程 2.1.2 线程池版的网络编程…

C++异常特性以及使用

异常 1.C传统的处理错误方式2.异常概念3.异常使用规则抛出和匹配规则 4.异常的重新抛出4.异常安全5.异常规范6.使用自定义的异常7.C标准异常体系7.异常优缺点 1.C传统的处理错误方式 终止程序&#xff1a;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&a…

探索Gorm - Golang流行的数据库ORM框架

&#x1f3f7;️个人主页&#xff1a;鼠鼠我捏&#xff0c;要死了捏的主页 &#x1f3f7;️系列专栏&#xff1a;Golang全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

备战蓝桥杯---组合数学2

本专题主要介绍容斥原理。 大家高中的时候肯定接触过韦恩图&#xff0c;容斥原理比较通俗的理解就是减去所有可能并加上重叠的部分。 我们直接看公式&#xff1a; 知道后&#xff0c;我们先看道模板题&#xff1a; 下面是AC代码&#xff1a; #include<bits/stdc.h> us…

C#,奥西里斯数(Osiris Number)的算法与源代码

1 奥西里斯数(Osiris Number) 奥西里斯数(Osiris Number)是一个数字&#xff0c; 其值等于通过将其自身数字的所有排列相加而形成的所有数字的值之和。 计算结果&#xff1a; 2 源程序 using System; namespace Legalsoft.Truffer.Algorithm { /// <summary> /…

【JavaScrpt 漫游】【015】JSON 对象简记

文章简介 本文为【JavaScript 漫游】专栏的第 015 篇文章&#xff0c;主要是对 JS 语言中的 JSON 对象的知识点进行了简要记录。 JSON 格式JSON 对象JSON.stringify()JSON.parse() JSON 格式 JSON 格式&#xff08;JavaScript Object Notation 的缩写&#xff09;是一种用于…