C语言小项目 -- 通讯录完整代码(登陆系统+动态开辟 + 文件操作)

news2024/11/28 12:31:53

目录

📰0. 项目介绍

📰1. 开发环境及框架

📰2. 通讯录账户模块功能分析实现:

📱2.1 通讯录账户菜单界面及数据结构设计

📱2.2 通讯录账户注册功能实现

📱2.3 通讯录账户登录功能实现

📰3. 通讯录模块功能分析实现:

📱3.1 通讯录菜单实现及数据结构设计

📱3.2 通讯录文件加载的实现

📱3.3 通讯录初始化和动态增长的实现

📱3.4 通讯录添加功能的实现

📱3.5 通讯录删除功能的实现

📱3.6 通讯录查找功能的实现

📱3.7 通讯录排序功能的实现

📱3.8 通讯录修改功能的实现

📱3.9 通讯录打印功能的实现

📱3.10 通讯录文件保存及释放空间

📰4. 通讯录完整源代码:

📱4.1 Contacts.h

📱4.2 Contacts.c

📱4.3 ContactsUsers.c

📱4.4 Contacts_Test.c


📰0. 项目介绍

使用C语言设计的一个通讯录管理系统,首先需要账户注册或者账户登录,进入通讯录管理界面,来实现联系人信息的长时间存储(包含姓名、性别、年龄、电话号码等),并且在需要时能够查找出相关联系人的信息。需要包含录入、查找、修改、删除、排序等功能。对通讯录信息存储进行动态内存管理,并以文件格式存取数据。

📰1. 开发环境及框架

本人开发环境采用—VS2022,学会调试,参考文章调试规则,以及windows自带画图板

采取工程内多文件进行链接编译,包括:

  1.  Contacts.h——头文件,所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件。
  2. Contacts.c——源文件,里边含通讯录各种操作函数的具体功能实现
  3. ContactsUsers.c——源文件,包含账户登录注册功能的具体实现
  4. Contacts_Test.c——测试通讯录功能的使用,包含主体运行,主函数等

📰2. 通讯录账户模块功能分析实现:

具体实现功能:

  1. 用户菜单界面的实现
  2. 用户数据结构设计
  3. 用户注册功能的实现(通过文件操作将数据写入文件)
  4. 用户登录功能的实现(通过文件操作将数据从文件读出)

📱2.1 通讯录账户菜单界面及数据结构设计

通过在头文件引用枚举类型,定义枚举常量Option1,实现操作项,增加代码的可维护性;定义结构体类型Users,实现对账号、密码的操作。

账号、密码均采用字符串存储,大小定义为标识符常量,便于进行修改。

void menu1()
{
	printf("------------------------------\n");
	printf("---------- CONTACT -----------\n");
	printf("********  1.Logo In  *********\n");
	printf("******************************\n");
	printf("********  2.Sign In  *********\n");
	printf("******************************\n");
	printf("***********(0.exit)***********\n");
	printf("------------------------------\n");
}
//打印格式
#define RED "\033[0;32;31m"
#define GREEN "\033[0;32;32m"
#define BLUE  "\033[0;32;34m"
#define NONE "\033[m"

#define	NAME_MAX 20
#define PASSWD_MAX 12
enum Option1
{
	EXIT1,
	LOGOIN,
	SIGNIN,
};
typedef struct Users
{
	char UserName[NAME_MAX];
	char UserPasswd[PASSWD_MAX];
}Users;

📱2.2 通讯录账户注册功能实现

文件读取:首先通过只读的方式打开Users.bat二进制文本文件,如果返回NULL,说明文本文件未被创建,便用写的方式进行创建,可以参考文章文件操作

判断账户:进入注册界面,通过两个结构体变量,一个读取用户注册账户名,一个读取文件账户,循环读取文件,并于用户注册账户名进行比较:

        1.使用strcmp,如果输入账户名已经被注册,便return

        2.使用feof( ),如果读取至文件尾,便进行下一步操作

判断密码:通过中间变量进行两次密码确定,且密码位数不得小于五位,如果成功,便将第一个结构体变量通过fwrite写入文件

void UserSign()
{
	Users user1 = { 0,0 },user2 = {0,0};
	FILE* pf,*PF = NULL;
	pf = fopen("Users.bat", "rb");
	if (pf == NULL)
	{
		PF = fopen("Users.bat", "wb");
		fclose(PF);;
	}
	pf = fopen("Users.bat", "rb");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("      Registration interface\n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please set a new user name:>"NONE);
	if (scanf("%s", user1.UserName) == EOF)
	{
		perror("Incorrect input");
	}

	printf(GREEN"       Enter successfully\n"NONE);
	fread(&user2, sizeof(Users), 1, pf);

//【判断】有没有注册过-比较字符串是否相等 
//不相等->是否到文件尾 
	while (1)
	{
		if (strcmp(user1.UserName, user2.UserName) != 0)
		{
			if (feof(pf) == 0)//未到文件尾 
				fread(&user2, sizeof(Users), 1, pf);
			else//到了文件尾仍然没有相同的字符串-说明输入的账号使新的 可以去注册界面 
			{
				printf(GREEN"The account has not been registered. Rejump\n"NONE);
				break;//利用break来跳出无限循环 
			}
		}
		else
		{
			printf(RED"err: The account has been registered!\n"NONE);
			fclose(pf); pf = NULL;
			system("pause");
			return;
		}
	}
	//判断两次密码是否相同,且必须大于5位
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("      Registration interface       \n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please set the user password :(English and digital only):>"NONE);
	if (scanf("%s", user1.UserPasswd) == EOF)
	{
		perror("Incorrect input");
	}
	while (strlen(user1.UserPasswd) < 5)
	{
		printf(RED"err:The password must be at least six characters!"NONE
		BLUE"\nPlease enter the password again:>"NONE);
		if (scanf("%s", user1.UserPasswd) == EOF)
		{
			perror("Incorrect input");
		}
	}
	printf(BLUE"Please enter your password again:>"NONE);
	char tmp[PASSWD_MAX] = { 0 };
	do {
		if (EOF == scanf("%s", tmp))
		{
			perror("Incorrect input");
		}
		if (strcmp(tmp, user1.UserPasswd) != 0)
			printf(RED"\nerr:The two passwords are different.\
				\nPlease enter the password again->"NONE);
		else 
			break;
	} while (1);
	//两次密码一致
	fclose(pf);	
	pf = NULL;
	pf = fopen("Users.bat", "ab");
	if (pf == NULL)
	{
		perror("UserSign failed");
	}
	//fwrite会在当前文件指针的位置写入数据
	//"w" 打开,文件指针指到头,只写;"a" 打开,指向文件尾
	else
	{
		fwrite(&user1, sizeof(Users), 1, pf);
		printf(GREEN"     Registered successfully!\n"NONE);
		system("pause");
		fclose(pf);
		pf = NULL;
	}
	return;
}

📱2.3 通讯录账户登录功能实现

返回类型bool,更方便判断是否登陆成功:

                        1.登陆成功,进入通信录内部系统

                        2.登陆失败,重新登录

文件读取:以只读方式打开文件,同上创建两个结构体变量,如果文件为NULL,说明没有用户注册信息,提示需先注册,返回false。

判断账户:进入登陆界面,输入账户,与文件读取账户进行判断,如没有,提示账号未被注册,返回false;如果找到账户,便进行密码判断。

判断密码:使用户具有三次输入机会,如三次机会均输入错误,便返回false。如果正确,便返回true。

bool UserLogo()
{
	FILE* pf = fopen("Users.bat", "rb");
	Users user1 = { 0,0 }, user2 = { 0,0 };
	if (pf == NULL)
	{
		printf(RED"err:The user directory file does not exist!\n"NONE
		"  Please register the user first\n"NONE);
		system("pause");
		return false;
	}
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("          Login interface\n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please enter the account number:>"NONE);
	if (scanf("%s", user1.UserName) == EOF)
	{
		perror("Incorrect input");
	}
	fread(&user2, sizeof(Users), 1, pf);
	while (1)
	{
		if (strcmp(user1.UserName, user2.UserName) != 0)
		{
			if (feof(pf) == 0)//未到文件尾 
				fread(&user2, sizeof(Users), 1, pf);
			else//到了文件尾仍然没有相同的字符串-说明输入的账号新的 可以去注册界面 
			{
				printf(GREEN"The account has not been registered. Rejump\n"NONE);
				system("pause");
                fclose(pf);
				pf = NULL;
				return false;//利用break来跳出无限循环 
			}
		}
		else
		{
			break;
		}
	}
	printf(BLUE"Please enter password:>"NONE);
	int n = 3;//三次输入机会
	while (n)
	{
		if (scanf("%s", user1.UserPasswd) == EOF)
		{
			perror("Incorrect input");
		}
		if (strcmp(user1.UserPasswd, user2.UserPasswd) != 0)
		{
			if (n == 1)
			{
				printf(RED"	 err:Login failure\n"NONE);
				fclose(pf);
				pf = NULL;
				system("pause");
				return false;
			}
			printf(RED"err:Password error\n"NONE
			BLUE"Please enter the password again:>"NONE);
		}
		else
		{
			break;
		}
		n--;
	}

	printf(GREEN"    Login success!\n"NONE);
	getchar();
	system("pause");
	fclose(pf); 
	pf = NULL;
	return true;
}

📰3. 通讯录模块功能分析实现:

具体实现功能:

  1. 通讯录菜单界面的实现
  2. 通讯录数据结构设计
  3. 通讯录文件加载的实现(通过文件操作将数据从文件读出)
  4. 通讯录的初始化,以及动态增长
  5. 通讯录添加功能的实现(通过文件操作将数据写入文件)
  6. 通讯录删除功能的实现(通过文件操作将数据从文件读出)
  7. 通讯录查找功能的实现(通过文件操作将数据读出,用名字或者手机号进行查找)
  8. 通讯录修改功能的实现(通过文件操作将数据写入文件)
  9. 通讯录排序功能的实现
  10. 通讯录的打印(通过文件操作将数据从文件读出)
  11. 保存通讯录到文件并释放空间(通过文件操作将数据写入文件)

📱3.1 通讯录菜单实现及数据结构设计

通过在头文件引用枚举类型,定义枚举常量Option2,实现操作项,增加代码的可维护性;定义结构体类型PeoInfo描述数据信息,通过结构体Contacts实现线性数据结构

对通讯录的操作进而转换为对顺序表的操作

void menu2()
{
	printf("------------------------------\n");
	printf("---------- CONTACT -----------\n");
	printf("***** 1.add       2.del  *****\n");
	printf("******************************\n");
	printf("***** 3.search  4.modify *****\n");
	printf("******************************\n");
	printf("***** 5.sort    6.print  *****\n");
	printf("**********(0.exit)************\n");
	printf("------------------------------\n");
}
#define	NAME_MAX 20
#define	SEX_MAX 5
#define TELE_MAX 12
#define	ADDR_MAX 30

#define DEFAULT_SZ 4//初始化容量大小
enum Option2
{
	EXIT2,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	char age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contacts
{
	PeoInfo* data;
	int sz;
	int capacity;
}Contacts;

📱3.2 通讯录文件加载的实现

通过文件操作函数,将文件数据读出,加载文件由初始化函数自动调用,因此可以设置为内部链接函数。

static void LoadContact(Contacts* con)
{
	FILE* pf = fopen("contacts.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact::fopen");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		check_capacity(con);
		con->data[con->sz] = tmp;
		con->sz++;
	}
	fclose(pf);
	pf = NULL;
}

📱3.3 通讯录初始化和动态增长的实现

动态开辟空间的优点:

  • 1. 可以动态的申请空间,以便动态确定对象所需要的内存;
  • 2. 便于储存大型对象,通常情况下栈区的大小容不下过于庞大的对象;
  • 3. 传递指针比传递整个对象更方便高效;(当然对于一个变量也可以取地址,但是临时变量的地址是不能长久使用的,特别是返回临时变量的地址是大忌)
  • 4. 同时传递指针可以便于大家共同维护一个空间,指针在传递的过程中,大家都可以修改指针指向的内容,当然要加锁进行保护,这样一处修改,处处修改,否则就要设置全局的变量,大家统一修改使用

参考我的另一篇文章动态内存管理——static使其具有内部链接属性,只能在此文件内部使用

static void check_capacity(Contacts* con)
{
	if (con->sz == con->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(con->data, con->capacity == 0 ? DEFAULT_SZ * sizeof(PeoInfo) : (con->capacity + 2) * sizeof(PeoInfo));

		if (tmp != NULL)
		{
			con->data = tmp;
		}
		else
		{
			perror("check_capacity::realloc");
			return;
		}
		if (con->capacity == 0)
		{
			con->capacity = 4;
		}
		else
		{
			con->capacity += 2;
		}
	}
	return;
}
void InitContact(Contacts* con)
{
	assert(con);
	con->sz = con->capacity = 0;
	con->data = NULL;

	LoadContact(con);
}

📱3.4 通讯录添加功能的实现

通过检查空间大小,直接进行输入

void AddContact(Contacts* con)
{
	check_capacity(con);
	system("cls");
	printf("Add contact information\n");
	printf(BLUE"Please enter your name:>"NONE);
	scanf("%s", con->data[con->sz].name);
	printf(BLUE"Please enter age:>"NONE);
	scanf("%d", &(con->data[con->sz].age));
	printf(BLUE"Please enter gender:>"NONE);
	scanf("%s", con->data[con->sz].sex);
	printf(BLUE"Please enter telephone number:>"NONE);
	scanf("%s", con->data[con->sz].tele);
	printf(BLUE"Please enter the address:>"NONE);
	scanf("%s", con->data[con->sz].addr);
	con->sz++;
	printf(GREEN"  Add successfully\n"NONE);
	system("pause");
}

📱3.5 通讯录删除功能的实现

打印删除菜单——通过名字或者电话号进行删除

可以实现为回调函数,及函数指针传参,通过参数相同,返回值相同,意义相同,便于添加删除方式

static int FindByName(Contacts* con, const char* name)
{
	assert(con && name);
	for (int i = 0; i < con->sz; ++i)
	{
		if (0 == strcmp(con->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}
static int FindByTele(Contacts* con, const char* tele)
{
	assert(con && tele);
	for (int i = 0; i < con->sz; ++i)
	{
		if (0 == strcmp(con->data[i].tele, tele))
		{
			return i;
		}
	}
	return -1;
}
static void deletmenu()
{
	printf("------------------------------\n");
	printf("***** 1. Delete by name  *****\n");
	printf("***** 2. Delete by tele  *****\n");
	printf("***** 0. EXIT DELETE     *****\n");
	printf("------------------------------\n");
}

static void DeleContact(Contacts* con, int (*Find)(Contacts*, const char*))
{
	assert(con);
	char temp[NAME_MAX + TELE_MAX] = { 0 };
	scanf("%s", temp);
	int pos = Find(con, temp);
	if (pos == -1)
	{
		system("cls");
		PrintContact(con);
		printf(RED"err:Nonexistence!!!\n"NONE);
		return;
	}
	void* dest = (void*)(&con->data[pos]);
	void* scr = (void*)(&con->data[pos + 1]);
	int num = sizeof(PeoInfo) * (con->sz - 1 - pos);
	memmove(dest, scr, num);
	con->sz--;
	system("cls");
	PrintContact(con);
	printf(GREEN"   Deleted successfully!\n"NONE);
	system("pause");
}
void DeleContactMenu(Contacts* con)
{
	while (getchar() != '\n');
	assert(con);
	system("cls");
	PrintContact(con);
	if (con->sz == 0)
	{
		printf(RED"err:The contact is empty and cannot be deleted!!!"NONE);
		return;
	}
	char input = 0;
	do
	{
		deletmenu();
		printf(BLUE"Please select:>"NONE);
		scanf("%c", &input);
		switch (input - '0')
		{
		case 1:
			printf(BLUE"Please enter the name of the person you want to delete:>"NONE);
			DeleContact(con, FindByName);
			break;
		case 2:
			printf(BLUE"Please enter the telephone of the person you want to delete:>"NONE);
			DeleContact(con, FindByTele);
			break;
		case 0:
			puts(RED"	Exit successfully\n"RED);
			system("pause");
			return;
		default:
			printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
			system("pause");
			break;
		}
		if (input != '\n')
		{
			while (getchar() != '\n');
		}
	} while (1);
}

📱3.6 通讯录查找功能的实现

打印查找菜单——通过名字或者电话号进行查找

可以实现为回调函数,及函数指针传参,通过参数相同,返回值相同,意义相同,便于添加查找方式

static void searchmenu()
{
	printf("------------------------------\n");
	printf("***** 1. Search by name  *****\n");
	printf("***** 2. Search by tele  *****\n");
	printf("***** 0. EXIT Search     *****\n");
	printf("------------------------------\n");
}
static void SearchContact(Contacts* con, int (*Find)(Contacts*, const char*))
{
	assert(con);
	char temp[NAME_MAX + TELE_MAX] = { 0 };
	scanf("%s", temp);
	int pos = Find(con, temp);
	if (pos == -1)
	{
		system("cls");
		PrintContact(con);
		printf(RED"err:Nonexistence!!!\n"NONE);
		return;
	}
	system("cls");
	printf(GREEN"Sucess:Search successfully!!!\n"NONE);
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
		con->data[pos].name,
		con->data[pos].age, con->data[pos].sex,
		con->data[pos].tele, con->data[pos].addr);
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	system("pause");
	return;
}

void SearhConMenu(Contacts* con)
{
	while (getchar() != '\n');
	assert(con);
	system("cls");
	PrintContact(con);
	if (con->sz == 0)
	{
		printf(RED"err:The contact is empty and cannot be deleted!!!"NONE);
		return;
	}
	char input = 0;
	do
	{
		searchmenu();
		printf(BLUE"Please select:>"NONE);
		scanf("%c", &input);
		switch (input - '0')
		{
		case 1:
			printf(BLUE"Please enter the name of the person you want to search:>"NONE);
			SearchContact(con, FindByName);
			break;
		case 2:
			printf(BLUE"Please enter the telephone of the person you want to search:>"NONE);
			SearchContact(con, FindByTele);
			break;
		case 0:
			puts(GREEN"	Exit successfully\n"RED);
			system("pause");
			return;
		default:
			printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
			system("pause");
			break;
		}
		if (input != '\n')
		{
			while (getchar() != '\n');
		}
	} while (1);
}

📱3.7 通讯录排序功能的实现

通过回调函数,使用库函数qsort,通过名字进行排序,排序完成,打印通讯录。

//排序通讯录信息
int cmp_by_name(const void* elem1, const void* elem2)
{
	return strcmp(((PeoInfo*)elem1)->name, ((PeoInfo*)elem2)->name);
}
void QsortCon(Contacts* con)
{
	assert(con);
	system("cls");
	int ret = sizeof(con->data[0]);
	qsort(con->data, con->sz, sizeof(con->data[0]), cmp_by_name);
	PrintContact(con);
	printf(GREEN"Sort completion!\n"NONE);
	system("pause");
}

📱3.8 通讯录修改功能的实现

通过名字查找需要修改数据的位置,进而进行直接写入

void ModifyCon(Contacts* con)
{
	assert(con);
	PrintContact(con);
	char name[NAME_MAX] = { 0 };
	printf(BLUE"Please enter the name of the person whose information you want to change:>"NONE);
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos == -1)
	{
		printf(RED"err:The changed object does not exist!!!\n"NONE);
		return;
	}
	else
	{
		system("cls");
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
			con->data[pos].name,
			con->data[pos].age, con->data[pos].sex,
			con->data[pos].tele, con->data[pos].addr);
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("Please enter the change information!\n");
		printf(BLUE"Please enter name:>"NONE);
		scanf("%s", con->data[pos].name);
		printf(BLUE"Please enter age:>"NONE);
		scanf("%d", &(con->data[pos].age));
		printf(BLUE"Please enter gender:>"NONE);
		scanf("%s", con->data[pos].sex);
		printf(BLUE"Please enter telephone number:>"NONE);
		scanf("%s", con->data[pos].tele);
		printf(BLUE"Please enter the address:>"NONE);
		scanf("%s", con->data[pos].addr);
		printf(GREEN"Information change completed!\n"NONE);
		system("pause");
	}
}

📱3.9 通讯录打印功能的实现

void PrintContact(const Contacts* con)
{
	assert(con);
	int i = 0;
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
	for (i = 0; i < con->sz; i++)
	{
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
			(con->data + i)->name,
			con->data[i].age, con->data[i].sex,
			con->data[i].tele, con->data[i].addr);
	}
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
}

📱3.10 通讯录文件保存及释放空间

通过文件操作,保存所有数据到contacts.dat二进制文件中,并将堆区所动态开辟的空间进行释放.

//销毁通讯录
void DestroyContact(Contacts* con)
{
	assert(con);
	if (con->data != NULL)
	{
		free(con->data);
		con->data = NULL;
		con->capacity = con->sz = 0;
	}
}

//保存通讯录信息到文件
void SaveContact(const Contacts* con)
{
	FILE* pf = fopen("contacts.dat", "wb");
	if (pf == NULL)
	{
		perror("SaveContact::fopen");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite(con->data + i, sizeof(PeoInfo), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

📰4. 通讯录完整源代码:

运行图:

 

📱4.1 Contacts.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#define RED "\033[0;32;31m"
#define GREEN "\033[0;32;32m"
#define BLUE  "\033[0;32;34m"
#define NONE "\033[m"


#define	NAME_MAX 20
#define PASSWD_MAX 12

#define	SEX_MAX 5
#define TELE_MAX 12
#define	ADDR_MAX 30

#define DEFAULT_SZ 4//初始化容量大小
enum Option1
{
	EXIT1,
	LOGOIN,
	SIGNIN,
};
typedef struct Users
{
	char UserName[NAME_MAX];
	char UserPasswd[PASSWD_MAX];
}Users;


enum Option2
{
	EXIT2,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contacts
{
	PeoInfo* data;
	int sz;
	int capacity;
}Contacts;


bool UserLogo();
void UserSign();


void InitContact(Contacts* con);
void AddContact(Contacts* con);
void DeleContactMenu(Contacts* con);
void PrintContact(const Contacts* con);
void SearhConMenu(Contacts* con);
void QsortCon(Contacts* con);
void ModifyCon(Contacts* con);
void SaveContact(const Contacts* con);
void DestroyContact(Contacts* con);

📱4.2 Contacts.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contacts.h"
static void check_capacity(Contacts* con)
{
	if (con->sz == con->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(con->data, con->capacity == 0 ? DEFAULT_SZ * sizeof(PeoInfo) : (con->capacity + 2) * sizeof(PeoInfo));
		if (tmp != NULL)
		{
			con->data = tmp;
		}
		else
		{
			perror("check_capacity::realloc");
			return;
		}
		if (con->capacity == 0)
		{
			con->capacity = 4;
		}
		else
		{
			con->capacity += 2;
		}
	}
	return;
}

static void LoadContact(Contacts* con)
{
	FILE* pf = fopen("contacts.dat", "rb");
	if (pf == NULL)
	{
		perror("LoadContact::fopen");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		check_capacity(con);
		con->data[con->sz] = tmp;
		con->sz++;
	}
	fclose(pf);
	pf = NULL;
}


void InitContact(Contacts* con)
{
	assert(con);
	con->sz = con->capacity = 0;
	con->data = NULL;

	LoadContact(con);
}


void AddContact(Contacts* con)
{
	while (getchar() != '\n');
	check_capacity(con);
	system("cls");
	printf("Add contact information\n");
	printf(BLUE"Please enter name:>"NONE);
	scanf("%s", con->data[con->sz].name);
	printf(BLUE"Please enter age:>"NONE);
	scanf("%d", &(con->data[con->sz].age));
	printf(BLUE"Please enter gender:>"NONE);
	scanf("%s", con->data[con->sz].sex);
	printf(BLUE"Please enter telephone number:>"NONE);
	scanf("%s", con->data[con->sz].tele);
	printf(BLUE"Please enter the address:>"NONE);
	scanf("%s", con->data[con->sz].addr);
	con->sz++;
	printf(GREEN"  Add successfully\n"NONE);
	system("pause");
}


//打印通讯录信息,只打印,不修改
void PrintContact(const Contacts* con)
{
	assert(con);
	int i = 0;
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
	for (i = 0; i < con->sz; i++)
	{
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
			(con->data + i)->name,
			con->data[i].age, con->data[i].sex,
			con->data[i].tele, con->data[i].addr);
	}
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
}
static int FindByName(Contacts* con, const char* name)
{
	assert(con && name);
	for (int i = 0; i < con->sz; ++i)
	{
		if (0 == strcmp(con->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}
static int FindByTele(Contacts* con, const char* tele)
{
	assert(con && tele);
	for (int i = 0; i < con->sz; ++i)
	{
		if (0 == strcmp(con->data[i].tele, tele))
		{
			return i;
		}
	}
	return -1;
}
static void deletmenu()
{
	printf("------------------------------\n");
	printf("***** 1. Delete by name  *****\n");
	printf("***** 2. Delete by tele  *****\n");
	printf("***** 0. EXIT DELETE     *****\n");
	printf("------------------------------\n");
}

static void DeleContact(Contacts* con, int (*Find)(Contacts*, const char*))
{
	assert(con);
	char temp[NAME_MAX + TELE_MAX] = { 0 };
	scanf("%s", temp);
	int pos = Find(con, temp);
	if (pos == -1)
	{
		system("cls");
		PrintContact(con);
		printf(RED"err:Nonexistence!!!\n"NONE);
		return;
	}
	void* dest = (void*)(&con->data[pos]);
	void* scr = (void*)(&con->data[pos + 1]);
	int num = sizeof(PeoInfo) * (con->sz - 1 - pos);
	memmove(dest, scr, num);
	con->sz--;
	system("cls");
	PrintContact(con);
	printf(GREEN"   Deleted successfully!\n"NONE);
	system("pause");
	return;
}
void DeleContactMenu(Contacts* con)
{
	while (getchar() != '\n');
	assert(con);
	system("cls");
	PrintContact(con);
	if (con->sz == 0)
	{
		printf(RED"err:The contact is empty and cannot be deleted!!!"NONE);
		return;
	}
	char input = 0;
	do
	{
		deletmenu();
		printf(BLUE"Please select:>"NONE);
		scanf("%c", &input);
		switch (input - '0')
		{
		case 1:
			printf(BLUE"Please enter the name of the person you want to delete:>"NONE);
			DeleContact(con, FindByName);
			break;
		case 2:
			printf(BLUE"Please enter the telephone of the person you want to delete:>"NONE);
			DeleContact(con, FindByTele);
			break;
		case 0:
			puts(GREEN"	Exit successfully\n"NONE);
			system("pause");
			return;
		default:
			printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
			system("pause");
			break;
		}
		if (input != '\n')
		{
			while (getchar() != '\n');
		}
	} while (1);
}

static void searchmenu()
{
	printf("------------------------------\n");
	printf("***** 1. Search by name  *****\n");
	printf("***** 2. Search by tele  *****\n");
	printf("***** 0. EXIT Search     *****\n");
	printf("------------------------------\n");
}
static void SearchContact(Contacts* con, int (*Find)(Contacts*, const char*))
{
	assert(con);
	char temp[NAME_MAX + TELE_MAX] = { 0 };
	scanf("%s", temp);
	int pos = Find(con, temp);
	if (pos == -1)
	{
		system("cls");
		PrintContact(con);
		printf(RED"err:Nonexistence!!!\n"NONE);
		return;
	}
	system("cls");
	printf(GREEN"Sucess:Search successfully!!!\n"NONE);
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
		con->data[pos].name,
		con->data[pos].age, con->data[pos].sex,
		con->data[pos].tele, con->data[pos].addr);
	printf("|--------------------|-----|-----|------------|------------------------------|\n");
	system("pause");
	return;
}

void SearhConMenu(Contacts* con)
{
	while (getchar() != '\n');
	assert(con);
	system("cls");
	PrintContact(con);
	if (con->sz == 0)
	{
		printf(RED"err:The contact is empty and cannot be deleted!!!"NONE);
		return;
	}
	char input = 0;
	do
	{
		searchmenu();
		printf(BLUE"Please select:>"NONE);
		scanf("%c", &input);
		switch (input - '0')
		{
		case 1:
			printf(BLUE"Please enter the name of the person you want to search:>"NONE);
			SearchContact(con, FindByName);
			break;
		case 2:
			printf(BLUE"Please enter the telephone of the person you want to search:>"NONE);
			SearchContact(con, FindByTele);
			break;
		case 0:
			puts(GREEN"	Exit successfully\n"RED);
			system("pause");
			return;
		default:
			printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
			system("pause");
			break;
		}
		if (input != '\n')
		{
			while (getchar() != '\n');
		}
	} while (1);
}

//排序通讯录信息
int cmp_by_name(const void* elem1, const void* elem2)
{
	return strcmp(((PeoInfo*)elem1)->name, ((PeoInfo*)elem2)->name);
}
void QsortCon(Contacts* con)
{
	assert(con);
	system("cls");
	int ret = sizeof(con->data[0]);
	qsort(con->data, con->sz, sizeof(con->data[0]), cmp_by_name);
	PrintContact(con);
	printf(GREEN"Sort completion!\n"NONE);
	system("pause");
}

void ModifyCon(Contacts* con)
{
	assert(con);
	PrintContact(con);
	char name[NAME_MAX] = { 0 };
	printf(BLUE"Please enter the name of the person whose information you want to change:>"NONE);
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos == -1)
	{
		printf(RED"err:The changed object does not exist!!!\n"NONE);
		return;
	}
	else
	{
		system("cls");
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5s|%-5s|%-12s|%-30s|\n", "姓名", "年龄", "性别", "电话号", "住址");
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("|%-20s|%-5d|%-5s|%-12s|%-30s|\n",
			con->data[pos].name,
			con->data[pos].age, con->data[pos].sex,
			con->data[pos].tele, con->data[pos].addr);
		printf("|--------------------|-----|-----|------------|------------------------------|\n");
		printf("Please enter the change information!\n");
		printf(BLUE"Please enter name:>"NONE);
		scanf("%s", con->data[pos].name);
		printf(BLUE"Please enter age:>"NONE);
		scanf("%d", &(con->data[pos].age));
		printf(BLUE"Please enter gender:>"NONE);
		scanf("%s", con->data[pos].sex);
		printf(BLUE"Please enter telephone number:>"NONE);
		scanf("%s", con->data[pos].tele);
		printf(BLUE"Please enter the address:>"NONE);
		scanf("%s", con->data[pos].addr);
		printf(GREEN"Information change completed!\n"NONE);
		system("pause");
	}
}

//销毁通讯录
void DestroyContact(Contacts* con)
{
	assert(con);
	if (con->data != NULL)
	{
		free(con->data);
		con->data = NULL;
		con->capacity = con->sz = 0;
	}
}

//保存通讯录信息到文件
void SaveContact(const Contacts* con)
{
	FILE* pf = fopen("contacts.dat", "wb");
	if (pf == NULL)
	{
		perror("SaveContact::fopen");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite(con->data + i, sizeof(PeoInfo), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

📱4.3 ContactsUsers.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contacts.h"

bool UserLogo()
{
	FILE* pf = fopen("Users.bat", "rb");
	Users user1 = { 0,0 }, user2 = { 0,0 };
	if (pf == NULL)
	{
		printf(RED"err:The user directory file does not exist!\n"NONE
		"  Please register the user first\n"NONE);
		system("pause");
		return false;
	}
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("          Login interface\n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please enter the account number:>"NONE);
	if (scanf("%s", user1.UserName) == EOF)
	{
		perror("Incorrect input");
	}
	fread(&user2, sizeof(Users), 1, pf);
	while (1)
	{
		if (strcmp(user1.UserName, user2.UserName) != 0)
		{
			if (feof(pf) == 0)//未到文件尾 
				fread(&user2, sizeof(Users), 1, pf);
			else//到了文件尾仍然没有相同的字符串-说明输入的账号新的 可以去注册界面 
			{
				printf(GREEN"The account has not been registered. Rejump\n"NONE);
				system("pause");
				fclose(pf);
				pf = NULL;
				return false;//利用break来跳出无限循环 
			}
		}
		else
		{
			break;
		}
	}
	printf(BLUE"Please enter password:>"NONE);
	int n = 3;//三次输入机会
	while (n)
	{
		if (scanf("%s", user1.UserPasswd) == EOF)
		{
			perror("Incorrect input");
		}
		if (strcmp(user1.UserPasswd, user2.UserPasswd) != 0)
		{
			if (n == 1)
			{
				printf(RED"	 err:Login failure\n"NONE);
				fclose(pf);
				pf = NULL;
				system("pause");
				return false;
			}
			printf(RED"err:Password error\n"NONE
			BLUE"Please enter the password again:>"NONE);
		}
		else
		{
			break;
		}
		n--;
	}

	printf(GREEN"    Login success!\n"NONE);
	getchar();
	system("pause");
	fclose(pf); 
	pf = NULL;
	return true;
}

void UserSign()
{
	Users user1 = { 0,0 },user2 = {0,0};
	FILE* pf,*PF = NULL;
	pf = fopen("Users.bat", "rb");
	if (pf == NULL)
	{
		PF = fopen("Users.bat", "wb");
		fclose(PF);;
	}
	pf = fopen("Users.bat", "rb");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("      Registration interface\n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please set a new user name:>"NONE);
	if (scanf("%s", user1.UserName) == EOF)
	{
		perror("Incorrect input");
	}

	printf(GREEN"       Enter successfully\n"NONE);
	fread(&user2, sizeof(Users), 1, pf);

//【判断】有没有注册过-比较字符串是否相等 
//不相等->是否到文件尾 
	while (1)
	{
		if (strcmp(user1.UserName, user2.UserName) != 0)
		{
			if (feof(pf) == 0)//未到文件尾 
				fread(&user2, sizeof(Users), 1, pf);
			else//到了文件尾仍然没有相同的字符串-说明输入的账号使新的 可以去注册界面 
			{
				printf(GREEN"The account has not been registered. Rejump\n"NONE);
				break;//利用break来跳出无限循环 
			}
		}
		else
		{
			printf(RED"err: The account has been registered!\n"NONE);
			fclose(pf); pf = NULL;
			system("pause");
			return;
		}
	}
	//判断两次密码是否相同,且必须大于5位
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf("      Registration interface       \n");
	printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
	printf(BLUE"Please set the user password :(English and digital only):>"NONE);
	if (scanf("%s", user1.UserPasswd) == EOF)
	{
		perror("Incorrect input");
	}
	while (strlen(user1.UserPasswd) < 5)
	{
		printf(RED"err:The password must be at least six characters!"NONE
		BLUE"\nPlease enter the password again:>"NONE);
		if (scanf("%s", user1.UserPasswd) == EOF)
		{
			perror("Incorrect input");
		}
	}
	printf(BLUE"Please enter your password again:>"NONE);
	char tmp[PASSWD_MAX] = { 0 };
	do {
		if (EOF == scanf("%s", tmp))
		{
			perror("Incorrect input");
		}
		if (strcmp(tmp, user1.UserPasswd) != 0)
			printf(RED"\nerr:The two passwords are different.\
				\nPlease enter the password again->"NONE);
		else 
			break;
	} while (1);
	//两次密码一致
	fclose(pf);	
	pf = NULL;
	pf = fopen("Users.bat", "ab");
	if (pf == NULL)
	{
		perror("UserSign failed");
	}
	//fwrite会在当前文件指针的位置写入数据
	//"w" 打开,文件指针指到头,只写;"a" 打开,指向文件尾
	else
	{
		fwrite(&user1, sizeof(Users), 1, pf);
		printf(GREEN"     Registered successfully!\n"NONE);
		system("pause");
		fclose(pf);
		pf = NULL;
	}
	return;
}

📱4.4 Contacts_Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contacts.h"



void menu2()
{
	printf("------------------------------\n");
	printf("---------- CONTACT -----------\n");
	printf("***** 1.add       2.del  *****\n");
	printf("******************************\n");
	printf("***** 3.search  4.modify *****\n");
	printf("******************************\n");
	printf("***** 5.sort    6.print  *****\n");
	printf("**********(0.exit)************\n");
	printf("------------------------------\n");


}
void test2()
{
	char input = 0;
	Contacts con;
	InitContact(&con);
	while (1)
	{
		system("cls");
		menu2();
		printf(BLUE"Welcome to use,please select:>"NONE);
		if (scanf("%c", &input) != EOF)
		{
			switch (input - '0')
			{
			case ADD:
				AddContact(&con);
				break;
			case DEL:
				DeleContactMenu(&con);
				break;
			case SEARCH:
				SearhConMenu(&con);
				break;
			case MODIFY:
				ModifyCon(&con);
				break;
			case SORT:
				QsortCon(&con);
				break;
			case PRINT:
				PrintContact(&con);
				system("pause");
				break;
			case EXIT2:
				SaveContact(&con);
				DestroyContact(&con);
				puts(RED"	Exit successfully\n"RED);
				system("pause");
				return;
			default:
				printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
				system("pause");
				break;
			}
			if (input != '\n')
			{
				while (getchar() != '\n');
			}
		}
	}
}

void menu1()
{
	printf("------------------------------\n");
	printf("---------- CONTACT -----------\n");
	printf("********  1.Logo In  *********\n");
	printf("******************************\n");
	printf("********  2.Sign In  *********\n");
	printf("******************************\n");
	printf("***********(0.exit)***********\n");
	printf("------------------------------\n");
}
void test1()
{
	char input;
	do
	{
		system("cls");
		menu1();
		printf(BLUE"Welcome to use,please select:>"NONE);
		if (scanf("%c", &input) != EOF)
		{
			switch (input-'0')
			{
			case LOGOIN:
				system("cls"); 
				if (UserLogo() == true)
				{
					test2();
				}
				break;
			case SIGNIN:
				system("cls"); UserSign(); break;
			case EXIT1:
				puts(RED"	Exit successfully\n"RED); exit(0);
			default:
				printf(RED"err:Incorrect input:please enter again!\n\n"NONE);
				system("pause");
				break;
			}
			if (input != '\n')
			{
				while (getchar() != '\n');
			}
		}
	} while (1);
}

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

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

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

相关文章

完美解决丨 - [SyntaxError: invalid syntax](#SyntaxError-invalid-syntax)

目录 报错名称SyntaxError: invalid syntaxNameError: name xx is not definedIndentationError: expected an indented blockAttributeError: xx object has no attribute xxTypeError: xx object is not callableValueError: I/O operation on closed fileOSError: [Errno 2]…

目前的Android 市场怎么样?还好吗?

如今&#xff0c;随着互联网和移动设备的普及&#xff0c;Android 系统已成为全球最大的移动操作系统之一&#xff0c;成为最受欢迎的应用程序开发平台之一。作为一名 Android 开发者&#xff0c;我们生活中的大部分应用程序都是基于 Android 平台开发的&#xff0c;而我们的工…

从字节码分析String创建的几种方式

一.String a new String("a"); 1.到底会不会进入常量池 String a new String("a"); 通过idea中jclasslib插件获取到字节码 0 new #2 3 dup 4 ldc #3 <a> 6 invokespecial #4 <java/lang/String.<init> : (Ljava/lang/String;)V>9 as…

MongoDB 聚合管道中使用数组表达式运算符获取数组长度($size)和反转数组($reverseArray)

数组表达式运算符主要用于文档中数组的操作&#xff0c;本篇我们主要介绍如何使用数组表达式运算符获取数组的长度以及对数组中的数据进行反转&#xff1a; 一、准备数据 初始化成员数据 db.persons.insertMany([{ "_id" : "1001", "name" : …

go错误处理

func test() {num1 : 10num2 : 0result : num1 / num2fmt.Println("result", result)} func main() {test()for {fmt.Println("运行完毕&#xff01; main 下面的代码")time.Sleep(time.Second)}}在默认情况下&#xff0c;当发生错误后(panic) ,程序就会…

港联证券|揭秘涨停 旅游板块掀涨停潮

今天&#xff0c;A股三大股指低开低走。沪深两市收盘共38股涨停。剔除7只ST股&#xff0c;合计31股涨停。另外&#xff0c;14股封板未遂&#xff0c;整体封板率为73.08%。 涨停战场&#xff1a;6股封单资金超亿元 港联证券核算&#xff0c;从收盘涨停板封单量来看&#xff0c;…

【Pytorch】数据预处理

Pytorch是机器学习里面常用的框架之一&#xff0c;我们在学习机器学习之前最好需要学习如何使用这个框架对我们将要使用的数据数据进行预处理操作。 如果我们想要学习好pytorch里面的方法&#xff0c;我们需要常去用一下dir()和help()函数&#xff0c;它们一个会帮我们查看某个…

计算机软考考什么?怎么备考啊?

计算机软考是国家承认的计算机职业资格考试&#xff0c;是计算机行业从业者晋升职业等级的重要途径。计算机软考分为三个等级&#xff0c;分别是&#xff1a;初级、中级和高级。 备考计算机软考需要全面准备&#xff0c;下面我将从如何选择考试科目、如何制定学习计划、如何进…

【STL系列】unordered_set和unordered_map

前言 之前&#xff0c;我们介绍了STL中树形结构容器:set、map、multiset、multimap。 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时的效率可达到O(logN)&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;但当树中的结点非…

九龙证券|昨夜,大涨!蔚来5.99%,小鹏15.22%,理想6.39%

当地时间周一&#xff0c;美股三大指数低开高走&#xff0c;尾盘小幅收涨。盘面上&#xff0c;银行股、航空股遍及上涨。 展望本周&#xff0c;包括美联储理事沃勒、鲍曼等官员将迎来下月会议沉默期前的最终说话&#xff0c;投资者需关注其对经济和货币政策前景的看法。此外&am…

牛客网华为机考题库 C++

题目汇总HJ2 计算某字符出现次数HJ3 明明的随机数HJ4 字符串分隔HJ5 进制转换HJ6 质数因子HJ7 取近似值HJ8 合并表记录 哈希表HJ9 提取不重复的整数HJ10 字符个数统计HJ11 数字颠倒HJ12 字符串反转HJ13 句子逆序HJ14 字符串排序HJ15 求int型正整数在内存中存储时1的个数HJ16 购…

快速创建springboot+springcloud项目(nacos,seata,sentinel,gateway,openfeign)

一、创建一个maven项目 1.file->new->project 2.创建maven项目 3.删除src文件夹 4.在pom.xml文件中引入springboot和cloudAlibaba依赖 <dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId>&l…

用Python解决Excel问题的最佳姿势

大家好&#xff0c;我是毕加锁。 今天给大家带来的是用Python解决Excel问题的最佳姿势 文末送书&#xff01; 文末送书&#xff01; 文末送书&#xff01; 「问题说明」 这次要处理的excel有两个sheet&#xff0c;要根据其中一个sheet的数据来计算另外一个sheet的值。造成问…

循环神经网络

循环神经网络(Recurrent Neural Network&#xff0c;RNN)与卷积神经网络一样,都是深度学习中的重要部分。循环神经网络可以看作一类具有短期记忆能力的神经网络。在循环神经网络中&#xff0c;神经元不但可以接收其他神经元的信息&#xff0c;也可以接收自身的信息&#xff0c;…

ChatGPT 速通手册——开始提问

开始提问 当我们完成注册后&#xff0c;页面自动会跳转到ChatGPT的主页面&#xff0c;在这里我们就可以开始进行对话了。 我们在页面下方的输入框中填写问题&#xff0c;然后回车或者点击小飞机&#xff0c;我们的问题和ChatGPT的答案就会在页面上方以一问一答的格式展现出来…

Packet Tracer 的安装过程

Packet Tracer 的安装过程 下载地址 链接&#xff1a;https://pan.baidu.com/s/1KO-vJ1p-miU7LXRH92hLww 提取码&#xff1a;ocwu 、双击运行 Crack 文件夹中的"Patch.exe"程序&#xff0c;点击 Patch&#xff1b; 7、即可看到显示激活成功&#xff0c;接下来打开…

Matplotlib学习挑战第四关-网格线grid

Matplotlib 网格线 我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。 grid() 方法语法格式如下&#xff1a; matplotlib.pyplot.grid(bNone, whichmajor, axisboth, )b&#xff1a;可选&#xff0c;默认为 None&#xff0c;可以设置布尔值&#xff0c;true 为显…

CentOS 软件包管理

一、文件打包与压缩 1.du命令 --查看目录或文件所占磁盘空间的大小 -h&#xff0c;以K,M,G为单位显示统计结果&#xff08;默认单位为字节&#xff09; -s&#xff0c;查看目录本身的大小 2.打包压缩 tar命令--打包&#xff0c;打包文件的扩展名为.tar…

如何在TypeScript中使用泛型

介绍 泛型是静态类型语言的基本特征&#xff0c;允许开发人员将类型作为参数传递给另一种类型、函数或其他结构。当开发人员使他们的组件成为通用组件时&#xff0c;他们使该组件能够接受和强制在使用组件时传入的类型&#xff0c;这提高了代码灵活性&#xff0c;使组件可重用…

【计算机网络——计算机网络的概念,组成,功能和分类以及相关的性能指标,分层结构和协议,TCP/IP参考模型】

文章目录计算机网络体系结构计算机网络的概念、组成、功能和分类标准化工作及相关组织速率相关的性能指标时延、时延带宽积、PTT和利用率分层结构、协议、接口和服务OSI参考模型TCP IP参考模型计算机网络体系结构 计算机网络的概念、组成、功能和分类 计算机网络的概念 计算…