C语言实现简单的通讯录

1.功能总览

  • 菜单
  • 添加联系人
  • 显示已有联系人
  • 查找指定联系人
  • 删除指定联系人
  • 修改指定联系人
  • 对已有联系人进行排序

2.主函数的实现

int main()
{
	int input = 1;
	while (input)
	{
		Menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Add();
			break;
		case 2:
			Show();
			break;
		case 3:
			Search();
			break;
		case 4:
			Del();
			break;
		case 5:
			Modify();
			break;
		case 6:
			Sort();
			break;
		case 0:
			printf("exit\n");
			break;
		default:
			printf("error\n");
		}
	}
	return 0;
}
  • input接收用户输入信息
  • 由不同函数完成指定功能
  • 当输入为0退出程序

使用了库函数,需引用头文件<stdio.h>

3.菜单的创建

在菜单中,需指引用户输入内容以便进入特定函数:

void Menu()
{
	printf("********************************\n");
	printf("***** 1.Add         2.Show *****\n");
	printf("***** 3.Search      4.Del  *****\n");
	printf("***** 5.modify      6.sort *****\n");
	printf("*****        0.exit        *****\n");
	printf("********************************\n");
}

效果:
在这里插入图片描述

4.通讯录的建立与初始化

4.1建立

一个联系人包含不同类型的信息,所以我使用了结构体来储存信息:

struct Peo
{
	char name[NAME_MAX];
	int age;
	char tele[TELE_MAX];
};

这里创建了一个结构体类型Peo,可用于储存联系人的姓名、年龄、电话。
一个通讯录应包含多个联系人信息,因此用数组储存,而为了完成后续操作,我们需要记录已有联系人的数量,因此可以再创建一个结构体

struct Contact
{
	struct Peo peo[MAX];
	int num;
};

此时可在主函数中创建通讯录:

struct Contact con;

注:由于后续数据可能修改,因此我们使用了define

#define MAX 100
#define NAME_MAX 20
#define TELE_MAX 12

MAX指最多存储的联系人数量
NAME_MAX指联系人名字最大长度
TELE_MAX指联系人电话号码最长长度

4.2 初始化

虽然创建变量后会自动初始化为0,但我们仍可以创建一个函数来初始化通讯录:

void Init(struct Contact* p)
{
	assert(p);
	p->num = 0;
	memset(p->peo, 0, sizeof(p->peo));
}

此时可在主函数中初始化通讯录:

Init(&con);

注:使用了assert断言,需引用头文件<assert.h>

5.具体功能

5.1添加联系人

void Add(struct Contact* p)
{
	assert(p);
	if (p->num == MAX)
	{
		printf("已满\n");
		return;
	}
	printf("名字:");
	scanf("%s", p->peo[p->num].name);
	printf("年龄:");
	scanf("%d", &p->peo[p->num].age);
	printf("电话:");
	scanf("%s", p->peo[p->num].tele);
	p->num++;
	printf("添加成功\n");
}

注:需判断通讯录是否已满,以免溢出

5.2显示已有联系人

void Show(const struct Contact* p)
{
	assert(p);
	printf("%-*s\t%-*s\t%-*s\n", NAME_MAX, "名字", 4, "年龄", TELE_MAX, "电话");
	for (int i = 0; i < p->num; i++)
	{
		printf("%-*s\t", NAME_MAX, p->peo[i].name);
		printf("%-*d\t", 4, p->peo[i].age);
		printf("%-*s\n", TELE_MAX, p->peo[i].tele);
	}
}

效果:
在这里插入图片描述

关于printf的用法可以看看我写的printf函数详细介绍和使用技巧

5.3查找指定联系人

void Search(const struct Contact* p)
{
	assert(p);
	printf("输入要查找的名字:");
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);
	int tgt = find_by_name(p, name);
	if (tgt == -1)
	{
		printf("要查找的名字不存在\n");
		return;
	}
	printf("%-*s\t%-*s\t%-*s\n", NAME_MAX, "名字", 4, "年龄", TELE_MAX, "电话");
	printf("%-*s\t", NAME_MAX, p->peo[tgt].name);
	printf("%-*d\t", 4, p->peo[tgt].age);
	printf("%-*s\n", TELE_MAX, p->peo[tgt].tele);
}

在查找,删除,修改中我们都需按照名字查找指定联系人,因此可以再分装一个函数find_by_name:

static int find_by_name(const struct Contact* p, char* name)
{
	assert(p);
	for (int i = 0; i < p->num; i++)
	{
		if (strcmp(name, p->peo[i].name) == 0)
		{
			return i;
		}
	}
	return -1;
}

找到了返回下标,找不到返回-1

5.4删除指定联系人

void Del(struct Contact* p)
{
	assert(p);
	printf("输入要删除的名字:");
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);
	int tgt = find_by_name(p, name);
	if (tgt == -1)
	{
		printf("要删除的名字不存在\n");
		return;
	}
	for (int i = tgt; i < p->num - 1; i++)
	{
		//memmove(p->peo + i, p->peo + i + 1, sizeof(p->peo[0]));
		p->peo[i] = p->peo[i + 1];
	}
	p->num--;
	printf("删除成功\n");
}

在修改的操作中,我使用的方法是将修改人之后的人依次提前:
最开始我用的memmove:

memmove(p->peo + i, p->peo + i + 1, sizeof(p->peo[0]));

后来发现可以直接赋值:

p->peo[i] = p->peo[i + 1];

5.5修改指定联系人

void Modify(struct Contact* p)
{
	assert(p);
	printf("输入要修改的名字:");
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);
	int tgt = find_by_name(p, name);
	if (tgt == -1)
	{
		printf("要修改的名字不存在\n");
		return;
	}
	printf("名字:");
	scanf("%s", p->peo[tgt].name);
	printf("年龄:");
	scanf("%d", &p->peo[tgt].age);
	printf("电话:");
	scanf("%s", p->peo[tgt].tele);
}

5.6对已有联系人进行排序

int sort_by_name(const void* n1, const void* n2)
{
	return strcmp(((struct Peo*)n1)->name, ((struct Peo*)n2)->name);
}
void Sort(struct Contact* p)
{
	assert(p);
	qsort(p->peo, p->num, sizeof(p->peo[0]), sort_by_name);
	printf("排序成功\n");
}

这里直接用的qsort,并使用strcmp按照名字排序

6.可优化的点

更多的功能

联系人的最大数量不能自定义
可动态内存分配,如:
使用malloc初始化:

p->peo = (Peo*)calloc(3,sizeof(Peo));

使用realloc增容;

Peo* p = (Peo*)realloc(p->peo, (p->capacity + 2) * sizeof(Peo));

程序运行在内存上,一旦退出存储的信息将全部清空
可加入文件的使用


希望本篇文章对你有所帮助!
本人仅仅是个C语言初学者,如有任何意见,欢迎各位提出!


相关文章:
C语言指针详解-上
C语言指针详解-下

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值