前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言通讯录功能的实现

C语言通讯录功能的实现

作者头像
黎鹤舞
发布2024-03-19 15:13:53
710
发布2024-03-19 15:13:53
举报

C语言通讯录功能的实现

一、项目需求:

我们需要一个通讯录,可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。

并且在通讯录中要求实现下述功能:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 以名字排序所有联系人

二、模块化代码

在代码编辑中,为了避免代码过于冗长,也为了便于后续功能的修改。我们一般将代码分多成多个模块。

建立如下文件

contact.h (头文件,用来引入库函数,存放声明) contact.c (实现通讯录每个部分的功能) test.c (主函数,用于测试通讯录功能是否成功实现)

注意:.c文件需要使用自定义头文件的声明,要在最前端引入

代码语言:javascript
复制
#include "contact.h"		//自定义头文件需要用"" 而不是<>

三、整体思路

1.创建结构体类型

我们需要一个通讯录,可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。

这里我们就需要建立一个结构体,描述这信息。

代码语言:javascript
复制
#define nameMax  15
#define sexMax 5
#define numberMax 15
#define addrMax 20

//结构体定义,表示通讯录的每一页,包含了一个联系人的所有信息
typedef struct inform
{
	char name[nameMax];
	char sex[sexMax];
	int age;
	char number[numberMax];
	char addr[addrMax];

}inform;

这里我使用了typedef关键字关于typedef:

typedef 是类型重命名 与struct 结构体 连起来使用,可以让struct 在定义完成后使用{}后的名字作为类型名。

一个人的通讯录信息结构体已经已经建立好了。现在我们需要一个结构体数组,来存放1000个人的信息,同时出于功能的需求,我们还要知道通讯录已经存储了多少个人的信息,所以我们再建立一个通讯录本结构体。

代码语言:javascript
复制
//定义整本通讯录,能够存储100个人的信息和其通讯录所在位置
typedef struct Contact
{
	inform date[1000];
	int num;
}Contact;

这里使用了结构体嵌套,结构体内部元素是一个结构体数组;

2.建立循环

首先我们要有一个菜单,向使用者展示通讯录的功能,并且提示他们可以输入对应的字符来进行相对应的功能。

并且这是一个循环,可以不断输入来选择功能。

代码语言:javascript
复制
void meanu()
{
	printf("********************************\n");
	printf("***   1. add		2.del	 ***\n");
	printf("***   3.search		4.modify ***\n");
	printf("***   5.show		6.sort	 ***\n");
	printf("***   0.exit				 ***\n");
	printf("********************************\n");
}
int main()
{
	int input = 0;
	do 
	{
		meanu();
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
			break;
		case 7:
			break;
		case 0:
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

建立了菜单循环,下面就要开始往每一个选择加入不同的功能。

但是我们在编写程序1,2,3,4…这样的数字,经常需要回头查看设置的功能是什么

我们可以使用枚举常量

关于枚举常量 枚举常量有点类似于宏定义#define,是将一系列名字定义为常量。其默认赋值顺序是从0开始,逐个+1 缺点:只能赋值为整形常量。

代码语言:javascript
复制
enum
{
	Exit,
	Add,
	Del,
	Search,
	Modify,
	Show,
	Sort,
};

写在contact.h头文件中

那么循环可以更改为上述名字。

我们在将exit功能和default功能实现一下。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

void meanu()
{
	printf("**********************************\n");
	printf("***   1. add        2.del      ***\n");
	printf("***   3.search      4.modify   ***\n");
	printf("***   5.show        6.sort     ***\n");
	printf("***   0.exit                   ***\n");
	printf("**********************************\n");
}
int main()
{
	int input = 0;
	do 
	{
		meanu();
		scanf("%d", &input);
		switch (input)
		{

		case Add:
			break;
		case Del:
			break;
		case Search:
			break;
		case Modify:
			break;
		case Show:
			break;
		case Sort:
			break;
		case Exit:
			printf("退出成功!!!\n");
			break;
		default:
			printf("您输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

注意!!!

初始化结构体之后,结构体的初始值 !=0,需要主动初始化(赋予空白内容)

并且结构体的函数传递必须为 传址传递 否则无法修改结构体内部的信息。

代码语言:javascript
复制
//结构体初始化函数
void initContact(Contact* p)
{
	//先判断穿过来的指针是否为空
	assert(p);
	p->num = 0;
	memsent(p->date,0,sizeof(p->date));
}

利用memsent函数 可以快速的将date数组里的内容进行初始化

3.各个功能的实现
(1)add()增添联系人
代码语言:javascript
复制
//新增联系人
void add(Contact* p)
{
	assert(p);
	//判断通讯录是否已经未满,如果num = 100则无法添加
	if (1000 == p->num)
	{
		printf("通讯录已满,无法进行添加\n");
		return ;
	}

	printf("请输入姓名:\n");
	scanf("%s",p->date[p->num].name);
	printf("请输入性别:\n");
	scanf("%s",p->date[p->num].sex);
	printf("请输入年龄:\n");
	scanf("%d",&(p->date[p->num].age));
	printf("请输入号码:\n");
	scanf("%s",p->date[p->num].number);
	printf("请输入地址:\n");
	scanf("%s",p->date[p->num].addr);
	p->num += 1;
	printf("联系人信息已添加完成!\n");
}

注意:

在新增联系人的时候,我们首先需要判断通讯录是否为满。如果为满则跳出并给出提示。

(2)show()显示通讯录信息
代码语言:javascript
复制
void show(Contact* p)
{
	assert(p);
	if (0 == p->num)
	{
		printf("没有可以显示的信息!\n");
		return ;
	}
	printf("%-15s %-5s %-5s %-15s %-20s\n","姓名","性别","年龄","电话","地址");
	int i = 0;

	for (i = 0; i < p->num; i++)
	{
		printf("%-15s %-5s %-5d %-15s %-20s\n",
			p->date[i].name, p->date[i].sex, p->date[i].age, p->date[i].number, p->date[i].addr);
	}
}

如果结构体都为0,则不需要打印。

(3)search查找通讯录信息

这里我们考虑的是按人名进行查找,由于后面的删除功能也需要进行按人名进行查找,所以先自定义一个按名索引函数

按名索引 让用户输入要进行操作的联系人的名字,通过strcmp函数比较是否相同 如果相同 return 其所在位置 如果不同 return -1

代码语言:javascript
复制
//构建一个内部函数,用于实现按名查找
int findName(Contact* p , char name[])
{
	assert(p);
	int i = 0;
	//遍历通讯录,找到了返回是第几个联系人
	for (i = 0; i < p->num; i++)
	{
		if (0 == strcmp(p->date[i].name, name))
			return i;
	}
	//如果找不到返回 -1
	return -1;
}

由于这个函数仅供该文件下的函数调用,所以不需要在头文件中声明也是可以的。

有了按名索引功能,搜索功能就简单了许多:

但是仍有需要注意的是:

  • 首先通讯里要保证有内容可查,如果没有则进行提示
  • 查找到后要进行打印(同show函数的功能)
代码语言:javascript
复制
//查找联系人的函数
void search(Contact* p)
{
	assert(p);
	char name[nameMax] ;
	if (p->num == 0)
	{
		printf("通讯录无数据可供查找!\n");
		printf("请从新进行操作!\n");
		return;
	}
	printf("请输入你要查找人的姓名:");
	scanf("%s",name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}
	printf("查找成功:\n");
	//显示查找的人的信息:
	printf("%-15s %-5s %-5s %-15s %-20s\n",
		"姓名", "性别", "年龄", "电话", "地址");
	printf("%-15s %-5s %-5d %-15s %-20s\n",
		p->date[pos].name, 
		p->date[pos].sex,
		p->date[pos].age,
		p->date[pos].number,
		p->date[pos].addr);
}
(4)del删除通讯录信息功能

删除通讯录是建立在查找功能之上的,先对输入的人名进行按名索引,随换把要删除的信息进行覆盖,让后面的每一个元素都向前移动1位

计算机信息删除的本质,其实也就是把不可修改的区域进行覆盖,使其变为可修改的区域。

代码如下:

代码语言:javascript
复制
//删除联系人
void del(Contact* p)
{
	assert(p);
	char name[nameMax];

	if (p->num == 0)
	{
		printf("通讯录为空!!!\n");
		printf("请从新进行操作!\n");
		return;
	}

	printf("请输入你要删除人的姓名:");
	scanf("%s", name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}
	
	//删除
	int i = 0;
	for (i = pos; i < p->num; i++)	
	{
		p->date[i] = p->date[i + 1];	//同类型之间的变量可以进行赋值操作
	}
	p->num--;							//防止数组越界
	printf("清楚完毕!!\n");
}
(5)modify修改信息功能
代码语言:javascript
复制
//对通讯录信息进行修改
void modify(Contact* p)
{
	assert(p);
	char name[nameMax];

	if (p->num == 0)
	{
		printf("通讯录为空!!!\n");
		printf("请从新进行操作!\n");
		return;
	}

	printf("请输入你要修改人的姓名:");
	scanf("%s", name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}

	//修改:
	int choose = 0;
	do 
	{
		//选择修改菜单:
		printf("………………………………………………\n");
		printf("***   1.姓名        2.性别       ***\n");
		printf("***   3.年龄        4.号码       ***\n");
		printf("***   5.地址                     ***\n");
		printf("***   0.退出修改                 ***\n");
		printf("………………………………………………\n");

		printf("请输入你要修改的选项:>");
		scanf("%d", &choose);

		switch (choose)
		{
		case 1:
			printf("请输入修改后的姓名:");
			scanf("%s",p->date[pos].name);
			break;
		case 2:
			printf("请输入修改后的性别:");
			scanf("%s",p->date[pos].sex);
			break;
		case 3:
			printf("请输入修改后的年龄:");
			scanf("%d",p->date[pos].age);
			break;
		case 4:
			printf("请输入修改后的号码:");
			scanf("%s",p->date[pos].number);
			break;
		case 5:
			printf("请输入修改后的地址:");
			scanf("%s",p->date[pos].addr);
			break;
		case 0:
			printf("修改成功!!!\n");
			break;
		default :
			printf("非法字符输入,请重新选择\n");
			break;
		}

	} while (choose);
	

}

前面的功能基本一直,按名索引查找被操作人所在位置

后面类比主函数功能,建立一个修改信息菜单。直接对通讯录里的信息修改

(6)sort函数排序
代码语言:javascript
复制
//sort排序功能(按照名字排升序)
void sort(Contact* p)
{
	assert(p);
	Contact temp;
	if (p->num == 0)
		printf("通讯录为空,无法排序!!\n");
	//冒泡排序
	int i = 0;
	int j = 0;
	for (i = 0; i < p->num; i++)
	{
		for (j = 0; j < p->num - i - 1; j++)
		{
			if (strcmp(p->date[j].name, p->date[j + 1].name) > 0)
			{
				temp.date[0] = p->date[i];
				p->date[i] = p->date[i + 1];
				p->date[i + 1] = temp.date[i];
			}

		}
	}
}

排序的选择有很多种,可以按年龄排序,也可以自己进行选择

四、代码汇总

contact.h

代码语言:javascript
复制
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>

#define nameMax  15
#define sexMax 5
#define numberMax 15
#define addrMax 20

//结构体定义,表示通讯录的每一页,包含了一个联系人的所有信息
typedef struct inform
{
	char name[nameMax];
	char sex[sexMax];
	int age;
	char number[numberMax];
	char addr[addrMax];

}inform;

//定义整本通讯录,能够存储100个人的信息和其通讯录所在位置
typedef struct Contact
{
	inform date[1000];
	int num;
}Contact;

enum
{
	Exit,
	Add,
	Del,
	Search,
	Modify,
	Show,
	Sort,
};

//初始化结构体
void initContact(Contact* p);


//加入联系人
void add(Contact* p);


//显示联系人
void show(Contact* p);


//删除联系人
void del(Contact* p);

//查找联系人
void search(Contact* p);

//对通讯录信息进行修改
void modify(Contact* p);

//sort排序功能
void sort(Contact* p);

contact.c

代码语言:javascript
复制
#include "contact.h"


void initContact(Contact* p)
{
	//先判断穿过来的指针是否为空
	assert(p);
	p->num = 0;
	memset(p->date,0,sizeof(p->date));
}






//新增联系人
void add(Contact* p)
{
	assert(p);
	//判断通讯录是否已经未满,如果num = 100则无法添加
	if (1000 == p->num)
	{
		printf("通讯录已满,无法进行添加\n");
		return ;
	}

	printf("请输入姓名:\n");
	scanf("%s",p->date[p->num].name);
	printf("请输入性别:\n");
	scanf("%s",p->date[p->num].sex);
	printf("请输入年龄:\n");
	scanf("%d",&(p->date[p->num].age));
	printf("请输入号码:\n");
	scanf("%s",p->date[p->num].number);
	printf("请输入地址:\n");
	scanf("%s",p->date[p->num].addr);
	p->num += 1;
	printf("联系人信息已添加完成!\n");

}






//展示通讯录信息
void show(Contact* p)
{
	assert(p);
	if (0 == p->num)
	{
		printf("没有可以显示的信息!\n");
		return ;
	}
	printf("%-15s %-5s %-5s %-15s %-20s\n",
		"姓名","性别","年龄","电话","地址");
	int i = 0;

	for (i = 0; i < p->num; i++)
	{
		printf("%-15s %-5s %-5d %-15s %-20s\n",
			p->date[i].name,
			p->date[i].sex,
			p->date[i].age,
			p->date[i].number,
			p->date[i].addr);
	}

}









//构建一个内部函数,用于实现按名查找
int findName(Contact* p , char name[])
{
	assert(p);
	int i = 0;
	//遍历通讯录,找到了返回是第几个联系人
	for (i = 0; i < p->num; i++)
	{
		if (0 == strcmp(p->date[i].name, name))
			return i;
	}
	//如果找不到返回 -1
	return -1;

}








//查找联系人的函数
void search(Contact* p)
{
	assert(p);
	char name[nameMax] ;
	if (p->num == 0)
	{
		printf("通讯录无数据可供查找!\n");
		printf("请从新进行操作!\n");
		return;
	}
	printf("请输入你要查找人的姓名:");
	scanf("%s",name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}
	printf("查找成功:\n");
	//显示查找的人的信息:
	printf("%-15s %-5s %-5s %-15s %-20s\n",
		"姓名", "性别", "年龄", "电话", "地址");
	printf("%-15s %-5s %-5d %-15s %-20s\n",
		p->date[pos].name, 
		p->date[pos].sex,
		p->date[pos].age,
		p->date[pos].number,
		p->date[pos].addr);
}









//删除联系人
void del(Contact* p)
{
	assert(p);
	char name[nameMax];

	if (p->num == 0)
	{
		printf("通讯录为空!!!\n");
		printf("请从新进行操作!\n");
		return;
	}

	printf("请输入你要删除人的姓名:");
	scanf("%s", name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}
	
	//删除
	int i = 0;
	for (i = pos; i < p->num; i++)	
	{
		p->date[i] = p->date[i + 1];	//同类型之间的变量可以进行赋值操作
	}
	p->num--;							//防止数组越界
	printf("清楚完毕!!\n");
}







//对通讯录信息进行修改
void modify(Contact* p)
{
	assert(p);
	char name[nameMax];

	if (p->num == 0)
	{
		printf("通讯录为空!!!\n");
		printf("请从新进行操作!\n");
		return;
	}

	printf("请输入你要修改人的姓名:");
	scanf("%s", name);
	//rer用来接收findName的返回值,即所查人所在的位置
	int pos = findName(p, name);

	//如果返回值为 -1 表示
	if (-1 == pos)
	{
		printf("没有找到这个人的信息!\n");
		return;
	}

	//修改:
	int choose = 0;
	do 
	{
		//选择修改菜单:
		printf("………………………………………………\n");
		printf("***   1.姓名        2.性别       ***\n");
		printf("***   3.年龄        4.号码       ***\n");
		printf("***   5.地址                     ***\n");
		printf("***   0.退出修改                 ***\n");
		printf("………………………………………………\n");

		printf("请输入你要修改的选项:>");
		scanf("%d", &choose);

		switch (choose)
		{
		case 1:
			printf("请输入修改后的姓名:");
			scanf("%s",p->date[pos].name);
			break;
		case 2:
			printf("请输入修改后的性别:");
			scanf("%s",p->date[pos].sex);
			break;
		case 3:
			printf("请输入修改后的年龄:");
			scanf("%d",p->date[pos].age);
			break;
		case 4:
			printf("请输入修改后的号码:");
			scanf("%s",p->date[pos].number);
			break;
		case 5:
			printf("请输入修改后的地址:");
			scanf("%s",p->date[pos].addr);
			break;
		case 0:
			printf("修改成功!!!\n");
			break;
		default :
			printf("非法字符输入,请重新选择\n");
			break;
		}

	} while (choose);
	

}





//sort排序功能(按照名字排升序)
void sort(Contact* p)
{
	assert(p);
	Contact temp;
	if (p->num == 0)
		printf("通讯录为空,无法排序!!\n");
	//冒泡排序
	int i = 0;
	int j = 0;
	for (i = 0; i < p->num; i++)
	{
		for (j = 0; j < p->num - i - 1; j++)
		{
			if (strcmp(p->date[j].name, p->date[j + 1].name) > 0)
			{
				temp.date[0] = p->date[i];
				p->date[i] = p->date[i + 1];
				p->date[i + 1] = temp.date[i];
			}

		}
	}
}

test.c

代码语言:javascript
复制
#include "contact.h"

void meanu()
{
	printf("**********************************\n");
	printf("***   1.add         2.del      ***\n");
	printf("***   3.search      4.modify   ***\n");
	printf("***   5.show        6.sort     ***\n");
	printf("***   0.exit                   ***\n");
	printf("**********************************\n");
}
int main()
{
	int input = 0;
	//创建通讯录
	Contact contact;
	//注意:结构体类型创建的时候初始值是一个随机值,不是0,
	//需要对结构体进行初始化
	initContact(&contact);

	do 
	{
		meanu();
		scanf("%d", &input);
		switch (input)
		{

		case Add:
			add(&contact);
			break;
		case Del:
			del(&contact);
			break;
		case Search:
			search(&contact);
			break;
		case Modify:
			modify(&contact);
			break;
		case Show:
			show(&contact);
			break;
		case Sort:
			break;
		case Exit:
			printf("退出成功!!!\n");
			break;
		default:
			printf("您输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

五、反思和总结

这里只是一个简单的C语言项目,里面还有很多可以改进的地方。 如:

  • 排序函数是否可以用qsort函数?
  • 通讯录结构体是否可以使用动态内存管理?
  • 如何添加文件功能? 这些都是值得去进一步学习和改进的地方。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C语言通讯录功能的实现
    • 一、项目需求:
      • 二、模块化代码
        • 三、整体思路
          • 1.创建结构体类型
          • 2.建立循环
          • 3.各个功能的实现
        • 四、代码汇总
          • 五、反思和总结
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档