用C语言写一个简单的通讯录(静态版)

前言

在实现通讯录前,我们需先考虑这个通讯录应该具备哪些功能,以下是我写的通讯录功能预览。

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 排序通讯录联系人

代码实现

写通讯录时,我们需要创建三个文件,方便代码的调试和修改。

  1. test.c 测试整个通讯录的逻辑
  2. contact.h 通讯录相关功能的函数声明
  3. contact.c 通讯录相关功能的函数实现

test.c

我们先创建一个菜单供用户选择

static void menu()
{
    
    
	printf("******************************\n");
	printf("****   1.add       2.del  ****\n");
	printf("***    3.search    4.modfy****\n");
	printf("***    5.show      6.sort  ***\n");
	printf("***    0.exit              ***\n");
	printf("******************************\n");
}

然后创建一个枚举类型对应菜单的数据,方便使用switch时看过去更明了。

enum Option
{
    
    
	EXIT,		//退出
	ADD,		//增加
	DEL,		//删除
	SRARCH,		//查找
	MODFY,		//修改
	SHOW,		//显示
	SORT		//排序
};

然后在main函数里面创建一个通讯录的变量(这里的结构体我在contact.h里面定义了)和大概框架给写好。

int main()
{
    
    

	int input = 0;
	struct Contact con;//创建了一个描述通讯录的变量
	InitContact(&con);//初始化通讯录
	do
	{
    
    
		menu();//菜单
		printf("请选择:");
		scanf("%d",&input);
		switch (input)
		{
    
    
		case EXIT:
			printf("退出通讯录\n");
			break;
		case ADD:
			Addcontact(&con);//增加联系人
			break;
		case DEL:
			DelContact(&con);//删除联系人
			break;
		case SRARCH:
			SrarchContact(&con);//查找联系人
			break;
		case MODFY:
			ModfyContact(&con);//修改通讯录
			break;
		case SHOW:
			ShowCotact(&con);//显示通讯录
			break;
		case SORT:
			SortContact(&con);//排序通讯录
			break;
		default:
			printf("选择错误,请重新选择\n");
		}
	} while (input);
	return 0;
}

contact.h

在创建的头文件里把需要的头文件加上,这样其他两个.c文件只需要声明我们自己创建的头文件就可以使用库函数了,然后创建一个结构体来描述一个联系人的信息,用**#define**定义常量,可以更方便的修改。
再创建一个结构体,里面创建一个结构体数组,数组里面存放1000个联系人的信息,再创建一个整型变量,用来记录当前存放了多少个人的信息。

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

#define NAME_MAX 20  //名字
#define SEX_MAX 5	 //性别
#define TELE_MAX 12	 //电话
#define ADDR_MAX 30	 //地址
#define DATA_MAX 1000//人数

struct PeoInfo  //描述一个人信息的结构体
{
    
    
	char name[NAME_MAX];//名字
	int age;//年龄
	char sex[SEX_MAX];//性别
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
};
//通讯录的结构体
struct Contact
{
    
    
	struct PeoInfo data[DATA_MAX];
	int sz;//记录通讯录中里有几个人的信息
};

接下来就是我们需要实现的功能函数声明。

void InitContact(struct Contact* con);//初始化通讯录

void Addcontact(struct Contact* con);//增加联系人

void ShowCotact(const struct Contact* con);//显示通讯录

void DelContact(struct Contact* con);//删除联系人

void SrarchContact(struct Contact* con);//查找联系人

void ModfyContact(struct Contact* con);//修改通讯录

void SortContact(struct Contact* con);//排序通讯录

contact.c

初始化通讯录

在这里插入图片描述
我们创建好数组后其实里面的数值都是些随机数,我们需要将记录联系人的整型变量置0,然后把数组的元素全部置0,这里我用的是memset库函数。

void InitContact(struct Contact* con)
{
    
    
	con->sz = 0;
	//memset -设置内存的函数
	memset(con->data, 0, sizeof(con->data));
}

增加联系人

增加联系人之前我们需要判断通讯录是否满了,如果满了就无法添加,这里#define定义的常量就用上了。没满就开始添加数据,记录联系人的变量刚好可以对应上添加数据数组的下标,每次添加完成记录联系人的变量+1。

void Addcontact(struct Contact* con)
{
    
    
	if (con->sz == DATA_MAX)
	{
    
    
		printf("通讯录已满,无法继续添加\n");
	}
	else
	{
    
    
		
		printf("添加联系人\n");
		printf("请输入姓名:");
		scanf("%s", con->data[con->sz].name);
		printf("请输入年龄:");
		scanf("%d", &con->data[con->sz].age);
		printf("请输入性别:");
		scanf("%s", con->data[con->sz].sex);
		printf("请输入电话:");
		scanf("%s", con->data[con->sz].tele);
		printf("请输入地址:");
		scanf("%s", con->data[con->sz].addr);
		con->sz++;
		printf("添加成功\n");
	}
}

运行示例
在这里插入图片描述

显示联系人

添加联系人后我们想知道是否添加成功了,这时就可以写显示联系人的功能来测试是否添加成功。显示通讯录只需要遍历一遍数组打印出来就行了。

void ShowCotact(const struct Contact* con)
{
    
    
	int i = 0;
	printf("显示通讯录\n");
	if (con->sz == 0)
	{
    
    
		printf("通讯录为空\n");
		return;
	}
	printf("%-15s\t%-5s\t%-5s\t%-12s\t%-20s\t\t\n","姓名","年龄","性别","电话","地址");
	for (i = 0; i < con->sz; i++)
	{
    
    
		printf("%-15s\t", con->data[i].name);
		printf("%-5d\t", con->data[i].age);
		printf("%-5s\t", con->data[i].sex);
		printf("%-12s\t", con->data[i].tele);
		printf("%-20s\t\n", con->data[i].addr);
	}
}

运行示例
在这里插入图片描述

删除联系人

在删除联系人之前我们要先找那个联系人才能删除,如果找不到则无法删除,这里我创建了一个查找的函数,如果找到了就返回下标,如果找不到就返回-1。

//查找
int FindByName(struct Contact* con, char name[])//找到返回下标,没找到返回-1
{
    
    
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
    
    
		if (strcmp(con->data[i].name, name) == 0)
		{
    
    
			return i;
		}
	}
	return -1;
}

另外,在删除函数里面,我增加了一个菜单,可以选择删除指定联系人或者清空通讯录,如果删除值定联系人则记录联系人个数的变量要-1,清空则直接置0。

void DelMeum()
{
    
    
	printf("***************************\n");
	printf("****  1.删除指定联系人  ****\n");
	printf("****  2.清空通讯录      ****\n");
	printf("***************************\n");
}

void DelContact(struct Contact* con)//删除联系人
{
    
    
	char name[NAME_MAX] = {
    
     0 };
	printf("删除联系人\n");
	if (con->sz == 0)
	{
    
    
		printf("通讯录为空\n");
	}
	else
	{
    
    
		int input = 0;
		DelMeum();
		printf("请选择:>");
		scanf("%d", &input);
		if (input == 1)
		{
    
    
			printf("请输入要删除人的名字:");
			scanf("%s", name);
			//查找
			int pos = FindByName(con, name);//找到返回下标,没找到返回-1
			if (pos == -1)
			{
    
    
				printf("要删除的人不存在\n");
			}
			else
			{
    
    
				//删除
				int j = 0;
				for (j = 0; j < con->sz - 1; j++)
				{
    
    
					con->data[j] = con->data[j + 1];
				}
				con->sz--;
				printf("删除成功\n");
			}
		}
		else if (input == 2)
		{
    
    
			memset(con->data, 0, sizeof(struct PeoInfo));
			con->sz = 0;
			printf("清空通讯录成功\n");
		}

	}

}

运行示例
在这里插入图片描述

查找联系人

查找联系人,刚好利用了上面写的查找代码,找到就打印出来,没找到就输出被查找人不存在。

void SrarchContact(struct Contact* con)//查找联系人
{
    
    
	printf("查找联系人\n");
	char name[NAME_MAX] = {
    
     0 };
	printf("请输入要查找人的姓名:");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos == -1)
	{
    
    
		printf("要查找的人不存在\n");
	}
	else
	{
    
    
		printf("%-15s\t%-5s\t%-5s\t%-12s\t%-20s\t\t\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%-15s\t", con->data[pos].name);
		printf("%-5d\t", con->data[pos].age);
		printf("%-5s\t", con->data[pos].sex);
		printf("%-12s\t", con->data[pos].tele);
		printf("%-20s\t\n", con->data[pos].addr);
	}
}

运行示例
在这里插入图片描述

修改联系人

修改联系人也用到了查找函数,找到了就进行修改,找不到就输出通讯录没有该联系人。

void ModfyContact(struct Contact* con)//修改通讯录
{
    
    
	char name[NAME_MAX] = {
    
     0 };
	printf("修改联系人\n");
	printf("请输入要修改的联系人名字:");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos == -1)
	{
    
    
		printf("通讯录没有该联系人\n");
	}
	else
	{
    
    
		printf("请输入要修改的姓名:");
		scanf("%s", con->data[pos].name);
		printf("请输入要修改的年龄:");
		scanf("%d", &con->data[pos].age);
		printf("请输入要修改的性别:");
		scanf("%s", con->data[pos].sex);
		printf("请输入要修改的电话:");
		scanf("%s", con->data[pos].tele);
		printf("请输入要修改的地址:");
		scanf("%s", con->data[pos].addr);
		printf("修改成功\n");
	}
}

运行示例
在这里插入图片描述

排序联系人

排序联系人可以根据用户选择按年龄排序还是按名字排序,我这里用的是库函数qsort排序的。

static void menu()
{
    
    
	printf("***************************\n");
	printf("****       1.name      ****\n");
	printf("****       2.age       ****\n");
	printf("***************************\n");
}

enum Choice	//选择
{
    
    
	NOTSORT,
	NAME,
	AGE
};

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

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

void SortContact(struct Contact* con)//排序通讯录
{
    
    
	int input = 0;
	menu();
	printf("请选择您需要的排序方式:>");
	scanf("%d", &input);
	switch (input)
	{
    
    
	case NAME:
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
		printf("按名字排序成功\n");
		break;
	case AGE:
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
		printf("按年龄排序成功\n");
		break;
	case NOTSORT:
		printf("取消排序");
		break;
	default:
		printf("选择错误\n");
		break;
	}
}

运行示例
在这里插入图片描述
在这里插入图片描述
以上就是通讯录所需功能实现的全部代码

总结

静态版通讯录的空间是一开始就给定的,如果空间满了又不能增加空间,而如果使用的空间并没有那么大则又造成了浪费空间的尴尬处境,后续我将会写一篇动态版的通讯录,动态版通讯录能解决这种尴尬情况,谢谢各位观看!

猜你喜欢

转载自blog.csdn.net/qq_45270751/article/details/115312805