【基于动态内存+文件操作】通讯录管理系统

news2024/11/24 5:20:58

在这里插入图片描述

前言

每一个项目文件的功能说明

  • 打印基本菜单
  • 1.创建一个适合存放联系人信息的结构体和通讯录结构体
  • 2.初始化通讯录(加载上次的联系人,检查容量是否充足)

枚举常量内部内容

(1)增加联系人信息

(2)删除某个联系人信息

(3)查找联系人信息

(4)修改联系人信息

(5)展示联系人信息

(6)排序联系人信息(可以按照姓名,年龄,性别,电话,住址的等种类进行排序)

(7)清空通讯录

(8)保存当前录入的联系人信息

  • 所有函数的声明
  • 所有头文件
  • 完整代码
  • 文末:小编想说的话

前言

对于一个通讯录管理系统来说,较为重要的是清楚具体需要什么功能以及每一块功能的实现。

下面,实现一个通讯录,该通讯录能够进行联系人的添加,删除,查找,修改,展示,排序,保存,销毁,等功能。

我们知道,一个联系人有以下基本信息:联系人姓名,年龄,性别,电话,住址等。

所以下面来实现功能时,按照每一个功能逐一实现即可。

每一个项目文件的说明

该通讯录包含三个项目文件:
Contact.c文件
Contact.h文件
test.c文件

Contact.c文件是用来实现每个区域的功能。
Contact.h文件是用来声明函数,包含头文件的。
test.c文件是用来测试代码的(建议封装完一个函数,写完一个函数后就测试代码)

打印基本菜单,以供用户选择。

实现菜单较为简单,列出功能,共用户选择即可。

void menu(void)
{
	printf("*******************************\n");
	printf("******1.Add     2.Del    ******\n");
	printf("******3.Search  4.Modify ******\n");
	printf("******5.Show    6.Sort   ******\n");
	printf("******7.Clean   8.Save   ******\n");
	printf("******0.Exit             ******\n");
	printf("*******************************\n");

}

在这里插入图片描述

1.创建一个适合存放联系人信息的结构体

上面讲到,联系人的信息有姓名,年龄,性别,电话,地址等


#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define CAPACITY_SIZE 3


//个人信息
typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

基本联系人信息如上。

然而,这只是一个人的信息,一个通讯录有成百上千人,我们需要一块空间来存放联系人的信息,这就需要到一个结构体数组来存放每一个结构体联系人的信息,如下图:
在这里插入图片描述
又有一个问题了,当存放了第一个人的信息后,怎么找到第二个人的空间来存放?第三个人呢?

由此可以联想到,需要用到一个存储下标的结构体变量,每存储一个人的信息,该下标变量就++。
在这里插入图片描述

我们在一开始申请空间的时候,不适宜申请太多空间,申请多少空间,就用一个变量来记录,叫做capacity(容量),也就是结构体的申请的空间大小。

所以可以创建一个大空间存放每个人的信息,该空间也是一个结构体,包含一个数组和存储下标的变量和一个结构体的容量(能容纳多少个联系人)。

//整个通讯录信息
typedef struct Contact
{
	PeoInfo *data;
	int sz;
	int capacity;
}Contact;

2.初始化通讯录(加载上次的联系人,检查容量是否充足)

在初始化通讯录时,我们可以分装一个函数,专门实现该功能。

我们在写入联系人信息时,该信息会保存到本地的磁盘中,当我们再次进入通讯录时,应该加载上一次存放好的联系人的信息,防止用户重复存放等。
所以应该也需要封装一个加载信息的函数:

void LoadContact(Contact* ps)
{
	assert(ps);
	FILE* pfread = fopen("Contact.txt", "rb");//二进制形式读取
	PeoInfo tmp = { 0 };//把读取的联系人先放着,先判断容量够不够,再放进data里

	if (pfread == NULL)
	{
		printf("LoadContact:%s\n", strerror(errno));
	}

	else
	{
		while (fread(&tmp, sizeof(PeoInfo), 1, pfread))
		{
			CheckCapacity(ps);//判断容量够不够
			ps->data[ps->sz] = tmp;
			ps->sz++;
		}
	}
	fclose(pfread);
	pfread = NULL;
}

初始化完通讯录后,就加载上一次的联系人信息出来。由于我们在进入通讯录时,申请的空间不多,有可能在本地磁盘中存储的联系人信息有多个,我们申请的空间只要少量,所以需要检查容量是否充足,如果容量不足,则需要再次申请空间。

//检查容量
void CheckCapacity(Contact* ps)
{
	assert(ps);

	if (ps->sz == ps->capacity)
	{
		//扩容
		PeoInfo* ptr = realloc(ps->data, sizeof(PeoInfo) * (2 + ps->capacity));//一次扩容两个
		if (ptr == NULL)
		{
			printf("%s\n", strerror(errno));
			printf("增容失败\n");
		}
		else
		{
			ps->data = ptr;
			ps->capacity += 2;
			printf("增容成功\n");
		}
	}
}

用上面的函数来检查容量。

void InitContact(Contact* ps)
{
	assert(ps);
	ps->data =(PeoInfo*)malloc(sizeof(PeoInfo) * CAPACITY_SIZE);

	if (ps->data == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	ps->capacity = CAPACITY_SIZE;
	ps->sz = 0;
}

初始化完通讯录之后,就可以开始逐一实现每个函数的功能了。

枚举常量内部内容:

对于枚举来说,其成员的排序是从0开始的,即第一个成员的序号是0,第二个成员的序号是1…

enum
{
	Exit,//0
	Add,//1
	Del,//2
	Search,//3
	Modify,//4
	Show,//5
	Sort,//6
	Clean,//7
	Save//8
};

(1)增加联系人信息

再增加联系人之前,需要检查当前的容量是否足够,如果不够,也是一样需要增容。

增加联系人的信息,就需要输入姓名,年龄,性别,电话,住址等。
并且每次增加完之后,指向联系人的下标的变量就需要++,向前走。

void AddContact(Contact* ps)
{
	assert(ps);
	CheckCapacity(ps);
	检查容量是否充足
	
	printf("请输入姓名:>\n");
	scanf("%s", ps->data[ps->sz].name);
	printf("请输入年龄:>\n");
	scanf("%d", &ps->data[ps->sz].age);
	printf("请输入性别:>\n");
	scanf("%s", ps->data[ps->sz].sex);
	printf("请输入电话:>\n");
	scanf("%s", ps->data[ps->sz].tele);
	printf("请输入住址:>\n");
	scanf("%s", ps->data[ps->sz].addr);

	ps->sz++;
	printf("添加成功\n");
}

(2)删除联系人信息

实现代码之前,先想想,删除一个联系人,是不是要先找到该联系人?不然怎么删除呢?
而找该联系人,就是第三个功能:查找联系人。
而第四个功能:删除联系人,同理,必须先找到想修改的联系人的信息,才能修改。
所以,这三个功能都有相同点:先找到目标联系人
封装一个函数来实现:

static int FindByName(const Contact* ps)
{
	assert(ps);
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);
	for (int i = 0; i < ps->sz; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

以名字来查找。

有了这个函数,就可以删除目标联系人了。

所谓的删除,不过就是往前覆盖,进行下标再- -
在这里插入图片描述

void DelContact(Contact* ps)
{
	assert(ps);
	printf("请输入要删除的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//删除也就是向前覆盖即可
	for (int i = pos; i < ps->sz - 1; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	
	ps->sz--;
	printf("删除成功\n");
}

(3)查找联系人信息

查找联系人信息,然后打印出来。

void SearchContact(const Contact* ps)
{
	assert(ps);
	printf("请输入要查找的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话", "住址");

	printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[pos].name,
		ps->data[pos].age,
		ps->data[pos].sex,
		ps->data[pos].tele,
		ps->data[pos].addr);

}

(4)修改联系人信息

void ModifyContact(Contact* ps)
{
	assert(ps);
	printf("请输入要修改的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	printf("请输入姓名:>\n");
	scanf("%s", ps->data[pos].name);
	printf("请输入年龄:>\n");
	scanf("%d", &ps->data[pos].age);
	printf("请输入性别:>\n");
	scanf("%s", ps->data[pos].sex);
	printf("请输入电话:>\n");
	scanf("%s", ps->data[pos].tele);
	printf("请输入住址:>\n");
	scanf("%s", ps->data[pos].addr);

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

(5)展示联系人信息

void ShowContact(const Contact* ps)
{
	assert(ps);
	if (ps->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}

	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名","年龄","性别", "电话","住址");

	for (int i = 0; i < ps->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[i].name, 
			ps->data[i].age, 
			ps->data[i].sex,
			ps->data[i].tele, 
			ps->data[i].addr);
	}

}

(6)对联系人信息进行排序

提供的排序种类有:姓名,年龄,性别,电话,住址

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

int cmp_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age ;
}

int cmp_sex(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->sex, ((PeoInfo*)e2)->sex);
}

int cmp_tele(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->tele, ((PeoInfo*)e2)->tele);
}

int cmp_addr(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->addr, ((PeoInfo*)e2)->addr);
}

void SortContact(Contact* ps)
{
	assert(ps);
	char tmp[5] = { 0 };
	printf("请输入要排序的种类:>\n");
	printf("(姓名,年龄,性别,电话,住址)\n");
	scanf("%s", tmp);
	char* arr[5] = { "姓名","年龄","性别","电话","住址" };
	if (strcmp(arr[0], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);
	}

	if (strcmp(arr[1], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_age);
	}

	if (strcmp(arr[2], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_sex);
	}

	if (strcmp(arr[3], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_tele);
	}

	if (strcmp(arr[4], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_addr);
	}

	printf("排序成功\n");

}
void CleanContact(Contact* ps)
{
	if (ps->sz == 0)
	{
		printf("通讯录已为空,无需清除\n");
		return;
	}
	memset(ps->data, 0, ps->sz);
	ps->sz = 0;
	printf("清除成功\n");
} 

(7)清空联系人列表

void CleanContact(Contact* ps)
{
	if (ps->sz == 0)
	{
		printf("通讯录已为空,无需清除\n");
		return;
	}
	memset(ps->data, 0, ps->sz);
	ps->sz = 0;
	printf("清除成功\n");
} 

(8)保存当前的联系人信息到本地磁盘中

保存信息也就是写入文件。

void SaveContact(Contact* ps)
{
	assert(ps);
	size_t count = 0;
	if (ps->sz == 0)
	{
		printf("无要保存的联系人\n");
		return;
	}

	FILE* pfwrite = fopen("Contact.txt", "wb");//以二进制形式写入
	if (pfwrite == NULL)
	{
		printf("SaveContact:%s\n", strerror(errno));
	}
	for (int i = 0; i < ps->sz; i++)
	{
		count = fwrite(&(ps->data[i]), sizeof(ps->data[0]), 1, pfwrite);
		//size_t fwrite(const void* buffer, size_t size, size_t count, FILE * stream);
	}

	if (ps->sz == (int)count)
	{
		printf("所有联系人全部保存成功\n");
	}

	else
	{
		printf("保存了%zd个联系人", count);
	}

	fclose(pfwrite);
	pfwrite = NULL;
}

所有函数的声明

//初始化通讯录
void InitContact(Contact* ps);
//增加联系人信息
void AddContact(Contact *ps);
//展示联系人信息
void ShowContact(const Contact*ps);
//删除联系人信息
void DelContact(Contact* ps);
//搜索联系人信息
void SearchContact(const Contact *ps);
//修改联系人信息
void ModifyContact(Contact *ps);
//对联系人进行排序
void SortContact(Contact* ps);
//清空联系人
void CleanContact(Contact*ps);
//退出时销毁通讯录
void DestroyContact(Contact *ps);
//保存通讯录信息
void SaveContact(Contact* ps);

头文件如下:

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

完整代码如下:

Contact.h项目文件

#define _CRT_SECURE_NO_WARNINGS 1

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

#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define CAPACITY_SIZE 3

//个人信息
typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

//整个通讯录信息
typedef struct Contact
{
	PeoInfo *data;
	int sz;
	int capacity;
}Contact;

//初始化通讯录
void InitContact(Contact* ps);
//增加联系人信息
void AddContact(Contact *ps);
//展示联系人信息
void ShowContact(const Contact*ps);
//删除联系人信息
void DelContact(Contact* ps);
//搜索联系人信息
void SearchContact(const Contact *ps);
//修改联系人信息
void ModifyContact(Contact *ps);
//对联系人进行排序
void SortContact(Contact* ps);
//清空联系人
void CleanContact(Contact*ps);
//退出时销毁通讯录
void DestroyContact(Contact *ps);
//保存通讯录信息
void SaveContact(Contact* ps);

enum
{
	Exit,//0
	Add,//1
	Del,//2
	Search,//3
	Modify,//4
	Show,//5
	Sort,//6
	Clean,//7
	Save//8
};

Contact.c项目文件如下:

#include"Contact.h"

//检查容量
void CheckCapacity(Contact* ps)
{
	assert(ps);

	if (ps->sz == ps->capacity)
	{
		//扩容
		PeoInfo* ptr = realloc(ps->data, sizeof(PeoInfo) * (2 + ps->capacity));//一次扩容两个
		if (ptr == NULL)
		{
			printf("%s\n", strerror(errno));
			printf("增容失败\n");
		}
		else
		{
			ps->data = ptr;
			ps->capacity += 2;
			printf("增容成功\n");
		}
	}
}

//加载联系人信息
void LoadContact(Contact* ps)
{
	assert(ps);
	FILE* pfread = fopen("Contact.txt", "rb");//二进制形式读取
	PeoInfo tmp = { 0 };//把读取的联系人先放着,先判断容量够不够,再放进data里

	if (pfread == NULL)
	{
		printf("LoadContact:%s\n", strerror(errno));
	}

	else
	{
		//size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
		while (fread(&tmp, sizeof(PeoInfo), 1, pfread))
		{
			CheckCapacity(ps);//判断容量够不够
			ps->data[ps->sz] = tmp;
			ps->sz++;
		}
	}
	fclose(pfread);
	pfread = NULL;

}

//初始化通讯录
void InitContact(Contact* ps)
{
	assert(ps);
	ps->data =(PeoInfo*)malloc(sizeof(PeoInfo) * CAPACITY_SIZE);

	if (ps->data == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	ps->capacity = CAPACITY_SIZE;
	ps->sz = 0;
	
	LoadContact(ps);//从上次保存的文件中加载联系人信息出来

	//memset(ps->data, 0, sizeof(ps->data));
	//ps->sz = 0;
}



void AddContact(Contact* ps)
{
	assert(ps);
	CheckCapacity(ps);

	printf("请输入姓名:>\n");
	scanf("%s", ps->data[ps->sz].name);
	printf("请输入年龄:>\n");
	scanf("%d", &ps->data[ps->sz].age);
	printf("请输入性别:>\n");
	scanf("%s", ps->data[ps->sz].sex);
	printf("请输入电话:>\n");
	scanf("%s", ps->data[ps->sz].tele);
	printf("请输入住址:>\n");
	scanf("%s", ps->data[ps->sz].addr);

	ps->sz++;
	printf("添加成功\n");
}


static int FindByName(const Contact* ps)
{
	assert(ps);
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);
	for (int i = 0; i < ps->sz; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


void DelContact(Contact* ps)
{
	assert(ps);
	printf("请输入要删除的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//删除也就是向前覆盖即可
	for (int i = pos; i < ps->sz - 1; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	
	ps->sz--;
	printf("删除成功\n");
}

void SearchContact(const Contact* ps)
{
	assert(ps);
	printf("请输入要查找的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话", "住址");

	printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[pos].name,
		ps->data[pos].age,
		ps->data[pos].sex,
		ps->data[pos].tele,
		ps->data[pos].addr);

}


void ModifyContact(Contact* ps)
{
	assert(ps);
	printf("请输入要修改的人的名字:>\n");
	int pos = FindByName(ps);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	printf("请输入姓名:>\n");
	scanf("%s", ps->data[pos].name);
	printf("请输入年龄:>\n");
	scanf("%d", &ps->data[pos].age);
	printf("请输入性别:>\n");
	scanf("%s", ps->data[pos].sex);
	printf("请输入电话:>\n");
	scanf("%s", ps->data[pos].tele);
	printf("请输入住址:>\n");
	scanf("%s", ps->data[pos].addr);

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

void ShowContact(const Contact* ps)
{
	assert(ps);
	if (ps->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}

	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名","年龄","性别", "电话","住址");

	for (int i = 0; i < ps->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[i].name, 
			ps->data[i].age, 
			ps->data[i].sex,
			ps->data[i].tele, 
			ps->data[i].addr);
	}

}

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

int cmp_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age ;
}

int cmp_sex(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->sex, ((PeoInfo*)e2)->sex);
}

int cmp_tele(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->tele, ((PeoInfo*)e2)->tele);
}

int cmp_addr(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->addr, ((PeoInfo*)e2)->addr);
}

void SortContact(Contact* ps)
{
	assert(ps);
	char tmp[5] = { 0 };
	printf("请输入要排序的种类:>\n");
	printf("(姓名,年龄,性别,电话,住址)\n");
	scanf("%s", tmp);
	char* arr[5] = { "姓名","年龄","性别","电话","住址" };
	if (strcmp(arr[0], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);
	}

	if (strcmp(arr[1], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_age);
	}

	if (strcmp(arr[2], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_sex);
	}

	if (strcmp(arr[3], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_tele);
	}

	if (strcmp(arr[4], tmp) == 0)
	{
		//起始地址,排序个数,每个元素大小,比较方法
		qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_addr);
	}

	printf("排序成功\n");

}

void CleanContact(Contact* ps)
{
	if (ps->sz == 0)
	{
		printf("通讯录已为空,无需清除\n");
		return;
	}
	memset(ps->data, 0, ps->sz);
	ps->sz = 0;
	printf("清除成功\n");
} 

void DestroyContact(Contact* ps)
{
	free(ps->data);
	ps->data = NULL;
	printf("销毁成功\n");
}

void SaveContact(Contact* ps)
{
	assert(ps);
	size_t count = 0;
	if (ps->sz == 0)
	{
		printf("无要保存的联系人\n");
		return;
	}

	FILE* pfwrite = fopen("Contact.txt", "wb");//以二进制形式写入
	if (pfwrite == NULL)
	{
		printf("SaveContact:%s\n", strerror(errno));
	}
	for (int i = 0; i < ps->sz; i++)
	{
		count = fwrite(&(ps->data[i]), sizeof(ps->data[0]), 1, pfwrite);
		//size_t fwrite(const void* buffer, size_t size, size_t count, FILE * stream);
	}

	if (ps->sz == (int)count)
	{
		printf("所有联系人全部保存成功\n");
	}

	else
	{
		printf("保存了%zd个联系人", count);
	}

	fclose(pfwrite);
	pfwrite = NULL;
}

test.c项目文件如下:

#include"Contact.h"


void menu(void)
{
	printf("*******************************\n");
	printf("******1.Add     2.Del    ******\n");
	printf("******3.Search  4.Modify ******\n");
	printf("******5.Show    6.Sort   ******\n");
	printf("******7.Clean   8.Save   ******\n");
	printf("******0.Exit             ******\n");
	printf("*******************************\n");

}

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);
	do
	{
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case Exit:
			SaveContact(&con);//退出时自动保存
			printf("在您退出通讯录时,已自动为您保存\n");
			DestroyContact(&con);//退出时销毁通讯录
			printf("退出通讯录\n");
			break;
		case Add:
			AddContact(&con);
			break;
		case Del:
			DelContact(&con);
			break;
		case Search:
			SearchContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			SortContact(&con);
			break;
		case Clean:
			CleanContact(&con);
			break;
		case Save:
			SaveContact(&con);
			break;
		default:
			printf("选择错误,请重新选择:>\n");
			break;
		}
	} while (input);
	return 0;
}

小编想说的话

在实现通讯录的功能时,还有诸多不够完善的地方,以上通讯录系统是小编花好些时间一点点封装出来的,如有bug,欢迎在评论区指正!谢谢呀。

如果对你有帮助的话,请关注我呀!

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

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

相关文章

CY5.5-Dextran Cy5.5菁染料标记葡聚糖

产品名称&#xff1a;荧光Cy5.5菁染料标记葡聚糖 英文名称&#xff1a;CY5.5-Dextran 外观状态&#xff1a;紫色粉末 质量&#xff1a;90% 荧光波长&#xff1a;684nm-710nm 溶解性Dextran葡聚糖&#xff08;右旋糖酐Dextran&#xff09;,是一类具支链葡萄糖高聚物&#xff0c;…

系分 - 案例分析 - 需求分析(FAST分析)

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录案例分析 - 需求分析&#xff08;FAST分析&#xff09;FAST1 范围定义2 问题分析鱼骨图帕累托图制定系统改进目标3 需求分析定义需求PIECES方法4 逻辑设计5 决策分析6 物理设计和集成/构造和测试/安装和发…

考虑写出一个不抛异常的swap 函数

目录 一.标准库中的swap函数 二.针对于非模板类&#xff0c;设计全特化的std::swap() 三.针对模板类 四.合理使用using 五.swap成员函数不能抛出异常 六.swap函数总结 一.标准库中的swap函数 在C11中有move函数&#xff0c;它可以是一个左值变为右值&#xff0c;在许多场…

mybatis进阶

Mybatis的各种查询功能 MyBatis的各种查询功能&#xff1a; * 1、若查询出的数据只有一条 * a>可以通过实体类对象接收 * b>可以通过list集合接收 * c>可以通过map集合接收 * 结果&#xff1a;{password123456, sex男, id3, age23, email12345qq.com, usernameadmin} …

STM32 按键模块化

文章目录前言一、按键的原理图二、按键的GPIO配置总结前言 本篇文章将继续带大家学习模块化编程&#xff0c;今天主要给大家讲解按键的模块化。 一、按键的原理图 我们可以看到按键分别接到了板子的PE3和PE4引脚。 按键的具体原理这里我就不多讲了&#xff0c;大家可以看我之…

星光starfive2开发板的gpio使用

starfive2开发板是riscv平台不错的板子。 发展非常快。在starfive1的基础上有大量的改进和提升。 板子上的GPIO引脚定义是这样定义的&#xff1a;如下图所示 右侧6&#xff0c;8&#xff0c;10是调试用的串口&#xff0c;跟树莓派是一致的。 GPIO引脚的编号跟树莓派不一样。…

Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

Java多线程&#xff1a;多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题 每博一文案 常言道&#xff1a;“不经一事&#xff0c;不懂一人”。 一个人值不值得交往&#xff0c;在关键时候才能看得清。看过这样的一个…

ESP32设备驱动-HMC5883L磁场传感器驱动

HMC5883L磁场传感器驱动 1、HMC5883L介绍 霍尼韦尔 HMC5883L 是一款表面贴装、多芯片模块,专为低场磁场传感而设计,具有数字接口,适用于低成本罗盘和磁力计等应用。 HMC5883L 包括我们先进的高分辨率 HMC118X 系列磁阻传感器和一个 ASIC,该 ASIC 包含放大、自动消磁带驱动…

二叉平衡树之AVL树【手动实现代码】

目录 1、AVL树的概念 2、AVL树定义节点 3、AVL树的插入 4、AVL树的旋转 4.1、新节点插入较高左子树的左侧——右单旋 4.2、新节点插入较高右子树的右侧——左单旋 4.3、新节点插入较高左子树的右侧——左右双旋 4.4、新节点插入较高右子树的左侧——右左双旋 5、AVL树…

【LeetCode】1807. 替换字符串中的括号内容

1807. 替换字符串中的括号内容 题目描述 给你一个字符串 s &#xff0c;它包含一些括号对&#xff0c;每个括号中包含一个 非空 的键。 比方说&#xff0c;字符串 “(name)is(age)yearsold” 中&#xff0c;有 两个 括号对&#xff0c;分别包含键 “name” 和 “age” 。 你…

2023 年 The Sandbox 生态系统将迎来什么?

2022 年对于 The Sandbox 来说是多么美好的一年&#xff01;不仅是对我们的团队来说&#xff0c;对所有与我们建立业务的合作伙伴、才华横溢的创作者、工作室和代理机构来说也是这样。感谢大家让今年最喜欢的时刻成为现实&#xff0c;并成为这个社区的一部分。我们正在共同构建…

25w粉拿下1600w播放,仅用一周时间出圈B站!

2022年&#xff0c;B站举办了第四次跨年晚会《最美的夜》&#xff0c;艾薇儿登台唱起《Complicated》的瞬间&#xff0c;B站跨晚的直播间人气峰值到达3亿。在过去的一年里&#xff0c;平台持续变化带来亮眼成绩&#xff0c;月活用户破3亿、直播开通购物专区、竖屏模式增长播放等…

LaoCat带你认识容器与镜像(四【上】)

Dockerfile是实际项目生产中&#xff0c;比较常用的一个知识点&#xff0c;故也准备分成上下俩节来讲解。 本章内容 如何查询相关Dockerfile与Dockerfile基础命令介绍 本文实操全部基于Ubuntu 20.04 宿主机 > linux服务器本身 业务不断的扩充累积中&#xff0c;大多数企业应…

Python import自定义模块报错、自定义异常、字符串处理、截取

一、python import自定义的模块报错 问题现象&#xff1a;pycharm中运行一切正常&#xff0c;但是到命令行中&#xff08;cmd命令行或pycharm的Terminal窗口&#xff09;运行py文件&#xff0c;就会报错No module named xxx 问题原因&#xff1a; pycharm在每次运行时&#x…

【C进阶】指针的进阶

家人们欢迎来到小姜的世界&#xff0c;<<点此>>传送门 这里有详细的关于C/C/Linux等的解析博客&#xff0c;家人们赶紧冲鸭&#xff01;&#xff01;&#xff01; 客官&#xff0c;码字不易&#xff0c;来个三连支持一下吧&#xff01;&#xff01;&#xff01;关注…

祝大家兔年 新春快乐Happy new year

春节&#xff0c;也被称为农历新年。对于中国人来说&#xff0c;这是规模最大&#xff0c;最重要的传统节日。The Spring Festival is also called Chinese Lunar New Year. Being one of the traditional Chinese festivals, it is the grandest and most important festival …

Ue4 Insights的使用

1.运行UnrealInsights.exe 2.执行独立进程或者打包exe 这时会发现Insights自动创建并开始运行了一个Trace Sessions&#xff0c;持续记录到.utrace文件中 .utrace文件路径 3.也可以通过连接IP地址&#xff0c;获取到该计算机的UE程序。状态为LIVE实时 4.点击右下角Open按钮…

Redis客户端命令基础操作一

查看所有key 语法: keys * 是否存在key 语法: exists [key] 获取包含指定字符串的key 语法&#xff1a; keys *[字符串]* 设置key 语法&#xff1a;set [key] [value] 设置key 语法&#xff1a; setex 【key】【过期时间&#xff08;单位秒&#xff09;】【value】 key重…

时隔 20 年,这个编程语言再次“称王”

近日&#xff0c;全球知名的编程语言流行度排行榜网站 TIOBE 公布了 1 月编程指数信息。前三的编程语言是Python、C 和C&#xff0c;第四为Java&#xff0c;第五是C#。 TIOBE 的 2022 年度编程语言最终花落 C&#xff0c;也是它时隔 20 年后第二次赢得这一称号。 “年度编程语…

行云创新受邀出席2023中国(深圳)阿联酋(迪拜)经贸合作交流会

1月10日&#xff0c;2023中国&#xff08;深圳&#xff09;-阿联酋&#xff08;迪拜&#xff09;经贸合作交流会成功举办。本次交流会充分展示了深圳和迪拜两地城市营商环境和政策优势&#xff0c;并围绕科技创新、数字经济、港口物流等领域发展经验展开分享&#xff0c;来自两…