C语言初阶之实现静态通讯录详细思路及示例代码

前言

      终于有时间来写关于C语言实现通讯录功能这一系列的博客了,冲冲冲,话不多说!

目录

1.整体项目结构及对应文件的功能

2.基础菜单,输入及结构体和编写

3.通讯录具体功能(初始化,增删查改,升序排列,显示通讯录)实现逻辑

(1)初始化通讯录

(2)添加联系人

(3)删除联系人

(4)根据姓名查询指定联系人

(5)根据姓名修改指定联系人

(6)对通讯录信息按姓名排序

(7)显示通讯录信息


1.整体项目结构及对应文件的功能

          整体项目结构如下:

           对应文件的功能描述:

           1)contact.h :有关该项目所需的头文件引用,所需用到的数值定义,结构体及所需函数声明

           2)contact.c :相关函数实现(用" "引用自定义contact.h头文件)

           3)test.c :测试通讯录功能(用" "引用自定义contact.h头文件)

项目准备工作就完成啦!!!让我们继续下一步


2.基础菜单,输入及结构体和编写

     首先咱们得先单独写个菜单,方便用户使用通讯录。这个没什么思路,单纯打印功能。如下:

//菜单
void menu() {
	printf("/**********  欢迎打开通讯录 **********/\n");
	printf("/**** 0.exit 1.add  2.del  3.sech ****/\n");
	printf("/******* 4.mod  5.sort 6.show  *******/\n");
}

这里我们使用input变量让用户进行操作选择,do...while()循环中循环体至少执行一次,而用户进行至少一次操作选择,更加符合我们需求,所以我们可以使用do...while()循环+switch分支实现基本操作选择,然后在对应的分支中实现单个功能就好了。如下代码+注释:

int main() {
    //控制操作选择
	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);
	return 0;
}

大概的用户交互就差不多完成了,这时候我们就要想有关通讯录结构体该怎么声明呢?

大家应该都知道通讯录中存储的是一个个联系人的信息(姓名,年龄,家庭住址,电话等等),所以一个通讯录由多个联系人信息组成,我们可以这样定义:

//所需用到数值,方便后期不用到处修改
#define DataMaxSize 100
#define NameSize 10
#define AddressSize 20
#define PhoneSize 11
#define SexSize 5

//个人信息,将structPersonInfo重新定义为Person(也可以不重新定义,我这里是为了方便)
typedef struct PersonInfo {
	char name[NameSize];//姓名
	int age;//年龄
	char address[AddressSize];//家庭住址
	char phoneNumber[PhoneSize];//电话
	char sex[SexSize];//性别
}Person;

//通讯录
typedef struct Contact {
	Person data[DataMaxSize];
	int length;
}Contact;

这样我们就可以使用Contact结构体了。


3.通讯录具体功能(初始化,增删查改,升序排列,显示通讯录)实现逻辑

注:大家不太熟悉逻辑的尽量实现一个功能就测试一下(刚开始我也是这样),这里我就不一个个去测试了,大家可以先把思路在草稿纸上画出来然后再对应实现。最后我会总体给大家测试一遍。

(1)初始化通讯录

在用户进行操作选择之前,我们必须准备一个通讯录的结构体变量并把它初始化完毕后,才可以对其进行各种操作。无返回值,参数只需要一个通讯录结构体指针类型(因为调用初始化通讯录函数之后,会改变结构体中的值,所以这里我们传通讯录结构体指针)的参数就好了,如下:

//在contact.h中的函数声明
void initContact(Contact* con);

//在contact.c中的具体函数实现
//初始化通讯录
void initContact(Contact* con) {
	//con不能为空,记得引用头文件<assert.h>
	assert(con);
	con->length = 0;//通讯录中联系人个数为0
    //引用头文件<stdlib.h>
	memset(con->data, 0, sizeof(Person) * DataMaxSize);//所有初值都为0
}

最后在用户进行操作选择之前,准备一个通讯录结构体变量contact并调用initContact函数把它初始化就好了。

(2)添加联系人

准备好一个空的通讯录之后,我们总得往通讯录里添加联系人吧?怎么添加呢?通讯录中可以存放DataMaxSize多个联系人,所以我们直接将用户输入的联系人信息赋值进对应下标的结构体成员变量中,然后通讯录中联系人个数+1。如下:

//在contact.h中声明AddContact函数
void AddContact(Contact* con);
//在Contact.c函数中实现该函数
//添加联系人
void AddContact(Contact* con) {
	//con不能为空
	assert(con);
	printf("请输入所添加联系人的姓名:>");
	scanf("%s", con->data[con->length].name);
	printf("请输入所添加联系人的年龄:>");
	scanf("%d", &con->data[con->length].age);
	printf("请输入所添加联系人的地址:>");
	scanf("%s", con->data[con->length].address);
	printf("请输入所添加联系人的电话:>");
	scanf("%s", con->data[con->length].phoneNumber);
	printf("请输入所添加联系人的性别:>");
	scanf("%s", con->data[con->length].sex);
	con->length++;//通讯录联系人个数+1
	printf("成功添加联系人\n");
}

接下来直接在分支1调用就好了。

(3)删除联系人

当通讯录中某个人不会再联系的时候,我们会选择把它删除。这里就跟顺序表删除操作类型,不过顺序表中存放的是结构体类型的变量。我们直接将要删除结构体变量后面的元素一个个往前移动就好了。但是记得单独写一个函数用于查找该结构体变量哦,如果通讯录中没有该联系人,我们就无需删除,直接提示用户要删除的联系人不存在就好了。如下:

//在contact.h中声明DelContact函数
void DelContact(Contact* con);

//在contact.c中实现该函数
//查找指定联系人
int FindPerson(Contact* con, char* Name) {
	//con不能为空
	assert(con);
	for (int i = 0; i < con->length; i++) {
		if (0 == strcmp(con->data[i].name, Name)) return i;
	}
	return -1;
}

//删除联系人
void DelContact(Contact* con) {
	//con不能为空
	assert(con);
	printf("请输入所需删除联系人的姓名:>");
    //查找该联系人是否存在
	char Name[NameSize] = "";
	scanf("%s", Name);
    //当下标为-1,也就是ret=-1则该通讯录中不存在该联系人
	int ret = FindPerson(con, Name);
	if (ret>=0) {
		int i = 0;
        //从ret下标+1开始地方往前将该位置联系人覆盖
		for (i = ret; i < con->length-1; i++) {
			con->data[i] = con->data[i + 1];
		}
		printf("删除指定联系人成功\n");
        //联系人个数-1
		con->length--;
	}else printf("所需删除的联系人不存在\n");
}

然后在分支2中调用就好了。

(4)根据姓名查询指定联系人

有时候用户想知道自己手机通讯录中有没有此联系人,这时候就要用到通讯录的查询功能。我们这里通过名字去查询指定联系人,涉及到字符串比较(strcmp)对这个函数不明白的可以看看我另一篇关于str的函数的博客:模拟实现C语言字符串(str)及各种类型数据(mem)操作的库函数_Crystal_bit的博客-CSDN博客

和删除差不多的思路,都要先调用FindPerson确认通讯录中存在该联系人,然后通过返回的下标找到对应联系人。具体代码实现及注释:

//在contact.h中声明SearchContact函数
//查询指定联系人
void SearchContact(Contact* con);

//然后在contact.c中实现该函数
//查找联系人
void SearchContact(Contact* con) {
	//con不能为空
	assert(con);
	printf("请输入你所需查找联系人的姓名:>");
	char Name[NameSize] = "";
	scanf("%s", Name);
	int ret = FindPerson(con, Name);
	if (ret >= 0) {
        //为了打印的好看一些采用占位符
		printf("%-10s %-4d %-20s %-11s %-5s\n", con->data[ret].name, con->data[ret].age, con->data[ret].address, con->data[ret].phoneNumber, con->data[ret].sex);
        printf("查找成功!\n");
	}else printf("所需查找的联系人不存在\n");
	
}

这里实现的是分支3的功能。

(5)根据姓名修改指定联系人

联系人的信息可能会因为某些原因需要改变,比如电话号码修改了啊,联系人改名了啊等等。差不多的思路(通过名字找到对应联系人的下标->然后将对应下标的个人信息修改就好了),如下:

//contact.h中声明
//修改指定联系人
void ModifyContact(Contact* con);

//contact.c中实现
//修改联系人
void ModifyContact(Contact* con) {
	//con不能为空
	assert(con);
	printf("请输入你所需修改联系人的姓名:>");
	char Name[NameSize] = "";
	scanf("%s", Name);
    //查找联系人存不存在
	int ret = FindPerson(con, Name);
	if (ret >= 0) {
		printf("请输入所修改联系人的姓名:>");
		scanf("%s", con->data[ret].name);
		printf("请输入所修改联系人的年龄:>");
		scanf("%d", &con->data[ret].age);
		printf("请输入所修改联系人的地址:>");
		scanf("%s", con->data[ret].address);
		printf("请输入所修改联系人的电话:>");
		scanf("%s", con->data[ret].phoneNumber);
		printf("请输入所修改联系人的性别:>");
		scanf("%s", con->data[ret].sex);
        printf("修改成功\n");
	}else printf("所需修改的联系人不存在\n");
	
}

分支4的功能。

(6)对通讯录信息按姓名排序

一般通讯录都会按姓名首字母大小写进行联系人的排序。在不调用查找通讯录功能时,能方便我们更快查找对应的联系人。这里会涉及到库函数qsort的使用,推荐学习网站:qsort - C++ Reference (cplusplus.com)

具体实现代码及注释:

//contact.h声明
//对通讯录信息按姓名排升序
void SortContact(Contact* con);

//contact.c实现
//字符串比较函数
int cmp(const void* s1,const void* s2) {
	return strcmp(((Person*)s1)->name , ((Person*)s2)->name);
}

//对通讯录信息按姓名排升序
void SortContact(Contact* con) {
	//con 不能为空
	assert(con);
	qsort(con->data, con->length, sizeof(struct PersonInfo), cmp);
	printf("成功按姓名排升序\n");
}

分支6的功能。

(7)显示通讯录信息

这个逻辑很简单,就是整个通讯录的信息打印就好了。如下:

//contact.h声明
//显示通讯录信息
void ShowContact(Contact* con);

//contact.c实现
//显示通讯录信息
void ShowContact(Contact* con) {
	//con不能为空
	assert(con);
    //打印信息列名,设置占位符
	printf("%-10s %-4s %-20s %-11s %-5s\n", "姓名", "年龄", "地址", "电话", "性别");
	for (int i = 0; i < con->length; i++) {
		printf("%-10s %-4d %-20s %-11s %-5s", con->data[i].name, con->data[i].age, con->data[i].address, con->data[i].phoneNumber, con->data[i].sex);
		printf("\n");
	}
}

最后,咱们可以整体测试一下:

添加功能:

显示整个通讯录功能:

 删除指定联系人功能:

查找指定联系人:

对通讯录联系人进行排序(升序):

修改指定联系人信息:

 后面会在此通讯录基础上进行优化。大家加油~~~

 今日分享完毕~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值